Modernify PackageTranspilationRegistry

This commit is contained in:
Michelle Tilley 2016-11-01 08:55:40 -07:00
parent 64a8213bc1
commit f2ee0f01f5
No known key found for this signature in database
GPG Key ID: CD86C13E51F378DA

View File

@ -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