From ad448184b4eefb647249209a75a4cf981be7fa60 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 14:30:24 -0700 Subject: [PATCH 01/23] First pass at per-package transpilation --- src/compile-cache.js | 18 +++- src/package-transpilation-registry.js | 122 ++++++++++++++++++++++++++ src/package.coffee | 15 ++++ 3 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 src/package-transpilation-registry.js diff --git a/src/compile-cache.js b/src/compile-cache.js index ad1bd0a85..702b2659f 100644 --- a/src/compile-cache.js +++ b/src/compile-cache.js @@ -7,12 +7,24 @@ var path = require('path') var fs = require('fs-plus') + +var PackageTranspilationRegistry = require('./package-transpilation-registry') var CSON = null +var packageTranspilationRegistry = new PackageTranspilationRegistry() + var COMPILERS = { - '.js': require('./babel'), - '.ts': require('./typescript'), - '.coffee': require('./coffee-script') + '.js': packageTranspilationRegistry.wrapTranspiler(require('./babel')), + '.ts': packageTranspilationRegistry.wrapTranspiler(require('./typescript')), + '.coffee': packageTranspilationRegistry.wrapTranspiler(require('./coffee-script')) +} + +exports.addTranspilerConfigForPath = function (packagePath, config) { + packageTranspilationRegistry.addTranspilerConfigForPath(packagePath, config) +} + +exports.removeTranspilerConfigForPath = function (packagePath) { + packageTranspilationRegistry.removeTranspilerConfigForPath(packagePath) } var cacheStats = {} diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js new file mode 100644 index 000000000..caf83961e --- /dev/null +++ b/src/package-transpilation-registry.js @@ -0,0 +1,122 @@ +var crypto = require('crypto') +var fs = require('fs') +var path = require('path') + +var Resolve = null + +function PackageTranspilationRegistry () { + this.configByPackagePath = {} + this.configByFilePath = {} + this.transpilerPaths = {} + this.transpilerHashes = {} +} + +PackageTranspilationRegistry.prototype.addTranspilerConfigForPath = function (packagePath, config) { + packagePath = fs.realpathSync(packagePath) + this.configByPackagePath[packagePath] = Object.assign({}, config, { + path: packagePath + }) +} + +PackageTranspilationRegistry.prototype.removeTranspilerConfigForPath = function (packagePath) { + packagePath = fs.realpathSync(packagePath) + delete this.configByPackagePath[path] +} + +// Wraps the transpiler in an object with the same interface +// that falls back to the original transpiler implementation if and +// only if a package hasn't registered its desire to transpile its own source. +PackageTranspilationRegistry.prototype.wrapTranspiler = function (transpiler) { + var self = this + return { + getCachePath: function (sourceCode, filePath) { + var config = self.getPackageTranspilerConfigForFilePath(filePath) + if (config) { + return self.getCachePath(sourceCode, filePath, config) + } + + return transpiler.getCachePath(sourceCode, filePath) + }, + + compile: function (sourceCode, filePath) { + var config = self.getPackageTranspilerConfigForFilePath(filePath) + if (config) { + return self.transpileWithPackageTranspiler(sourceCode, filePath, config) + } + + return transpiler.compile(sourceCode, filePath) + }, + + shouldCompile: function (sourceCode, filePath) { + if (self.transpilerPaths[filePath]) { + return false + } + var config = self.getPackageTranspilerConfigForFilePath(filePath) + if (config) { + return true + } + + return transpiler.shouldCompile(sourceCode, filePath) + } + } +} + +PackageTranspilationRegistry.prototype.getPackageTranspilerConfigForFilePath = function (filePath) { + if (this.configByFilePath[filePath] !== undefined) return this.configByFilePath[filePath] + + var config = null + var thisPath = filePath + var lastPath = null + // Iterate parents from the file path to the root, checking at each level + // to see if a package manages transpilation for that directory. + // This means searching for a config for `/path/to/file/here.js` only + // only iterates four times, even if there are hundreds of configs registered. + while (thisPath !== lastPath) { // until we reach the root + if (config = this.configByPackagePath[thisPath]) { + this.configByFilePath[filePath] = config + return config + } + + lastPath = thisPath + thisPath = path.resolve(thisPath, '..') + } + + this.configByFilePath[filePath] = null + return null +} + +PackageTranspilationRegistry.prototype.getCachePath = function (sourceCode, filePath, config) { + var transpilerPath = path.join(config.path, config.transpiler) + var transpilerSource = config._transpilerSource || fs.readFileSync(transpilerPath, 'utf8') + config._transpilerSource = transpilerSource + return path.join( + "package-transpile", + crypto + .createHash('sha1') + .update(transpilerSource, 'utf8') + .update(sourceCode, 'utf8') + .digest('hex') + ) +} + +PackageTranspilationRegistry.prototype.transpileWithPackageTranspiler = function (sourceCode, filePath) { + var config = this.configByFilePath[filePath] + + Resolve = Resolve || require('resolve') + var transpilerPath = Resolve.sync(config.transpiler, {basedir: config.path, extensions: Object.keys(require.extensions)}) + if (transpilerPath) { + this.transpilerPaths[transpilerPath] = true + var transpiler = require(transpilerPath) + var result = transpiler.compile(sourceCode, filePath) + if (result === undefined) { + return sourceCode + } else { + return result + } + } else { + var err = new Error("Could not find transpiler '" + config.transpiler + "' from '" + config.path + "'") + console.error(err) + } +} + +module.exports = PackageTranspilationRegistry diff --git a/src/package.coffee b/src/package.coffee index 323dfa8d2..10764460f 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -6,6 +6,7 @@ CSON = require 'season' fs = require 'fs-plus' {Emitter, CompositeDisposable} = require 'event-kit' +CompileCache = require './compile-cache' ModuleCache = require './module-cache' ScopedProperties = require './scoped-properties' BufferedProcess = require './buffered-process' @@ -86,6 +87,7 @@ class Package @loadStylesheets() @registerDeserializerMethods() @activateCoreStartupServices() + @registerTranspilerConfig() @configSchemaRegisteredOnLoad = @registerConfigSchemaFromMetadata() @settingsPromise = @loadSettings() if @shouldRequireMainModuleOnLoad() and not @mainModule? @@ -94,6 +96,9 @@ class Package @handleError("Failed to load the #{@name} package", error) this + unload: -> + @unregisterTranspilerConfig() + shouldRequireMainModuleOnLoad: -> not ( @metadata.deserializers? or @@ -247,6 +252,16 @@ class Package @activationDisposables.add @packageManager.serviceHub.consume(name, version, @mainModule[methodName].bind(@mainModule)) return + registerTranspilerConfig: -> + if @metadata.atomTranspilers + for transpiler in @metadata.atomTranspilers + CompileCache.addTranspilerConfigForPath(@path, transpiler) + + unregisterTranspilerConfig: -> + if @metadata.atomTranspilers + for transpiler in @metadata.atomTranspilers + CompileCache.removeTranspilerConfigForPath(@path) + loadKeymaps: -> if @bundledPackage and @packageManager.packagesCache[@name]? @keymaps = (["#{@packageManager.resourcePath}#{path.sep}#{keymapPath}", keymapObject] for keymapPath, keymapObject of @packageManager.packagesCache[@name].keymaps) From 4f7b22c84edd00de5718dbca0158cdb6b99077f2 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 14:38:25 -0700 Subject: [PATCH 02/23] Pass config options to package transpilers --- src/package-transpilation-registry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index caf83961e..a2b2ae3aa 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -107,7 +107,7 @@ PackageTranspilationRegistry.prototype.transpileWithPackageTranspiler = function if (transpilerPath) { this.transpilerPaths[transpilerPath] = true var transpiler = require(transpilerPath) - var result = transpiler.compile(sourceCode, filePath) + var result = transpiler.compile(sourceCode, filePath, config.options || {}) if (result === undefined) { return sourceCode } else { From b11194102227de817fbbdb97985afb9175493302 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 15:18:34 -0700 Subject: [PATCH 03/23] Implement glob checking and multiple transpilers --- package.json | 1 + src/package-transpilation-registry.js | 212 ++++++++++++++------------ src/package.coffee | 6 +- 3 files changed, 119 insertions(+), 100 deletions(-) diff --git a/package.json b/package.json index 8731dceca..44c984e27 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "less-cache": "0.23", "line-top-index": "0.2.0", "marked": "^0.3.6", + "minimatch": "^3.0.3", "mocha": "2.5.1", "normalize-package-data": "^2.0.0", "nslog": "^3", diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index a2b2ae3aa..64c136f2c 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -2,121 +2,141 @@ var crypto = require('crypto') var fs = require('fs') var path = require('path') +var minimatch = require('minimatch') + var Resolve = null function PackageTranspilationRegistry () { this.configByPackagePath = {} - this.configByFilePath = {} + this.specByFilePath = {} this.transpilerPaths = {} this.transpilerHashes = {} } -PackageTranspilationRegistry.prototype.addTranspilerConfigForPath = function (packagePath, config) { - packagePath = fs.realpathSync(packagePath) - this.configByPackagePath[packagePath] = Object.assign({}, config, { - path: packagePath - }) -} - -PackageTranspilationRegistry.prototype.removeTranspilerConfigForPath = function (packagePath) { - packagePath = fs.realpathSync(packagePath) - delete this.configByPackagePath[path] -} - -// Wraps the transpiler in an object with the same interface -// that falls back to the original transpiler implementation if and -// only if a package hasn't registered its desire to transpile its own source. -PackageTranspilationRegistry.prototype.wrapTranspiler = function (transpiler) { - var self = this - return { - getCachePath: function (sourceCode, filePath) { - var config = self.getPackageTranspilerConfigForFilePath(filePath) - if (config) { - return self.getCachePath(sourceCode, filePath, config) - } - - return transpiler.getCachePath(sourceCode, filePath) - }, - - compile: function (sourceCode, filePath) { - var config = self.getPackageTranspilerConfigForFilePath(filePath) - if (config) { - return self.transpileWithPackageTranspiler(sourceCode, filePath, config) - } - - return transpiler.compile(sourceCode, filePath) - }, - - shouldCompile: function (sourceCode, filePath) { - if (self.transpilerPaths[filePath]) { - return false - } - var config = self.getPackageTranspilerConfigForFilePath(filePath) - if (config) { - return true - } - - return transpiler.shouldCompile(sourceCode, filePath) +Object.assign(PackageTranspilationRegistry.prototype, { + addTranspilerConfigForPath: function (packagePath, config) { + packagePath = fs.realpathSync(packagePath) + this.configByPackagePath[packagePath] = { + specs: config, + path: packagePath } - } -} + console.debug(">> adding", this.configByPackagePath[packagePath]) + }, -PackageTranspilationRegistry.prototype.getPackageTranspilerConfigForFilePath = function (filePath) { - if (this.configByFilePath[filePath] !== undefined) return this.configByFilePath[filePath] + removeTranspilerConfigForPath: function (packagePath) { + packagePath = fs.realpathSync(packagePath) + delete this.configByPackagePath[packagePath] + }, - var config = null - var thisPath = filePath - var lastPath = null - // Iterate parents from the file path to the root, checking at each level - // to see if a package manages transpilation for that directory. - // This means searching for a config for `/path/to/file/here.js` only - // only iterates four times, even if there are hundreds of configs registered. - while (thisPath !== lastPath) { // until we reach the root - if (config = this.configByPackagePath[thisPath]) { - this.configByFilePath[filePath] = config - return config + // Wraps the transpiler in an object with the same interface + // that falls back to the original transpiler implementation if and + // only if a package hasn't registered its desire to transpile its own source. + wrapTranspiler: function (transpiler) { + var self = this + return { + getCachePath: function (sourceCode, filePath) { + var spec = self.getPackageTranspilerSpecForFilePath(filePath) + if (spec) { + return self.getCachePath(sourceCode, filePath, spec) + } + + return transpiler.getCachePath(sourceCode, filePath) + }, + + compile: function (sourceCode, filePath) { + var spec = self.getPackageTranspilerSpecForFilePath(filePath) + if (spec) { + return self.transpileWithPackageTranspiler(sourceCode, filePath, spec) + } + + return transpiler.compile(sourceCode, filePath) + }, + + shouldCompile: function (sourceCode, filePath) { + if (self.transpilerPaths[filePath]) { + return false + } + var spec = self.getPackageTranspilerSpecForFilePath(filePath) + if (spec) { + return true + } + + return transpiler.shouldCompile(sourceCode, filePath) + } + } + }, + + getPackageTranspilerSpecForFilePath: function (filePath) { + if (this.specByFilePath[filePath] !== undefined) return this.specByFilePath[filePath] + + var config = null + var spec = null + var thisPath = filePath + var lastPath = null + // Iterate parents from the file path to the root, checking at each level + // to see if a package manages transpilation for that directory. + // This means searching for a config for `/path/to/file/here.js` only + // only iterates four times, even if there are hundreds of configs registered. + while (thisPath !== lastPath) { // until we reach the root + if (config = this.configByPackagePath[thisPath]) { + console.log('got one') + for (var i = 0; i < config.specs.length; i++) { + spec = config.specs[i] + console.log("checking", filePath, "against", path.join(config.path, spec.glob)) + if (minimatch(filePath, path.join(config.path, spec.glob))) { + spec._config = config + this.specByFilePath[filePath] = spec + return spec + } + } + } + + lastPath = thisPath + thisPath = path.resolve(thisPath, '..') } - lastPath = thisPath - thisPath = path.resolve(thisPath, '..') - } + this.specByFilePath[filePath] = null + return null + }, - this.configByFilePath[filePath] = null - return null -} + getCachePath: function (sourceCode, filePath, spec) { + var transpilerPath = path.join(spec._config.path, spec.transpiler) + var transpilerSource = spec._transpilerSource || fs.readFileSync(transpilerPath, 'utf8') + spec._transpilerSource = transpilerSource + return path.join( + "package-transpile", + crypto + .createHash('sha1') + .update(JSON.stringify(spec.options || {})) + .update(transpilerSource, 'utf8') + .update(sourceCode, 'utf8') + .digest('hex') + ) + }, -PackageTranspilationRegistry.prototype.getCachePath = function (sourceCode, filePath, config) { - var transpilerPath = path.join(config.path, config.transpiler) - var transpilerSource = config._transpilerSource || fs.readFileSync(transpilerPath, 'utf8') - config._transpilerSource = transpilerSource - return path.join( - "package-transpile", - crypto - .createHash('sha1') - .update(transpilerSource, 'utf8') - .update(sourceCode, 'utf8') - .digest('hex') - ) -} + transpileWithPackageTranspiler: function (sourceCode, filePath, spec) { + var spec = this.specByFilePath[filePath] -PackageTranspilationRegistry.prototype.transpileWithPackageTranspiler = function (sourceCode, filePath) { - var config = this.configByFilePath[filePath] + Resolve = Resolve || require('resolve') + var transpilerPath = Resolve.sync(spec.transpiler, { + basedir: spec._config.path, + extensions: Object.keys(require.extensions) + }) - Resolve = Resolve || require('resolve') - var transpilerPath = Resolve.sync(config.transpiler, {basedir: config.path, extensions: Object.keys(require.extensions)}) - if (transpilerPath) { - this.transpilerPaths[transpilerPath] = true - var transpiler = require(transpilerPath) - var result = transpiler.compile(sourceCode, filePath, config.options || {}) - if (result === undefined) { - return sourceCode + if (transpilerPath) { + this.transpilerPaths[transpilerPath] = true + var transpiler = require(transpilerPath) + var result = transpiler.compile(sourceCode, filePath, spec.options || {}) + if (result === undefined) { + return sourceCode + } else { + return result + } } else { - return result + var err = new Error("Could not resolve transpiler '" + spec.transpiler + "' from '" + config.path + "'") + console.error(err) } - } else { - var err = new Error("Could not find transpiler '" + config.transpiler + "' from '" + config.path + "'") - console.error(err) } -} +}) module.exports = PackageTranspilationRegistry diff --git a/src/package.coffee b/src/package.coffee index 10764460f..1874a6916 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -254,13 +254,11 @@ class Package registerTranspilerConfig: -> if @metadata.atomTranspilers - for transpiler in @metadata.atomTranspilers - CompileCache.addTranspilerConfigForPath(@path, transpiler) + CompileCache.addTranspilerConfigForPath(@path, @metadata.atomTranspilers) unregisterTranspilerConfig: -> if @metadata.atomTranspilers - for transpiler in @metadata.atomTranspilers - CompileCache.removeTranspilerConfigForPath(@path) + CompileCache.removeTranspilerConfigForPath(@path) loadKeymaps: -> if @bundledPackage and @packageManager.packagesCache[@name]? From 0f61b79049baf09bbf589a34c94d9e600c159138 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 15:24:29 -0700 Subject: [PATCH 04/23] :fire: transpilerHashes --- src/package-transpilation-registry.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 64c136f2c..800189c5f 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -10,7 +10,6 @@ function PackageTranspilationRegistry () { this.configByPackagePath = {} this.specByFilePath = {} this.transpilerPaths = {} - this.transpilerHashes = {} } Object.assign(PackageTranspilationRegistry.prototype, { From eafc281025bfdd092f1f044cb2da24b48a29cb90 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 15:25:24 -0700 Subject: [PATCH 05/23] :fire: console --- src/package-transpilation-registry.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 800189c5f..8767b4d72 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -19,7 +19,6 @@ Object.assign(PackageTranspilationRegistry.prototype, { specs: config, path: packagePath } - console.debug(">> adding", this.configByPackagePath[packagePath]) }, removeTranspilerConfigForPath: function (packagePath) { @@ -78,10 +77,8 @@ Object.assign(PackageTranspilationRegistry.prototype, { // only iterates four times, even if there are hundreds of configs registered. while (thisPath !== lastPath) { // until we reach the root if (config = this.configByPackagePath[thisPath]) { - console.log('got one') for (var i = 0; i < config.specs.length; i++) { spec = config.specs[i] - console.log("checking", filePath, "against", path.join(config.path, spec.glob)) if (minimatch(filePath, path.join(config.path, spec.glob))) { spec._config = config this.specByFilePath[filePath] = spec From 0c9ea6c67dbc036fde949ce41301c3773ab0f2bc Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 15:29:21 -0700 Subject: [PATCH 06/23] Remove lookup in favor of passed arg --- src/package-transpilation-registry.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 8767b4d72..bf07f9187 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -111,8 +111,6 @@ Object.assign(PackageTranspilationRegistry.prototype, { }, transpileWithPackageTranspiler: function (sourceCode, filePath, spec) { - var spec = this.specByFilePath[filePath] - Resolve = Resolve || require('resolve') var transpilerPath = Resolve.sync(spec.transpiler, { basedir: spec._config.path, From 8abdabb66d6913c7df43bae398e57907ffbd10e0 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 16:46:52 -0700 Subject: [PATCH 07/23] Fix linting issues/errors --- src/package-transpilation-registry.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index bf07f9187..a69ce6d31 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -76,7 +76,7 @@ Object.assign(PackageTranspilationRegistry.prototype, { // This means searching for a config for `/path/to/file/here.js` only // only iterates four times, even if there are hundreds of configs registered. while (thisPath !== lastPath) { // until we reach the root - if (config = this.configByPackagePath[thisPath]) { + if (config = this.configByPackagePath[thisPath]) { // // eslint-disable-line no-cond-assign for (var i = 0; i < config.specs.length; i++) { spec = config.specs[i] if (minimatch(filePath, path.join(config.path, spec.glob))) { @@ -100,7 +100,7 @@ Object.assign(PackageTranspilationRegistry.prototype, { var transpilerSource = spec._transpilerSource || fs.readFileSync(transpilerPath, 'utf8') spec._transpilerSource = transpilerSource return path.join( - "package-transpile", + 'package-transpile', crypto .createHash('sha1') .update(JSON.stringify(spec.options || {})) @@ -127,7 +127,7 @@ Object.assign(PackageTranspilationRegistry.prototype, { return result } } else { - var err = new Error("Could not resolve transpiler '" + spec.transpiler + "' from '" + config.path + "'") + var err = new Error("Could not resolve transpiler '" + spec.transpiler + "' from '" + spec._config.path + "'") console.error(err) } } From 57e36562df586e4f26326e9d5cf71d84769fe997 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 21:17:49 -0700 Subject: [PATCH 08/23] :fire: Extra // in eslint comment --- src/package-transpilation-registry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index a69ce6d31..b37671b77 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -76,7 +76,7 @@ Object.assign(PackageTranspilationRegistry.prototype, { // This means searching for a config for `/path/to/file/here.js` only // only iterates four times, even if there are hundreds of configs registered. while (thisPath !== lastPath) { // until we reach the root - if (config = this.configByPackagePath[thisPath]) { // // eslint-disable-line no-cond-assign + if (config = this.configByPackagePath[thisPath]) { // eslint-disable-line no-cond-assign for (var i = 0; i < config.specs.length; i++) { spec = config.specs[i] if (minimatch(filePath, path.join(config.path, spec.glob))) { From 07d13c18553d4c838b9cbf26fd1f536a4bb1f14b Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 21:56:54 -0700 Subject: [PATCH 09/23] Include user data in cache calculation --- src/package-transpilation-registry.js | 53 ++++++++++++++++++--------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index b37671b77..053264882 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -96,30 +96,30 @@ Object.assign(PackageTranspilationRegistry.prototype, { }, getCachePath: function (sourceCode, filePath, spec) { - var transpilerPath = path.join(spec._config.path, spec.transpiler) + var transpilerPath = this.getTranspilerPath(spec) var transpilerSource = spec._transpilerSource || fs.readFileSync(transpilerPath, 'utf8') spec._transpilerSource = transpilerSource - return path.join( - 'package-transpile', - crypto - .createHash('sha1') - .update(JSON.stringify(spec.options || {})) - .update(transpilerSource, 'utf8') - .update(sourceCode, 'utf8') - .digest('hex') - ) + var transpiler = this.getTranspiler(spec) + + var hash = crypto + .createHash('sha1') + .update(JSON.stringify(spec.options || {})) + .update(transpilerSource, 'utf8') + .update(sourceCode, 'utf8') + + var additionalCacheData + if (transpiler && transpiler.getCacheKeyData) { + additionalCacheData = transpiler.getCacheKeyData(sourceCode, filePath, spec.options) + hash.update(additionalCacheData, 'utf8') + } + + return path.join('package-transpile', hash.digest('hex')) }, transpileWithPackageTranspiler: function (sourceCode, filePath, spec) { - Resolve = Resolve || require('resolve') - var transpilerPath = Resolve.sync(spec.transpiler, { - basedir: spec._config.path, - extensions: Object.keys(require.extensions) - }) + var transpiler = this.getTranspiler(spec) - if (transpilerPath) { - this.transpilerPaths[transpilerPath] = true - var transpiler = require(transpilerPath) + if (transpiler) { var result = transpiler.compile(sourceCode, filePath, spec.options || {}) if (result === undefined) { return sourceCode @@ -130,6 +130,23 @@ Object.assign(PackageTranspilationRegistry.prototype, { var err = new Error("Could not resolve transpiler '" + spec.transpiler + "' from '" + spec._config.path + "'") console.error(err) } + }, + + getTranspilerPath: function (spec) { + Resolve = Resolve || require('resolve') + return Resolve.sync(spec.transpiler, { + basedir: spec._config.path, + extensions: Object.keys(require.extensions) + }) + }, + + getTranspiler: function (spec) { + var transpilerPath = this.getTranspilerPath(spec) + if (transpilerPath) { + var transpiler = require(transpilerPath) + this.transpilerPaths[transpilerPath] = true + return transpiler + } } }) From 8521e47e208d7f556f369031edd804348bd91f50 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 21:58:09 -0700 Subject: [PATCH 10/23] compile :arrow_right: transpile --- src/package-transpilation-registry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 053264882..343c46d45 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -120,7 +120,7 @@ Object.assign(PackageTranspilationRegistry.prototype, { var transpiler = this.getTranspiler(spec) if (transpiler) { - var result = transpiler.compile(sourceCode, filePath, spec.options || {}) + var result = transpiler.transpile(sourceCode, filePath, spec.options || {}) if (result === undefined) { return sourceCode } else { From 4a03874af0bfacfd27536e1b5d1557cf16fb7c80 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sat, 29 Oct 2016 22:09:59 -0700 Subject: [PATCH 11/23] Call on transpiled code --- src/package-transpilation-registry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 343c46d45..aa764b6f8 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -124,7 +124,7 @@ Object.assign(PackageTranspilationRegistry.prototype, { if (result === undefined) { return sourceCode } else { - return result + return result.toString() } } else { var err = new Error("Could not resolve transpiler '" + spec.transpiler + "' from '" + spec._config.path + "'") From 2be42a16e096977925e40e7bfd7927e1aad785e5 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sun, 30 Oct 2016 10:21:11 -0700 Subject: [PATCH 12/23] Throw when can't find custom transpiler --- src/package-transpilation-registry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index aa764b6f8..9a2f7d1d6 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -128,7 +128,7 @@ Object.assign(PackageTranspilationRegistry.prototype, { } } else { var err = new Error("Could not resolve transpiler '" + spec.transpiler + "' from '" + spec._config.path + "'") - console.error(err) + throw err } }, From 934ab30a0d3a14f55de2672001982860fda54aa8 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sun, 30 Oct 2016 10:21:22 -0700 Subject: [PATCH 13/23] Add PackageTranspilationRegistry spec --- spec/package-transpilation-registry-spec.js | 128 ++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 spec/package-transpilation-registry-spec.js diff --git a/spec/package-transpilation-registry-spec.js b/spec/package-transpilation-registry-spec.js new file mode 100644 index 000000000..ba22306e7 --- /dev/null +++ b/spec/package-transpilation-registry-spec.js @@ -0,0 +1,128 @@ +/** @babel */ +import fs from 'fs' +import path from 'path' + +import {it, fit, ffit, fffit, beforeEach, afterEach} from './async-spec-helpers' + +import PackageTranspilationRegistry from '../src/package-transpilation-registry' + +let originalCompiler = { + getCachePath: (sourceCode, filePath) => { + return "orig-cache-path" + }, + + compile: (sourceCode, filePath) => { + return sourceCode + "-original-compiler" + }, + + shouldCompile: (sourceCode, filePath) => { + return path.extname(filePath) === '.js' + } +} + +describe("PackageTranspilationRegistry", () => { + let registry + let wrappedCompiler + + beforeEach(() => { + registry = new PackageTranspilationRegistry() + wrappedCompiler = registry.wrapTranspiler(originalCompiler) + }) + + it('falls through to the original compiler by default', () => { + spyOn(originalCompiler, 'getCachePath') + spyOn(originalCompiler, 'compile') + spyOn(originalCompiler, 'shouldCompile') + + wrappedCompiler.getCachePath('source', '/path/to/file.js') + wrappedCompiler.compile('source', '/path/to/filejs') + wrappedCompiler.shouldCompile('source', '/path/to/file.js') + + expect(originalCompiler.getCachePath).toHaveBeenCalled() + expect(originalCompiler.compile).toHaveBeenCalled() + expect(originalCompiler.shouldCompile).toHaveBeenCalled() + }) + + describe('when a file is contained in a path that has custom transpilation', () => { + let hitPath = '/path/to/lib/file.js' + let hitPathCoffee = '/path/to/file2.coffee' + let missPath = '/path/other/file3.js' + let hitPathMissSubdir = '/path/to/file4.js' + let hitPathMissExt = '/path/to/file5.ts' + + let jsSpec = { glob: "lib/**/*.js", transpiler: './transpiler-js', options: { type: 'js' } } + let coffeeSpec = { glob: "*.coffee", transpiler: './transpiler-coffee', options: { type: 'coffee' } } + + let jsTranspiler = { + transpile: (sourceCode, filePath, options) => { + return sourceCode + "-transpiler-js" + }, + + getCacheKeyData: (sourceCode, filePath, options) => { + return 'js-transpiler-cache-data' + } + } + + let coffeeTranspiler = { + transpile: (sourceCode, filePath, options) => { + return sourceCode + "-transpiler-coffee" + }, + + getCacheKeyData: (sourceCode, filePath, options) => { + return 'coffee-transpiler-cache-data' + } + } + + beforeEach(() => { + jsSpec._transpilerSource = "js-transpiler-source" + coffeeSpec._transpilerSource = "coffee-transpiler-source" + + const oldFsRealpathSync = fs.realpathSync.bind(fs) + spyOn(fs, 'realpathSync').andCallFake(thePath => { + if (thePath === '/path/to') return thePath + if (thePath === '/path/other') return thePath + return oldFsRealpathSync(thePath) + }) + + spyOn(registry, "getTranspiler").andCallFake(spec => { + if (spec.transpiler === './transpiler-js') return jsTranspiler + if (spec.transpiler === './transpiler-coffee') return coffeeTranspiler + throw new Error('bad transpiler path ' + spec.transpiler) + }) + + registry.addTranspilerConfigForPath('/path/to', [ + jsSpec, coffeeSpec + ]) + }) + + it('always returns true from shouldCompile for a file in that dir that match a glob', () => { + spyOn(originalCompiler, 'shouldCompile').andReturn(false) + expect(wrappedCompiler.shouldCompile('source', hitPath)).toBe(true) + expect(wrappedCompiler.shouldCompile('source', hitPathCoffee)).toBe(true) + expect(wrappedCompiler.shouldCompile('source', hitPathMissExt)).toBe(false) + expect(wrappedCompiler.shouldCompile('source', hitPathMissSubdir)).toBe(false) + expect(wrappedCompiler.shouldCompile('source', missPath)).toBe(false) + }) + + it('calls getCacheKeyData on the transpiler to get additional cache key data', () => { + spyOn(registry, "getTranspilerPath").andReturn("./transpiler-js") + spyOn(jsTranspiler, 'getCacheKeyData').andCallThrough() + + wrappedCompiler.getCachePath('source', missPath, jsSpec) + expect(jsTranspiler.getCacheKeyData).not.toHaveBeenCalled() + wrappedCompiler.getCachePath('source', hitPath, jsSpec) + expect(jsTranspiler.getCacheKeyData).toHaveBeenCalled() + }) + + it('compiles files matching a glob with the associated transpiler, and the old one otherwise', () => { + spyOn(jsTranspiler, "transpile").andCallThrough() + spyOn(coffeeTranspiler, "transpile").andCallThrough() + + expect(wrappedCompiler.compile('source', hitPath)).toEqual('source-transpiler-js') + expect(wrappedCompiler.compile('source', hitPathCoffee)).toEqual('source-transpiler-coffee') + expect(wrappedCompiler.compile('source', missPath)).toEqual('source-original-compiler') + expect(wrappedCompiler.compile('source', hitPathMissExt)).toEqual('source-original-compiler') + expect(wrappedCompiler.compile('source', hitPathMissSubdir)).toEqual('source-original-compiler') + }) + }) +}) From 00a020d1750c89bf3f65eafaa7e0649664452ba8 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Sun, 30 Oct 2016 10:41:33 -0700 Subject: [PATCH 14/23] Move call to fs.realpathSync to CompileCache --- spec/package-transpilation-registry-spec.js | 7 ------- src/compile-cache.js | 2 ++ src/package-transpilation-registry.js | 2 -- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/spec/package-transpilation-registry-spec.js b/spec/package-transpilation-registry-spec.js index ba22306e7..f45d8d59e 100644 --- a/spec/package-transpilation-registry-spec.js +++ b/spec/package-transpilation-registry-spec.js @@ -77,13 +77,6 @@ describe("PackageTranspilationRegistry", () => { jsSpec._transpilerSource = "js-transpiler-source" coffeeSpec._transpilerSource = "coffee-transpiler-source" - const oldFsRealpathSync = fs.realpathSync.bind(fs) - spyOn(fs, 'realpathSync').andCallFake(thePath => { - if (thePath === '/path/to') return thePath - if (thePath === '/path/other') return thePath - return oldFsRealpathSync(thePath) - }) - spyOn(registry, "getTranspiler").andCallFake(spec => { if (spec.transpiler === './transpiler-js') return jsTranspiler if (spec.transpiler === './transpiler-coffee') return coffeeTranspiler diff --git a/src/compile-cache.js b/src/compile-cache.js index 702b2659f..6101626bb 100644 --- a/src/compile-cache.js +++ b/src/compile-cache.js @@ -20,10 +20,12 @@ var COMPILERS = { } exports.addTranspilerConfigForPath = function (packagePath, config) { + packagePath = fs.realpathSync(packagePath) packageTranspilationRegistry.addTranspilerConfigForPath(packagePath, config) } exports.removeTranspilerConfigForPath = function (packagePath) { + packagePath = fs.realpathSync(packagePath) packageTranspilationRegistry.removeTranspilerConfigForPath(packagePath) } diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 9a2f7d1d6..2708bd6fe 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -14,7 +14,6 @@ function PackageTranspilationRegistry () { Object.assign(PackageTranspilationRegistry.prototype, { addTranspilerConfigForPath: function (packagePath, config) { - packagePath = fs.realpathSync(packagePath) this.configByPackagePath[packagePath] = { specs: config, path: packagePath @@ -22,7 +21,6 @@ Object.assign(PackageTranspilationRegistry.prototype, { }, removeTranspilerConfigForPath: function (packagePath) { - packagePath = fs.realpathSync(packagePath) delete this.configByPackagePath[packagePath] }, From 1bc1b49f84da6ee43bf1dd4295d151737aa5d1bc Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Mon, 31 Oct 2016 16:42:33 -0700 Subject: [PATCH 15/23] Expect transpilation result on .code --- spec/package-transpilation-registry-spec.js | 4 ++-- src/package-transpilation-registry.js | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/spec/package-transpilation-registry-spec.js b/spec/package-transpilation-registry-spec.js index f45d8d59e..26d5e5657 100644 --- a/spec/package-transpilation-registry-spec.js +++ b/spec/package-transpilation-registry-spec.js @@ -55,7 +55,7 @@ describe("PackageTranspilationRegistry", () => { let jsTranspiler = { transpile: (sourceCode, filePath, options) => { - return sourceCode + "-transpiler-js" + return {code: sourceCode + "-transpiler-js"} }, getCacheKeyData: (sourceCode, filePath, options) => { @@ -65,7 +65,7 @@ describe("PackageTranspilationRegistry", () => { let coffeeTranspiler = { transpile: (sourceCode, filePath, options) => { - return sourceCode + "-transpiler-coffee" + return {code: sourceCode + "-transpiler-coffee"} }, getCacheKeyData: (sourceCode, filePath, options) => { diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 2708bd6fe..5a7503e88 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -119,10 +119,12 @@ Object.assign(PackageTranspilationRegistry.prototype, { if (transpiler) { var result = transpiler.transpile(sourceCode, filePath, spec.options || {}) - if (result === undefined) { + if (result === undefined || (result && result.code === undefined)) { return sourceCode + } else if (result.code) { + return result.code.toString() } else { - return result.toString() + throw new Error("Could not find a property `.code` on the transpilation results of " + filePath) } } else { var err = new Error("Could not resolve transpiler '" + spec.transpiler + "' from '" + spec._config.path + "'") From 5c885e6947fc27f5f3d530cd0294e0fcd3d48ca4 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Mon, 31 Oct 2016 16:53:24 -0700 Subject: [PATCH 16/23] We don't want no node_modules --- spec/package-transpilation-registry-spec.js | 3 +++ src/package-transpilation-registry.js | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/spec/package-transpilation-registry-spec.js b/spec/package-transpilation-registry-spec.js index 26d5e5657..116f41745 100644 --- a/spec/package-transpilation-registry-spec.js +++ b/spec/package-transpilation-registry-spec.js @@ -49,6 +49,7 @@ describe("PackageTranspilationRegistry", () => { let missPath = '/path/other/file3.js' let hitPathMissSubdir = '/path/to/file4.js' let hitPathMissExt = '/path/to/file5.ts' + let nodeModulesFolder = '/path/to/lib/node_modules/file6.js' let jsSpec = { glob: "lib/**/*.js", transpiler: './transpiler-js', options: { type: 'js' } } let coffeeSpec = { glob: "*.coffee", transpiler: './transpiler-coffee', options: { type: 'coffee' } } @@ -95,6 +96,7 @@ describe("PackageTranspilationRegistry", () => { expect(wrappedCompiler.shouldCompile('source', hitPathMissExt)).toBe(false) expect(wrappedCompiler.shouldCompile('source', hitPathMissSubdir)).toBe(false) expect(wrappedCompiler.shouldCompile('source', missPath)).toBe(false) + expect(wrappedCompiler.shouldCompile('source', nodeModulesFolder)).toBe(false) }) it('calls getCacheKeyData on the transpiler to get additional cache key data', () => { @@ -116,6 +118,7 @@ describe("PackageTranspilationRegistry", () => { expect(wrappedCompiler.compile('source', missPath)).toEqual('source-original-compiler') expect(wrappedCompiler.compile('source', hitPathMissExt)).toEqual('source-original-compiler') expect(wrappedCompiler.compile('source', hitPathMissSubdir)).toEqual('source-original-compiler') + expect(wrappedCompiler.compile('source', nodeModulesFolder)).toEqual('source-original-compiler') }) }) }) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 5a7503e88..5cbbc17c8 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -65,6 +65,11 @@ Object.assign(PackageTranspilationRegistry.prototype, { getPackageTranspilerSpecForFilePath: function (filePath) { if (this.specByFilePath[filePath] !== undefined) return this.specByFilePath[filePath] + // ignore node_modules + if (filePath.indexOf(path.sep + 'node_modules' + path.sep) > -1) { + return false + } + var config = null var spec = null var thisPath = filePath From 227ef5e2deab0e711653a0a7dd949b6f9cea6e91 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Mon, 31 Oct 2016 16:58:13 -0700 Subject: [PATCH 17/23] Add test for non-standard extension transpilation --- spec/package-transpilation-registry-spec.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/spec/package-transpilation-registry-spec.js b/spec/package-transpilation-registry-spec.js index 116f41745..d8e5542c8 100644 --- a/spec/package-transpilation-registry-spec.js +++ b/spec/package-transpilation-registry-spec.js @@ -50,9 +50,11 @@ describe("PackageTranspilationRegistry", () => { let hitPathMissSubdir = '/path/to/file4.js' let hitPathMissExt = '/path/to/file5.ts' let nodeModulesFolder = '/path/to/lib/node_modules/file6.js' + let hitNonStandardExt = '/path/to/file7.omgwhatisthis' let jsSpec = { glob: "lib/**/*.js", transpiler: './transpiler-js', options: { type: 'js' } } let coffeeSpec = { glob: "*.coffee", transpiler: './transpiler-coffee', options: { type: 'coffee' } } + let omgSpec = { glob: "*.omgwhatisthis", transpiler: './transpiler-omg', options: { type: 'omg' } } let jsTranspiler = { transpile: (sourceCode, filePath, options) => { @@ -74,18 +76,30 @@ describe("PackageTranspilationRegistry", () => { } } + let omgTranspiler = { + transpile: (sourceCode, filePath, options) => { + return {code: sourceCode + "-transpiler-omg"} + }, + + getCacheKeyData: (sourceCode, filePath, options) => { + return 'omg-transpiler-cache-data' + } + } + beforeEach(() => { jsSpec._transpilerSource = "js-transpiler-source" coffeeSpec._transpilerSource = "coffee-transpiler-source" + omgTranspiler._transpilerSource = "omg-transpiler-source" spyOn(registry, "getTranspiler").andCallFake(spec => { if (spec.transpiler === './transpiler-js') return jsTranspiler if (spec.transpiler === './transpiler-coffee') return coffeeTranspiler + if (spec.transpiler === './transpiler-omg') return omgTranspiler throw new Error('bad transpiler path ' + spec.transpiler) }) registry.addTranspilerConfigForPath('/path/to', [ - jsSpec, coffeeSpec + jsSpec, coffeeSpec, omgSpec ]) }) @@ -93,6 +107,7 @@ describe("PackageTranspilationRegistry", () => { spyOn(originalCompiler, 'shouldCompile').andReturn(false) expect(wrappedCompiler.shouldCompile('source', hitPath)).toBe(true) expect(wrappedCompiler.shouldCompile('source', hitPathCoffee)).toBe(true) + expect(wrappedCompiler.shouldCompile('source', hitNonStandardExt)).toBe(true) expect(wrappedCompiler.shouldCompile('source', hitPathMissExt)).toBe(false) expect(wrappedCompiler.shouldCompile('source', hitPathMissSubdir)).toBe(false) expect(wrappedCompiler.shouldCompile('source', missPath)).toBe(false) @@ -115,6 +130,7 @@ describe("PackageTranspilationRegistry", () => { expect(wrappedCompiler.compile('source', hitPath)).toEqual('source-transpiler-js') expect(wrappedCompiler.compile('source', hitPathCoffee)).toEqual('source-transpiler-coffee') + expect(wrappedCompiler.compile('source', hitNonStandardExt)).toEqual('source-transpiler-omg') expect(wrappedCompiler.compile('source', missPath)).toEqual('source-original-compiler') expect(wrappedCompiler.compile('source', hitPathMissExt)).toEqual('source-original-compiler') expect(wrappedCompiler.compile('source', hitPathMissSubdir)).toEqual('source-original-compiler') From 5743b2a2834bde366a23da13132ab2fc1c51fce8 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Mon, 31 Oct 2016 17:11:19 -0700 Subject: [PATCH 18/23] Finish up a few missing expectations --- spec/package-transpilation-registry-spec.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/package-transpilation-registry-spec.js b/spec/package-transpilation-registry-spec.js index d8e5542c8..6efd2e72b 100644 --- a/spec/package-transpilation-registry-spec.js +++ b/spec/package-transpilation-registry-spec.js @@ -127,10 +127,15 @@ describe("PackageTranspilationRegistry", () => { it('compiles files matching a glob with the associated transpiler, and the old one otherwise', () => { spyOn(jsTranspiler, "transpile").andCallThrough() spyOn(coffeeTranspiler, "transpile").andCallThrough() + spyOn(omgTranspiler, "transpile").andCallThrough() expect(wrappedCompiler.compile('source', hitPath)).toEqual('source-transpiler-js') + expect(jsTranspiler.transpile).toHaveBeenCalledWith('source', hitPath, jsSpec.options) expect(wrappedCompiler.compile('source', hitPathCoffee)).toEqual('source-transpiler-coffee') + expect(coffeeTranspiler.transpile).toHaveBeenCalledWith('source', hitPathCoffee, coffeeSpec.options) expect(wrappedCompiler.compile('source', hitNonStandardExt)).toEqual('source-transpiler-omg') + expect(omgTranspiler.transpile).toHaveBeenCalledWith('source', hitNonStandardExt, omgSpec.options) + expect(wrappedCompiler.compile('source', missPath)).toEqual('source-original-compiler') expect(wrappedCompiler.compile('source', hitPathMissExt)).toEqual('source-original-compiler') expect(wrappedCompiler.compile('source', hitPathMissSubdir)).toEqual('source-original-compiler') From ef5897e72bb1518fc2e134c158dc738ac5d98d53 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Mon, 31 Oct 2016 19:57:09 -0700 Subject: [PATCH 19/23] :shirt: --- src/package-transpilation-registry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 5cbbc17c8..e51eebea6 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -129,7 +129,7 @@ Object.assign(PackageTranspilationRegistry.prototype, { } else if (result.code) { return result.code.toString() } else { - throw new Error("Could not find a property `.code` on the transpilation results of " + filePath) + throw new Error('Could not find a property `.code` on the transpilation results of ' + filePath) } } else { var err = new Error("Could not resolve transpiler '" + spec.transpiler + "' from '" + spec._config.path + "'") From 2d3afb431c54466d18f7b7b59a8910456d8ca36c Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Mon, 31 Oct 2016 23:21:13 -0700 Subject: [PATCH 20/23] Include package name as part of cache key --- spec/package-transpilation-registry-spec.js | 2 +- src/compile-cache.js | 4 ++-- src/package-transpilation-registry.js | 9 +++++---- src/package.coffee | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/spec/package-transpilation-registry-spec.js b/spec/package-transpilation-registry-spec.js index 6efd2e72b..7a13d3396 100644 --- a/spec/package-transpilation-registry-spec.js +++ b/spec/package-transpilation-registry-spec.js @@ -98,7 +98,7 @@ describe("PackageTranspilationRegistry", () => { throw new Error('bad transpiler path ' + spec.transpiler) }) - registry.addTranspilerConfigForPath('/path/to', [ + registry.addTranspilerConfigForPath('/path/to', 'my-package', [ jsSpec, coffeeSpec, omgSpec ]) }) diff --git a/src/compile-cache.js b/src/compile-cache.js index 6101626bb..fed890d5c 100644 --- a/src/compile-cache.js +++ b/src/compile-cache.js @@ -19,9 +19,9 @@ var COMPILERS = { '.coffee': packageTranspilationRegistry.wrapTranspiler(require('./coffee-script')) } -exports.addTranspilerConfigForPath = function (packagePath, config) { +exports.addTranspilerConfigForPath = function (packagePath, packageName, config) { packagePath = fs.realpathSync(packagePath) - packageTranspilationRegistry.addTranspilerConfigForPath(packagePath, config) + packageTranspilationRegistry.addTranspilerConfigForPath(packagePath, packageName, config) } exports.removeTranspilerConfigForPath = function (packagePath) { diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index e51eebea6..80e2469c1 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -13,10 +13,11 @@ function PackageTranspilationRegistry () { } Object.assign(PackageTranspilationRegistry.prototype, { - addTranspilerConfigForPath: function (packagePath, config) { + addTranspilerConfigForPath: function (packagePath, packageName, config) { this.configByPackagePath[packagePath] = { - specs: config, - path: packagePath + name: packageName, + path: packagePath, + specs: config } }, @@ -116,7 +117,7 @@ Object.assign(PackageTranspilationRegistry.prototype, { hash.update(additionalCacheData, 'utf8') } - return path.join('package-transpile', hash.digest('hex')) + return path.join('package-transpile', spec._config.name, hash.digest('hex')) }, transpileWithPackageTranspiler: function (sourceCode, filePath, spec) { diff --git a/src/package.coffee b/src/package.coffee index 1874a6916..6029c99ae 100644 --- a/src/package.coffee +++ b/src/package.coffee @@ -254,7 +254,7 @@ class Package registerTranspilerConfig: -> if @metadata.atomTranspilers - CompileCache.addTranspilerConfigForPath(@path, @metadata.atomTranspilers) + CompileCache.addTranspilerConfigForPath(@path, @name, @metadata.atomTranspilers) unregisterTranspilerConfig: -> if @metadata.atomTranspilers From 64a8213bc17c30b5ecf8016dcd7ad47519384fbf Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 1 Nov 2016 08:12:33 -0700 Subject: [PATCH 21/23] const-ify some lets --- spec/package-transpilation-registry-spec.js | 28 ++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/spec/package-transpilation-registry-spec.js b/spec/package-transpilation-registry-spec.js index 7a13d3396..cec52a949 100644 --- a/spec/package-transpilation-registry-spec.js +++ b/spec/package-transpilation-registry-spec.js @@ -6,7 +6,7 @@ import {it, fit, ffit, fffit, beforeEach, afterEach} from './async-spec-helpers' import PackageTranspilationRegistry from '../src/package-transpilation-registry' -let originalCompiler = { +const originalCompiler = { getCachePath: (sourceCode, filePath) => { return "orig-cache-path" }, @@ -44,19 +44,19 @@ describe("PackageTranspilationRegistry", () => { }) describe('when a file is contained in a path that has custom transpilation', () => { - let hitPath = '/path/to/lib/file.js' - let hitPathCoffee = '/path/to/file2.coffee' - let missPath = '/path/other/file3.js' - let hitPathMissSubdir = '/path/to/file4.js' - let hitPathMissExt = '/path/to/file5.ts' - let nodeModulesFolder = '/path/to/lib/node_modules/file6.js' - let hitNonStandardExt = '/path/to/file7.omgwhatisthis' + const hitPath = '/path/to/lib/file.js' + const hitPathCoffee = '/path/to/file2.coffee' + const missPath = '/path/other/file3.js' + const hitPathMissSubdir = '/path/to/file4.js' + const hitPathMissExt = '/path/to/file5.ts' + const nodeModulesFolder = '/path/to/lib/node_modules/file6.js' + const hitNonStandardExt = '/path/to/file7.omgwhatisthis' - let jsSpec = { glob: "lib/**/*.js", transpiler: './transpiler-js', options: { type: 'js' } } - let coffeeSpec = { glob: "*.coffee", transpiler: './transpiler-coffee', options: { type: 'coffee' } } - let omgSpec = { glob: "*.omgwhatisthis", transpiler: './transpiler-omg', options: { type: 'omg' } } + const jsSpec = { glob: "lib/**/*.js", transpiler: './transpiler-js', options: { type: 'js' } } + const coffeeSpec = { glob: "*.coffee", transpiler: './transpiler-coffee', options: { type: 'coffee' } } + const omgSpec = { glob: "*.omgwhatisthis", transpiler: './transpiler-omg', options: { type: 'omg' } } - let jsTranspiler = { + const jsTranspiler = { transpile: (sourceCode, filePath, options) => { return {code: sourceCode + "-transpiler-js"} }, @@ -66,7 +66,7 @@ describe("PackageTranspilationRegistry", () => { } } - let coffeeTranspiler = { + const coffeeTranspiler = { transpile: (sourceCode, filePath, options) => { return {code: sourceCode + "-transpiler-coffee"} }, @@ -76,7 +76,7 @@ describe("PackageTranspilationRegistry", () => { } } - let omgTranspiler = { + const omgTranspiler = { transpile: (sourceCode, filePath, options) => { return {code: sourceCode + "-transpiler-omg"} }, From f2ee0f01f50c3b644f0546f2eabc37cf77c68b7f Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 1 Nov 2016 08:55:40 -0700 Subject: [PATCH 22/23] Modernify PackageTranspilationRegistry --- src/package-transpilation-registry.js | 112 +++++++++++++------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 80e2469c1..7923711c3 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -1,59 +1,63 @@ -var crypto = require('crypto') -var fs = require('fs') -var path = require('path') +"use strict" +// This file is required by compile-cache, which is required directly from +// apm, so it can only use the subset of newer JavaScript features that apm's +// version of Node supports. Strict mode is required for block scoped declarations. -var minimatch = require('minimatch') +const crypto = require('crypto') +const fs = require('fs') +const path = require('path') -var Resolve = null +const minimatch = require('minimatch') -function PackageTranspilationRegistry () { - this.configByPackagePath = {} - this.specByFilePath = {} - this.transpilerPaths = {} -} +let Resolve = null -Object.assign(PackageTranspilationRegistry.prototype, { - addTranspilerConfigForPath: function (packagePath, packageName, config) { +class PackageTranspilationRegistry { + constructor () { + this.configByPackagePath = {} + this.specByFilePath = {} + this.transpilerPaths = {} + } + + addTranspilerConfigForPath (packagePath, packageName, config) { this.configByPackagePath[packagePath] = { name: packageName, path: packagePath, specs: config } - }, + } - removeTranspilerConfigForPath: function (packagePath) { + removeTranspilerConfigForPath (packagePath) { delete this.configByPackagePath[packagePath] - }, + } // Wraps the transpiler in an object with the same interface // that falls back to the original transpiler implementation if and // only if a package hasn't registered its desire to transpile its own source. - wrapTranspiler: function (transpiler) { - var self = this + wrapTranspiler (transpiler) { return { - getCachePath: function (sourceCode, filePath) { - var spec = self.getPackageTranspilerSpecForFilePath(filePath) + getCachePath: (sourceCode, filePath) => { + const spec = this.getPackageTranspilerSpecForFilePath(filePath) if (spec) { - return self.getCachePath(sourceCode, filePath, spec) + return this.getCachePath(sourceCode, filePath, spec) } return transpiler.getCachePath(sourceCode, filePath) }, - compile: function (sourceCode, filePath) { - var spec = self.getPackageTranspilerSpecForFilePath(filePath) + compile: (sourceCode, filePath) => { + const spec = this.getPackageTranspilerSpecForFilePath(filePath) if (spec) { - return self.transpileWithPackageTranspiler(sourceCode, filePath, spec) + return this.transpileWithPackageTranspiler(sourceCode, filePath, spec) } return transpiler.compile(sourceCode, filePath) }, - shouldCompile: function (sourceCode, filePath) { - if (self.transpilerPaths[filePath]) { + shouldCompile: (sourceCode, filePath) => { + if (this.transpilerPaths[filePath]) { return false } - var spec = self.getPackageTranspilerSpecForFilePath(filePath) + const spec = this.getPackageTranspilerSpecForFilePath(filePath) if (spec) { return true } @@ -61,9 +65,9 @@ Object.assign(PackageTranspilationRegistry.prototype, { return transpiler.shouldCompile(sourceCode, filePath) } } - }, + } - getPackageTranspilerSpecForFilePath: function (filePath) { + getPackageTranspilerSpecForFilePath (filePath) { if (this.specByFilePath[filePath] !== undefined) return this.specByFilePath[filePath] // ignore node_modules @@ -71,18 +75,17 @@ Object.assign(PackageTranspilationRegistry.prototype, { return false } - var config = null - var spec = null - var thisPath = filePath - var lastPath = null + let thisPath = filePath + let lastPath = null // Iterate parents from the file path to the root, checking at each level // to see if a package manages transpilation for that directory. // This means searching for a config for `/path/to/file/here.js` only // only iterates four times, even if there are hundreds of configs registered. while (thisPath !== lastPath) { // until we reach the root - if (config = this.configByPackagePath[thisPath]) { // eslint-disable-line no-cond-assign - for (var i = 0; i < config.specs.length; i++) { - spec = config.specs[i] + let config = this.configByPackagePath[thisPath] + if (config) { + for (let i = 0; i < config.specs.length; i++) { + const spec = config.specs[i] if (minimatch(filePath, path.join(config.path, spec.glob))) { spec._config = config this.specByFilePath[filePath] = spec @@ -97,34 +100,33 @@ Object.assign(PackageTranspilationRegistry.prototype, { this.specByFilePath[filePath] = null return null - }, + } - getCachePath: function (sourceCode, filePath, spec) { - var transpilerPath = this.getTranspilerPath(spec) - var transpilerSource = spec._transpilerSource || fs.readFileSync(transpilerPath, 'utf8') + getCachePath (sourceCode, filePath, spec) { + const transpilerPath = this.getTranspilerPath(spec) + const transpilerSource = spec._transpilerSource || fs.readFileSync(transpilerPath, 'utf8') spec._transpilerSource = transpilerSource - var transpiler = this.getTranspiler(spec) + const transpiler = this.getTranspiler(spec) - var hash = crypto + let hash = crypto .createHash('sha1') .update(JSON.stringify(spec.options || {})) .update(transpilerSource, 'utf8') .update(sourceCode, 'utf8') - var additionalCacheData if (transpiler && transpiler.getCacheKeyData) { - additionalCacheData = transpiler.getCacheKeyData(sourceCode, filePath, spec.options) + const additionalCacheData = transpiler.getCacheKeyData(sourceCode, filePath, spec.options) hash.update(additionalCacheData, 'utf8') } return path.join('package-transpile', spec._config.name, hash.digest('hex')) - }, + } - transpileWithPackageTranspiler: function (sourceCode, filePath, spec) { - var transpiler = this.getTranspiler(spec) + transpileWithPackageTranspiler (sourceCode, filePath, spec) { + const transpiler = this.getTranspiler(spec) if (transpiler) { - var result = transpiler.transpile(sourceCode, filePath, spec.options || {}) + const result = transpiler.transpile(sourceCode, filePath, spec.options || {}) if (result === undefined || (result && result.code === undefined)) { return sourceCode } else if (result.code) { @@ -133,27 +135,27 @@ Object.assign(PackageTranspilationRegistry.prototype, { throw new Error('Could not find a property `.code` on the transpilation results of ' + filePath) } } else { - var err = new Error("Could not resolve transpiler '" + spec.transpiler + "' from '" + spec._config.path + "'") + const err = new Error("Could not resolve transpiler '" + spec.transpiler + "' from '" + spec._config.path + "'") throw err } - }, + } - getTranspilerPath: function (spec) { + getTranspilerPath (spec) { Resolve = Resolve || require('resolve') return Resolve.sync(spec.transpiler, { basedir: spec._config.path, extensions: Object.keys(require.extensions) }) - }, + } - getTranspiler: function (spec) { - var transpilerPath = this.getTranspilerPath(spec) + getTranspiler (spec) { + const transpilerPath = this.getTranspilerPath(spec) if (transpilerPath) { - var transpiler = require(transpilerPath) + const transpiler = require(transpilerPath) this.transpilerPaths[transpilerPath] = true return transpiler } } -}) +} module.exports = PackageTranspilationRegistry From cb959f33d610718dbad5cffb79e3b9091253ece4 Mon Sep 17 00:00:00 2001 From: Michelle Tilley Date: Tue, 1 Nov 2016 09:55:37 -0700 Subject: [PATCH 23/23] :shirt: --- src/package-transpilation-registry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package-transpilation-registry.js b/src/package-transpilation-registry.js index 7923711c3..46509807f 100644 --- a/src/package-transpilation-registry.js +++ b/src/package-transpilation-registry.js @@ -1,4 +1,4 @@ -"use strict" +'use strict' // This file is required by compile-cache, which is required directly from // apm, so it can only use the subset of newer JavaScript features that apm's // version of Node supports. Strict mode is required for block scoped declarations.