Transpile all .js files with 6to5.
In the spirit of supporting JavaScript development for Atom packages,
this adds default support for es.next transpilation support in the way
that Atom already has default support for CoffeeScript transpilation.
There are many new features in ES6+ that make JavaScript development
easier and more enjoyable, particularly in terms of support for async code.
For reference, this was a much faster way to iterate on this than running `./script/build`
each time:
```
cp /Users/mbolin/src/atom/static/index.js /Applications/Atom.app/Contents/Resources/app/static/index.js
coffee --output /Applications/Atom.app/Contents/Resources/app/src --compile /Users/mbolin/src/atom/src/esnext.coffee
```
Run the following in the console to see how warm the cache was after startup:
```
global.require('../src/esnext/').getCacheHits()
global.require('../src/esnext/').getCacheMisses()
```
Esse commit está contido em:
@@ -19,6 +19,7 @@
|
||||
],
|
||||
"atomShellVersion": "0.21.0",
|
||||
"dependencies": {
|
||||
"6to5-core": "3.0.14",
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^3.1.0",
|
||||
"bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{create6to5VersionAndOptionsDigest} = require '../src/esnext'
|
||||
crypto = require 'crypto'
|
||||
|
||||
describe "esnext", ->
|
||||
|
||||
it "::create6to5VersionAndOptionsDigest", ->
|
||||
defaultOptions =
|
||||
'blacklist': [
|
||||
'useStrict'
|
||||
]
|
||||
'experimental': true,
|
||||
'optional': [
|
||||
'asyncToGenerator'
|
||||
]
|
||||
'reactCompat': true
|
||||
'sourceMap': 'inline'
|
||||
version = '3.0.14'
|
||||
shasum = crypto.createHash('sha1')
|
||||
shasum.update('6to5-core', 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
shasum.update(version, 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
shasum.update('{"blacklist": ["useStrict",],"experimental": true,"optional": ["asyncToGenerator",],"reactCompat": true,"sourceMap": "inline",}')
|
||||
expectedDigest = shasum.digest('hex')
|
||||
|
||||
observedDigest = create6to5VersionAndOptionsDigest(version, defaultOptions)
|
||||
expect(observedDigest).toEqual(expectedDigest)
|
||||
@@ -0,0 +1,157 @@
|
||||
###
|
||||
Cache for source code transpiled by 6to5.
|
||||
|
||||
Inspired by https://github.com/atom/atom/blob/6b963a562f8d495fbebe6abdbafbc7caf705f2c3/src/coffee-cache.coffee.
|
||||
###
|
||||
|
||||
crypto = require 'crypto'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path';
|
||||
to5 = require '6to5-core'
|
||||
|
||||
stats =
|
||||
hits: 0
|
||||
misses: 0
|
||||
|
||||
defaultOptions =
|
||||
# The Chrome dev tools will show the original version of the file
|
||||
# when the source map is inlined.
|
||||
'sourceMap': 'inline'
|
||||
|
||||
# Because Atom is currently packaged with a fork of React v0.11,
|
||||
# it makes sense to use the --react-compat option so the React
|
||||
# JSX transformer produces pre-v0.12 code.
|
||||
'reactCompat': true
|
||||
|
||||
# Blacklisted features do not get transpiled. Features that are
|
||||
# natively supported in the target environment should be listed
|
||||
# here. Because Atom uses a bleeding edge version of Node/io.js,
|
||||
# I think this can include es6.arrowFunctions, es6.classes, and
|
||||
# possibly others, but I want to be conservative.
|
||||
'blacklist': [
|
||||
'useStrict'
|
||||
]
|
||||
|
||||
# Includes support for es7 features listed at:
|
||||
# http://6to5.org/docs/usage/transformers/#es7-experimental-.
|
||||
'experimental': true,
|
||||
|
||||
'optional': [
|
||||
# Target a version of the regenerator runtime that
|
||||
# supports yield so the transpiled code is cleaner/smaller.
|
||||
'asyncToGenerator'
|
||||
]
|
||||
|
||||
###
|
||||
shasum - Hash with an update() method.
|
||||
value - Must be a value that could be returned by JSON.parse().
|
||||
###
|
||||
updateDigestForJsonValue = (shasum, value) ->
|
||||
# Implmentation is similar to that of pretty-printing a JSON object, except:
|
||||
# * Strings are not escaped.
|
||||
# * No effort is made to avoid trailing commas.
|
||||
# These shortcuts should not affect the correctness of this function.
|
||||
if typeof value is 'string'
|
||||
shasum.update('"', 'utf8')
|
||||
shasum.update(value, 'utf8')
|
||||
shasum.update('"', 'utf8')
|
||||
else if typeof value is 'boolean' or typeof value is 'number'
|
||||
shasum.update(value.toString(), 'utf8')
|
||||
else if typeof value is null
|
||||
shasum.update('null', 'utf8')
|
||||
else if Array.isArray value
|
||||
shasum.update('[', 'utf8')
|
||||
for item in value
|
||||
updateDigestForJsonValue(shasum, item)
|
||||
shasum.update(',', 'utf8')
|
||||
shasum.update(']', 'utf8')
|
||||
else
|
||||
# Must be an object: be sure to sort the keys.
|
||||
keys = []
|
||||
for key of value
|
||||
keys.push(key)
|
||||
keys.sort()
|
||||
|
||||
shasum.update('{', 'utf8')
|
||||
for key in keys
|
||||
updateDigestForJsonValue(shasum, key)
|
||||
shasum.update(': ', 'utf8')
|
||||
updateDigestForJsonValue(shasum, value[key])
|
||||
shasum.update(',', 'utf8')
|
||||
shasum.update('}', 'utf8')
|
||||
|
||||
create6to5VersionAndOptionsDigest = (version, options) ->
|
||||
shasum = crypto.createHash('sha1')
|
||||
# Include the version of 6to5 in the hash.
|
||||
shasum.update('6to5-core', 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
shasum.update(version, 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
updateDigestForJsonValue(shasum, options)
|
||||
return shasum.digest('hex')
|
||||
|
||||
cacheDir = path.join(fs.absolute('~/.atom'), 'compile-cache')
|
||||
jsCacheDir = path.join(
|
||||
cacheDir,
|
||||
create6to5VersionAndOptionsDigest(to5.version, defaultOptions),
|
||||
'js')
|
||||
|
||||
getCachePath = (sourceCode) ->
|
||||
digest = crypto.createHash('sha1').update(sourceCode, 'utf8').digest('hex')
|
||||
return path.join(jsCacheDir, "#{digest}.js")
|
||||
|
||||
getCachedJavaScript = (cachePath) ->
|
||||
if fs.isFileSync(cachePath)
|
||||
try
|
||||
cachedJavaScript = fs.readFileSync(cachePath, 'utf8')
|
||||
stats.hits++
|
||||
return cachedJavaScript
|
||||
return null
|
||||
|
||||
# Returns the 6to5 options that should be used to transpile filePath.
|
||||
createOptions = (filePath) ->
|
||||
options =
|
||||
'filename': filePath
|
||||
for key, value of defaultOptions
|
||||
options[key] = value
|
||||
return options
|
||||
|
||||
# Function that obeys the contract of an entry in the require.extensions map.
|
||||
# Returns the transpiled version of the JavaScript code at filePath, which is
|
||||
# either generated on the fly or pulled from cache.
|
||||
loadFile = (module, filePath) ->
|
||||
sourceCode = fs.readFileSync(filePath, 'utf8')
|
||||
if not (sourceCode.startsWith('"use 6to5"') or sourceCode.startsWith("'use 6to5'"))
|
||||
module._compile(sourceCode, filePath)
|
||||
return
|
||||
|
||||
cachePath = getCachePath(sourceCode)
|
||||
js = getCachedJavaScript(cachePath)
|
||||
|
||||
unless js
|
||||
options = createOptions filePath
|
||||
try
|
||||
js = to5.transform(sourceCode, options).code
|
||||
stats.misses++
|
||||
catch error
|
||||
console.error('Error compiling %s: %o', filePath, error)
|
||||
throw error
|
||||
|
||||
try
|
||||
fs.writeFileSync(cachePath, js)
|
||||
catch error
|
||||
console.error('Error writing to cache at %s: %o', cachePath, error)
|
||||
throw error
|
||||
|
||||
module._compile(js, filePath)
|
||||
|
||||
register = (appVersion) ->
|
||||
require.extensions['.js'] = loadFile
|
||||
|
||||
module.exports =
|
||||
register: register
|
||||
getCacheMisses: -> stats.misses
|
||||
getCacheHits: -> stats.hits
|
||||
|
||||
# Visible for testing.
|
||||
create6to5VersionAndOptionsDigest: create6to5VersionAndOptionsDigest
|
||||
+10
-2
@@ -1,3 +1,11 @@
|
||||
function registerRuntimeTranspilers() {
|
||||
// This sets require.extensions['.coffee'].
|
||||
require('coffee-script').register();
|
||||
|
||||
// This redefines require.extensions['.js'].
|
||||
require('../src/esnext').register();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
try {
|
||||
var startTime = Date.now();
|
||||
@@ -22,7 +30,7 @@ window.onload = function() {
|
||||
|
||||
// Require before the module cache in dev mode
|
||||
if (devMode) {
|
||||
require('coffee-script').register();
|
||||
registerRuntimeTranspilers();
|
||||
}
|
||||
|
||||
ModuleCache = require('../src/module-cache');
|
||||
@@ -41,7 +49,7 @@ window.onload = function() {
|
||||
require('vm-compatibility-layer');
|
||||
|
||||
if (!devMode) {
|
||||
require('coffee-script').register();
|
||||
registerRuntimeTranspilers();
|
||||
}
|
||||
|
||||
require('../src/coffee-cache').register();
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário