mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
@@ -66,6 +66,7 @@
|
||||
"temp": "0.8.1",
|
||||
"text-buffer": "^5.1.0",
|
||||
"theorist": "^1.0.2",
|
||||
"typescript-simple": "^1.0.0",
|
||||
"underscore-plus": "^1.6.6"
|
||||
},
|
||||
"packageDependencies": {
|
||||
|
||||
@@ -3,26 +3,37 @@ CSON = require 'season'
|
||||
CoffeeCache = require 'coffee-cash'
|
||||
|
||||
babel = require '../src/babel'
|
||||
typescript = require '../src/typescript'
|
||||
CompileCache = require '../src/compile-cache'
|
||||
|
||||
describe "Compile Cache", ->
|
||||
describe ".addPathToCache(filePath)", ->
|
||||
it "adds the path to the correct CSON, CoffeeScript, or babel cache", ->
|
||||
it "adds the path to the correct CSON, CoffeeScript, babel or typescript cache", ->
|
||||
spyOn(CSON, 'readFileSync').andCallThrough()
|
||||
spyOn(CoffeeCache, 'addPathToCache').andCallThrough()
|
||||
spyOn(babel, 'addPathToCache').andCallThrough()
|
||||
spyOn(typescript, 'addPathToCache').andCallThrough()
|
||||
|
||||
CompileCache.addPathToCache(path.join(__dirname, 'fixtures', 'cson.cson'))
|
||||
expect(CSON.readFileSync.callCount).toBe 1
|
||||
expect(CoffeeCache.addPathToCache.callCount).toBe 0
|
||||
expect(babel.addPathToCache.callCount).toBe 0
|
||||
expect(typescript.addPathToCache.callCount).toBe 0
|
||||
|
||||
CompileCache.addPathToCache(path.join(__dirname, 'fixtures', 'coffee.coffee'))
|
||||
expect(CSON.readFileSync.callCount).toBe 1
|
||||
expect(CoffeeCache.addPathToCache.callCount).toBe 1
|
||||
expect(babel.addPathToCache.callCount).toBe 0
|
||||
expect(typescript.addPathToCache.callCount).toBe 0
|
||||
|
||||
CompileCache.addPathToCache(path.join(__dirname, 'fixtures', 'babel', 'babel-double-quotes.js'))
|
||||
expect(CSON.readFileSync.callCount).toBe 1
|
||||
expect(CoffeeCache.addPathToCache.callCount).toBe 1
|
||||
expect(babel.addPathToCache.callCount).toBe 1
|
||||
expect(typescript.addPathToCache.callCount).toBe 0
|
||||
|
||||
CompileCache.addPathToCache(path.join(__dirname, 'fixtures', 'typescript', 'valid.ts'))
|
||||
expect(CSON.readFileSync.callCount).toBe 1
|
||||
expect(CoffeeCache.addPathToCache.callCount).toBe 1
|
||||
expect(babel.addPathToCache.callCount).toBe 1
|
||||
expect(typescript.addPathToCache.callCount).toBe 1
|
||||
|
||||
1
spec/fixtures/typescript/invalid.ts
vendored
Normal file
1
spec/fixtures/typescript/invalid.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
var foo = 123 123; // Syntax error
|
||||
2
spec/fixtures/typescript/valid.ts
vendored
Normal file
2
spec/fixtures/typescript/valid.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
var inc = v => v + 1
|
||||
export = inc
|
||||
30
spec/typescript-spec.coffee
Normal file
30
spec/typescript-spec.coffee
Normal file
@@ -0,0 +1,30 @@
|
||||
typescript = require '../src/typescript'
|
||||
crypto = require 'crypto'
|
||||
|
||||
describe "TypeScript transpiler support", ->
|
||||
describe "::createTypeScriptVersionAndOptionsDigest", ->
|
||||
it "returns a digest for the library version and specified options", ->
|
||||
defaultOptions =
|
||||
target: 1 # ES5
|
||||
module: 'commonjs'
|
||||
sourceMap: true
|
||||
version = '1.4.1'
|
||||
shasum = crypto.createHash('sha1')
|
||||
shasum.update('typescript', 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
shasum.update(version, 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
shasum.update(JSON.stringify(defaultOptions))
|
||||
expectedDigest = shasum.digest('hex')
|
||||
|
||||
observedDigest = typescript.createTypeScriptVersionAndOptionsDigest(version, defaultOptions)
|
||||
expect(observedDigest).toEqual expectedDigest
|
||||
|
||||
describe "when there is a .ts file", ->
|
||||
it "transpiles it using typescript", ->
|
||||
transpiled = require('./fixtures/typescript/valid.ts')
|
||||
expect(transpiled(3)).toBe 4
|
||||
|
||||
describe "when the .ts file is invalid", ->
|
||||
it "does not transpile", ->
|
||||
expect(-> require('./fixtures/typescript/invalid.ts')).toThrow()
|
||||
@@ -2,6 +2,7 @@ path = require 'path'
|
||||
CSON = require 'season'
|
||||
CoffeeCache = require 'coffee-cash'
|
||||
babel = require './babel'
|
||||
typescript = require './typescript'
|
||||
|
||||
# This file is required directly by apm so that files can be cached during
|
||||
# package install so that the first package load in Atom doesn't have to
|
||||
@@ -16,6 +17,7 @@ exports.addPathToCache = (filePath, atomHome) ->
|
||||
CoffeeCache.setCacheDirectory(path.join(cacheDir, 'coffee'))
|
||||
CSON.setCacheDir(path.join(cacheDir, 'cson'))
|
||||
babel.setCacheDirectory(path.join(cacheDir, 'js', 'babel'))
|
||||
typescript.setCacheDirectory(path.join(cacheDir, 'ts'))
|
||||
|
||||
switch path.extname(filePath)
|
||||
when '.coffee'
|
||||
@@ -24,3 +26,5 @@ exports.addPathToCache = (filePath, atomHome) ->
|
||||
CSON.readFileSync(filePath)
|
||||
when '.js'
|
||||
babel.addPathToCache(filePath)
|
||||
when '.ts'
|
||||
typescript.addPathToCache(filePath)
|
||||
|
||||
104
src/typescript.coffee
Normal file
104
src/typescript.coffee
Normal file
@@ -0,0 +1,104 @@
|
||||
###
|
||||
Cache for source code transpiled by TypeScript.
|
||||
|
||||
Inspired by https://github.com/atom/atom/blob/7a719d585db96ff7d2977db9067e1d9d4d0adf1a/src/babel.coffee
|
||||
###
|
||||
|
||||
crypto = require 'crypto'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
tss = null # Defer until used
|
||||
|
||||
stats =
|
||||
hits: 0
|
||||
misses: 0
|
||||
|
||||
defaultOptions =
|
||||
target: 1 # ES5
|
||||
module: 'commonjs'
|
||||
sourceMap: true
|
||||
|
||||
createTypeScriptVersionAndOptionsDigest = (version, options) ->
|
||||
shasum = crypto.createHash('sha1')
|
||||
# Include the version of typescript in the hash.
|
||||
shasum.update('typescript', 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
shasum.update(version, 'utf8')
|
||||
shasum.update('\0', 'utf8')
|
||||
shasum.update(JSON.stringify(options))
|
||||
shasum.digest('hex')
|
||||
|
||||
cacheDir = null
|
||||
jsCacheDir = null
|
||||
|
||||
getCachePath = (sourceCode) ->
|
||||
digest = crypto.createHash('sha1').update(sourceCode, 'utf8').digest('hex')
|
||||
|
||||
unless jsCacheDir?
|
||||
tssVersion = require('typescript-simple/package.json').version
|
||||
jsCacheDir = path.join(cacheDir, createTypeScriptVersionAndOptionsDigest(tssVersion, defaultOptions))
|
||||
|
||||
path.join(jsCacheDir, "#{digest}.js")
|
||||
|
||||
getCachedJavaScript = (cachePath) ->
|
||||
if fs.isFileSync(cachePath)
|
||||
try
|
||||
cachedJavaScript = fs.readFileSync(cachePath, 'utf8')
|
||||
stats.hits++
|
||||
return cachedJavaScript
|
||||
null
|
||||
|
||||
# Returns the TypeScript options that should be used to transpile filePath.
|
||||
createOptions = (filePath) ->
|
||||
options = filename: filePath
|
||||
for key, value of defaultOptions
|
||||
options[key] = value
|
||||
options
|
||||
|
||||
transpile = (sourceCode, filePath, cachePath) ->
|
||||
options = createOptions(filePath)
|
||||
tss ?= new (require 'typescript-simple').TypeScriptSimple(options, false)
|
||||
js = tss.compile(sourceCode, filePath)
|
||||
stats.misses++
|
||||
|
||||
try
|
||||
fs.writeFileSync(cachePath, js)
|
||||
|
||||
js
|
||||
|
||||
# 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')
|
||||
cachePath = getCachePath(sourceCode)
|
||||
js = getCachedJavaScript(cachePath) ? transpile(sourceCode, filePath, cachePath)
|
||||
module._compile(js, filePath)
|
||||
|
||||
register = ->
|
||||
Object.defineProperty(require.extensions, '.ts', {
|
||||
enumerable: true
|
||||
writable: false
|
||||
value: loadFile
|
||||
})
|
||||
|
||||
setCacheDirectory = (newCacheDir) ->
|
||||
if cacheDir isnt newCacheDir
|
||||
cacheDir = newCacheDir
|
||||
jsCacheDir = null
|
||||
|
||||
module.exports =
|
||||
register: register
|
||||
setCacheDirectory: setCacheDirectory
|
||||
getCacheMisses: -> stats.misses
|
||||
getCacheHits: -> stats.hits
|
||||
|
||||
# Visible for testing.
|
||||
createTypeScriptVersionAndOptionsDigest: createTypeScriptVersionAndOptionsDigest
|
||||
|
||||
addPathToCache: (filePath) ->
|
||||
return if path.extname(filePath) isnt '.ts'
|
||||
|
||||
sourceCode = fs.readFileSync(filePath, 'utf8')
|
||||
cachePath = getCachePath(sourceCode)
|
||||
transpile(sourceCode, filePath, cachePath)
|
||||
@@ -47,6 +47,7 @@ window.onload = function() {
|
||||
setupCsonCache(cacheDir);
|
||||
setupSourceMapCache(cacheDir);
|
||||
setupBabel(cacheDir);
|
||||
setupTypeScript(cacheDir);
|
||||
|
||||
require(loadSettings.bootstrapScript);
|
||||
require('ipc').sendChannel('window-command', 'window:loaded');
|
||||
@@ -95,6 +96,12 @@ var setupBabel = function(cacheDir) {
|
||||
babel.register();
|
||||
}
|
||||
|
||||
var setupTypeScript = function(cacheDir) {
|
||||
var typescript = require('../src/typescript');
|
||||
typescript.setCacheDirectory(path.join(cacheDir, 'typescript'));
|
||||
typescript.register();
|
||||
}
|
||||
|
||||
var setupCsonCache = function(cacheDir) {
|
||||
require('season').setCacheDir(path.join(cacheDir, 'cson'));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user