From 7b8a5f3ab837b47551d600cdbc271f19b3960b16 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Fri, 28 Jul 2017 10:49:02 -0700 Subject: [PATCH 01/15] Bump CoffeeScript version --- .../.npm/plugin/compileCoffeescript/npm-shrinkwrap.json | 6 +++--- packages/non-core/coffeescript/package.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/npm-shrinkwrap.json b/packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/npm-shrinkwrap.json index a24f8dcdc1..1f8aef812e 100644 --- a/packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/npm-shrinkwrap.json +++ b/packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/npm-shrinkwrap.json @@ -1,9 +1,9 @@ { "dependencies": { "coffeescript": { - "version": "1.12.6", - "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.12.6.tgz", - "from": "coffeescript@1.12.6" + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.12.7.tgz", + "from": "coffeescript@1.12.7" }, "source-map": { "version": "0.5.6", diff --git a/packages/non-core/coffeescript/package.js b/packages/non-core/coffeescript/package.js index 5c7601eb1f..298d1c8a51 100644 --- a/packages/non-core/coffeescript/package.js +++ b/packages/non-core/coffeescript/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Javascript dialect with fewer braces and semicolons", - version: "1.12.6_1" + version: "1.12.7_1" }); Package.registerBuildPlugin({ @@ -8,7 +8,7 @@ Package.registerBuildPlugin({ use: ['caching-compiler', 'ecmascript'], sources: ['plugin/compile-coffeescript.js'], npmDependencies: { - "coffeescript": "1.12.6", + "coffeescript": "1.12.7", "source-map": "0.5.6" } }); From 0d65440fe08606a192fc51c1d137dd28f622b600 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Tue, 25 Jul 2017 17:52:59 -0700 Subject: [PATCH 02/15] Instructions for how to test the coffeescript package --- packages/non-core/coffeescript/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/non-core/coffeescript/README.md b/packages/non-core/coffeescript/README.md index 711ff02abd..fe0681a1ae 100644 --- a/packages/non-core/coffeescript/README.md +++ b/packages/non-core/coffeescript/README.md @@ -51,3 +51,13 @@ you'd like to see changed. ### Modules and CoffeeScript See [Modules » CoffeeScript Syntax](http://docs.meteor.com/packages/modules.html#CoffeeScript). + +### Testing This Package + +Follow the [instructions](https://github.com/meteor/meteor/blob/devel/Development.md#tests) +to check out the Meteor repo and run `test-packages`. +Once you can do that successfully, to test the `coffeescript` package run: + +```bash +./meteor test-packages packages/non-core/coffeescript +``` From e4c02401799b8c50242f5a731cb2f1212d02ea10 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Fri, 28 Jul 2017 13:38:38 -0700 Subject: [PATCH 03/15] Split coffeescript package into coffeescript / coffeescript-compiler. --- .../non-core/coffeescript-compiler/.gitignore | 1 + .../.npm/package}/.gitignore | 0 .../.npm/package}/README | 0 .../.npm/package}/npm-shrinkwrap.json | 0 .../non-core/coffeescript-compiler/README.md | 17 ++ .../coffeescript-compiler.js | 214 +++++++++++++++ .../non-core/coffeescript-compiler/package.js | 21 ++ .../coffeescript-test-helper/.gitignore | 0 .../coffeescript-test-helper/README.md | 0 .../coffeescript-test-helper/exporting.coffee | 0 .../coffeescript-test-helper/package.js | 0 packages/non-core/coffeescript/.gitignore | 1 + packages/non-core/coffeescript/README.md | 6 +- .../coffeescript/compile-coffeescript.js | 48 ++++ packages/non-core/coffeescript/package.js | 22 +- .../plugin/compile-coffeescript.js | 252 ------------------ 16 files changed, 316 insertions(+), 266 deletions(-) create mode 100644 packages/non-core/coffeescript-compiler/.gitignore rename packages/non-core/{coffeescript/.npm/plugin/compileCoffeescript => coffeescript-compiler/.npm/package}/.gitignore (100%) rename packages/non-core/{coffeescript/.npm/plugin/compileCoffeescript => coffeescript-compiler/.npm/package}/README (100%) rename packages/non-core/{coffeescript/.npm/plugin/compileCoffeescript => coffeescript-compiler/.npm/package}/npm-shrinkwrap.json (100%) create mode 100644 packages/non-core/coffeescript-compiler/README.md create mode 100644 packages/non-core/coffeescript-compiler/coffeescript-compiler.js create mode 100644 packages/non-core/coffeescript-compiler/package.js rename packages/{ => non-core}/coffeescript-test-helper/.gitignore (100%) rename packages/{ => non-core}/coffeescript-test-helper/README.md (100%) rename packages/{ => non-core}/coffeescript-test-helper/exporting.coffee (100%) rename packages/{ => non-core}/coffeescript-test-helper/package.js (100%) create mode 100644 packages/non-core/coffeescript/compile-coffeescript.js delete mode 100644 packages/non-core/coffeescript/plugin/compile-coffeescript.js diff --git a/packages/non-core/coffeescript-compiler/.gitignore b/packages/non-core/coffeescript-compiler/.gitignore new file mode 100644 index 0000000000..918ef5d781 --- /dev/null +++ b/packages/non-core/coffeescript-compiler/.gitignore @@ -0,0 +1 @@ +.npm diff --git a/packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/.gitignore b/packages/non-core/coffeescript-compiler/.npm/package/.gitignore similarity index 100% rename from packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/.gitignore rename to packages/non-core/coffeescript-compiler/.npm/package/.gitignore diff --git a/packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/README b/packages/non-core/coffeescript-compiler/.npm/package/README similarity index 100% rename from packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/README rename to packages/non-core/coffeescript-compiler/.npm/package/README diff --git a/packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/npm-shrinkwrap.json b/packages/non-core/coffeescript-compiler/.npm/package/npm-shrinkwrap.json similarity index 100% rename from packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/npm-shrinkwrap.json rename to packages/non-core/coffeescript-compiler/.npm/package/npm-shrinkwrap.json diff --git a/packages/non-core/coffeescript-compiler/README.md b/packages/non-core/coffeescript-compiler/README.md new file mode 100644 index 0000000000..2a394f6f5b --- /dev/null +++ b/packages/non-core/coffeescript-compiler/README.md @@ -0,0 +1,17 @@ +# coffeescript-compiler +[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/coffeescript-compiler) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/coffeescript-compiler) +*** + +This package supports the [`coffeescript`](../coffeescript/README.md) package, +and any other packages that wish to compile CoffeeScript code into JavaScript. +Like the [`babel-compiler`](../babel-compiler/README.md) package, the actual +compilation is separated out from the build plugin so that packages besides +the official `coffeescript` package can compile CoffeeScript code. + +### Testing This Package + +Testing the `coffeescript` package also tests this one: + +```bash +./meteor test-packages coffeescript +``` diff --git a/packages/non-core/coffeescript-compiler/coffeescript-compiler.js b/packages/non-core/coffeescript-compiler/coffeescript-compiler.js new file mode 100644 index 0000000000..ed228594cc --- /dev/null +++ b/packages/non-core/coffeescript-compiler/coffeescript-compiler.js @@ -0,0 +1,214 @@ +import { BabelCompiler } from 'meteor/babel-compiler'; +import CoffeeScript from 'coffeescript'; +import { SourceMapConsumer, SourceMapGenerator } from 'source-map'; + + +// The CoffeeScript compiler overrides Error.prepareStackTrace, mostly for the +// use of coffee.run which we don't use. This conflicts with the tool's use of +// Error.prepareStackTrace to properly show error messages in linked code. +// Restore the tool's one after CoffeeScript clobbers it at import time. +if (Error.METEOR_prepareStackTrace) { + Error.prepareStackTrace = Error.METEOR_prepareStackTrace; +} + + +// The CompileResult for this CachingCompiler is a {source, sourceMap} object. +CoffeeScriptCompiler = class CoffeeScriptCompiler { + constructor() { + this.babelCompiler = new BabelCompiler({ + // Prevent Babel from importing helpers from babel-runtime, since + // the CoffeeScript plugin does not imply the modules package, which + // means require may not be defined. Note that this in no way + // prevents CoffeeScript projects from using the modules package and + // putting require or import statements within backticks; it just + // won't happen automatically because of Babel. + runtime: false + }); + } + + getCompileOptions(inputFile) { + return { + bare: true, + filename: inputFile.getPathInPackage(), + literate: inputFile.getExtension() !== 'coffee', + // Return a source map. + sourceMap: true, + // This becomes the `file` field of the source map. + generatedFile: '/' + this.outputFilePath(inputFile), + // This becomes the `sources` field of the source map. + sourceFiles: [inputFile.getDisplayPath()], + }; + } + + outputFilePath(inputFile) { + return inputFile.getPathInPackage() + '.js'; + } + + compileOneFile(inputFile) { + const source = inputFile.getContentsAsString(); + const compileOptions = this.getCompileOptions(inputFile); + + let output; + try { + output = CoffeeScript.compile(source, compileOptions); + } catch (e) { + inputFile.error({ + message: e.message, + line: e.location && (e.location.first_line + 1), + column: e.location && (e.location.first_column + 1) + }); + return null; + } + + let sourceMap = JSON.parse(output.v3SourceMap); + sourceMap.sourcesContent = [source]; + + output.js = this.stripExportedVars( + output.js, + inputFile.getDeclaredExports().map(e => e.name) + ); + + // CoffeeScript contains a handful of features that output as ES2015+, + // such as modules, generator functions, for…of, and tagged template + // literals. Because they’re too varied to detect, pass all CoffeeScript + // compiler output through the Babel compiler. + const doubleRoastedCoffee = + this.babelCompiler.processOneFileForTarget(inputFile, output.js); + + if (doubleRoastedCoffee != null && + doubleRoastedCoffee.data != null) { + output.js = doubleRoastedCoffee.data; + + const coffeeSourceMap = doubleRoastedCoffee.sourceMap; + + if (coffeeSourceMap) { + // Reference the compiled CoffeeScript file so that `applySourceMap` + // below can match it with the source map produced by the CoffeeScript + // compiler. + coffeeSourceMap.sources[0] = '/' + this.outputFilePath(inputFile); + + // Combine the original CoffeeScript source map with the one + // produced by this.babelCompiler.processOneFileForTarget. + const smg = SourceMapGenerator.fromSourceMap( + new SourceMapConsumer(coffeeSourceMap) + ); + smg.applySourceMap(new SourceMapConsumer(sourceMap)); + sourceMap = smg.toJSON(); + } else { + // If the .coffee file is contained by a node_modules directory, + // then BabelCompiler will not transpile it, and there will be + // no sourceMap, but that's fine because the original + // CoffeeScript sourceMap will still be valid. + } + } + + return this.addSharedHeader(output.js, sourceMap); + } + + stripExportedVars(source, exports) { + if (!exports || !exports.length) + return source; + const lines = source.split("\n"); + + // We make the following assumptions, based on the output of CoffeeScript + // 1.7.1. + // - The var declaration in question is not indented and is the first such + // var declaration. (CoffeeScript only produces one var line at each + // scope and there's only one top-level scope.) All relevant variables + // are actually on this line. + // - The user hasn't used a ###-comment containing a line that looks like + // a var line, to produce something like + // /* bla + // var foo; + // */ + // before an actual var line. (ie, we do NOT attempt to figure out if + // we're inside a /**/ comment, which is produced by ### comments.) + // - The var in question is not assigned to in the declaration, nor are any + // other vars on this line. (CoffeeScript does produce some assignments + // but only for internal helpers generated by CoffeeScript, and they end + // up on subsequent lines.) + // XXX relax these assumptions by doing actual JS parsing (eg with jsparse). + // I'd do this now, but there's no easy way to "unparse" a jsparse AST. + // Or alternatively, hack the compiler to allow us to specify unbound + // symbols directly. + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + const match = /^var (.+)([,;])$/.exec(line); + if (!match) + continue; + + // If there's an assignment on this line, we assume that there are ONLY + // assignments and that the var we are looking for is not declared. (Part + // of our strong assumption about the layout of this code.) + if (match[1].indexOf('=') !== -1) + continue; + + // We want to replace the line with something no shorter, so that all + // records in the source map continue to point at valid + // characters. + function replaceLine(x) { + if (x.length >= lines[i].length) { + lines[i] = x; + } else { + lines[i] = x + new Array(1 + (lines[i].length - x.length)).join(' '); + } + } + + let vars = match[1].split(', ').filter(v => exports.indexOf(v) === -1); + if (vars.length) { + replaceLine('var ' + vars.join(', ') + match[2]); + } else { + // We got rid of all the vars on this line. Drop the whole line if this + // didn't continue to the next line, otherwise keep just the 'var '. + if (match[2] === ';') + replaceLine(''); + else + replaceLine('var'); + } + break; + } + + return lines.join('\n'); + } + + addSharedHeader(source, sourceMap) { + // We want the symbol "share" to be visible to all CoffeeScript files in the + // package (and shared between them), but not visible to JavaScript + // files. (That's because we don't want to introduce two competing ways to + // make package-local variables into JS ("share" vs assigning to non-var + // variables).) The following hack accomplishes that: "__coffeescriptShare" + // will be visible at the package level and "share" at the file level. This + // should work both in "package" mode where __coffeescriptShare will be added + // as a var in the package closure, and in "app" mode where it will end up as + // a global. + // + // This ends in a newline to make the source map easier to adjust. + const header = ("__coffeescriptShare = typeof __coffeescriptShare === 'object' " + + "? __coffeescriptShare : {}; " + + "var share = __coffeescriptShare;\n"); + + // If the file begins with "use strict", we need to keep that as the first + // statement. + const processedSource = source.replace(/^(?:((['"])use strict\2;)\n)?/, (match, useStrict) => { + if (match) { + // There's a "use strict"; we keep this as the first statement and insert + // our header at the end of the line that it's on. This doesn't change + // line numbers or the part of the line that previous may have been + // annotated, so we don't need to update the source map. + return useStrict + ' ' + header; + } else { + // There's no use strict, so we can just add the header at the very + // beginning. This adds a line to the file, so we update the source map to + // add a single un-annotated line to the beginning. + sourceMap.mappings = ';' + sourceMap.mappings; + return header; + } + }); + return { + source: processedSource, + sourceMap: sourceMap + }; + } + +} diff --git a/packages/non-core/coffeescript-compiler/package.js b/packages/non-core/coffeescript-compiler/package.js new file mode 100644 index 0000000000..fc394b7751 --- /dev/null +++ b/packages/non-core/coffeescript-compiler/package.js @@ -0,0 +1,21 @@ +Package.describe({ + name: 'coffeescript-compiler', + summary: 'Compiler for CoffeeScript code, supporting the coffeescript package', + version: '1.12.7_1' // Tracks version of NPM `coffeescript` module, with _1, _2 etc. +}); + +Npm.depends({ + 'coffeescript': '1.12.7', + 'source-map': '0.5.6' +}); + +Package.onUse(function (api) { + api.use('babel-compiler'); + api.use('ecmascript'); + + api.addFiles(['coffeescript-compiler.js'], 'server'); + + api.export('CoffeeScriptCompiler', 'server'); +}); + +// See `coffeescript` package for tests. diff --git a/packages/coffeescript-test-helper/.gitignore b/packages/non-core/coffeescript-test-helper/.gitignore similarity index 100% rename from packages/coffeescript-test-helper/.gitignore rename to packages/non-core/coffeescript-test-helper/.gitignore diff --git a/packages/coffeescript-test-helper/README.md b/packages/non-core/coffeescript-test-helper/README.md similarity index 100% rename from packages/coffeescript-test-helper/README.md rename to packages/non-core/coffeescript-test-helper/README.md diff --git a/packages/coffeescript-test-helper/exporting.coffee b/packages/non-core/coffeescript-test-helper/exporting.coffee similarity index 100% rename from packages/coffeescript-test-helper/exporting.coffee rename to packages/non-core/coffeescript-test-helper/exporting.coffee diff --git a/packages/coffeescript-test-helper/package.js b/packages/non-core/coffeescript-test-helper/package.js similarity index 100% rename from packages/coffeescript-test-helper/package.js rename to packages/non-core/coffeescript-test-helper/package.js diff --git a/packages/non-core/coffeescript/.gitignore b/packages/non-core/coffeescript/.gitignore index 677a6fc263..c01644335c 100644 --- a/packages/non-core/coffeescript/.gitignore +++ b/packages/non-core/coffeescript/.gitignore @@ -1 +1,2 @@ .build* +.npm diff --git a/packages/non-core/coffeescript/README.md b/packages/non-core/coffeescript/README.md index fe0681a1ae..b23b98c88d 100644 --- a/packages/non-core/coffeescript/README.md +++ b/packages/non-core/coffeescript/README.md @@ -44,10 +44,6 @@ Here's how CoffeeScript works with Meteor's namespacing. for a value that is shared between all CoffeeScript code in a package, but doesn't escape that package. -Heavy CoffeeScript users, please let us know how this arrangement -works for you, whether `share` is helpful for you, and anything else -you'd like to see changed. - ### Modules and CoffeeScript See [Modules » CoffeeScript Syntax](http://docs.meteor.com/packages/modules.html#CoffeeScript). @@ -59,5 +55,5 @@ to check out the Meteor repo and run `test-packages`. Once you can do that successfully, to test the `coffeescript` package run: ```bash -./meteor test-packages packages/non-core/coffeescript +./meteor test-packages coffeescript ``` diff --git a/packages/non-core/coffeescript/compile-coffeescript.js b/packages/non-core/coffeescript/compile-coffeescript.js new file mode 100644 index 0000000000..c8c940b770 --- /dev/null +++ b/packages/non-core/coffeescript/compile-coffeescript.js @@ -0,0 +1,48 @@ +Plugin.registerCompiler({ + extensions: ['coffee', 'litcoffee', 'coffee.md'] +}, () => new CachedCoffeeScriptCompiler()); + + +// The CompileResult for this CachingCompiler is a {source, sourceMap} object. +class CachedCoffeeScriptCompiler extends CachingCompiler { + constructor() { + super({ + compilerName: 'coffeescript', + defaultCacheSize: 1024*1024*10, + }); + + this.coffeeScriptCompiler = new CoffeeScriptCompiler(); + } + + getCacheKey(inputFile) { + return [ + inputFile.getSourceHash(), + inputFile.getDeclaredExports(), + this.coffeeScriptCompiler.getCompileOptions(inputFile), + ]; + } + + setDiskCacheDirectory(cacheDir) { + this.coffeeScriptCompiler.babelCompiler.setDiskCacheDirectory(cacheDir); + return super.setDiskCacheDirectory(cacheDir); + } + + compileOneFile(inputFile) { + return this.coffeeScriptCompiler.compileOneFile(inputFile); + } + + addCompileResult(inputFile, sourceWithMap) { + inputFile.addJavaScript({ + path: this.coffeeScriptCompiler.outputFilePath(inputFile), + sourcePath: inputFile.getPathInPackage(), + data: sourceWithMap.source, + sourceMap: sourceWithMap.sourceMap, + bare: inputFile.getFileOptions().bare + }); + } + + compileResultSize(sourceWithMap) { + return sourceWithMap.source.length + + this.sourceMapSize(sourceWithMap.sourceMap); + } +} diff --git a/packages/non-core/coffeescript/package.js b/packages/non-core/coffeescript/package.js index 298d1c8a51..0634a95762 100644 --- a/packages/non-core/coffeescript/package.js +++ b/packages/non-core/coffeescript/package.js @@ -1,21 +1,25 @@ Package.describe({ - summary: "Javascript dialect with fewer braces and semicolons", - version: "1.12.7_1" + name: 'coffeescript', + summary: 'Javascript dialect with fewer braces and semicolons', + // This package version used to track the version of the NPM `coffeescript` + // module, but now the Meteor package `coffeescript-compiler` tracks that + // version; so in order for this to appear newer than the previous package + // version 1.12.6_1, we jump to 10+. + version: '10.0.1' }); Package.registerBuildPlugin({ - name: "compileCoffeescript", - use: ['caching-compiler', 'ecmascript'], - sources: ['plugin/compile-coffeescript.js'], + name: 'compile-coffeescript', + use: ['caching-compiler', 'coffeescript-compiler', 'ecmascript'], + sources: ['compile-coffeescript.js'], npmDependencies: { - "coffeescript": "1.12.7", - "source-map": "0.5.6" + 'coffeescript': '1.12.7', + 'source-map': '0.5.6' } }); Package.onUse(function (api) { api.use('isobuild:compiler-plugin@1.0.0'); - api.use('babel-compiler'); // Because the CoffeeScript plugin now calls // BabelCompiler.prototype.processOneFileForTarget for any ES2015+ @@ -23,7 +27,7 @@ Package.onUse(function (api) { // same runtime environment that the 'ecmascript' package provides. // The following api.imply calls should match those in ../ecmascript/package.js, // except that coffeescript does not api.imply('modules'). - api.imply('ecmascript-runtime'); + api.imply('ecmascript-runtime', 'server'); api.imply('babel-runtime'); api.imply('promise'); }); diff --git a/packages/non-core/coffeescript/plugin/compile-coffeescript.js b/packages/non-core/coffeescript/plugin/compile-coffeescript.js deleted file mode 100644 index 03abcbe842..0000000000 --- a/packages/non-core/coffeescript/plugin/compile-coffeescript.js +++ /dev/null @@ -1,252 +0,0 @@ -import { - SourceMapConsumer, - SourceMapGenerator, -} from 'source-map'; -import coffee from 'coffeescript'; -import { BabelCompiler } from 'meteor/babel-compiler'; - -// The CoffeeScript compiler overrides Error.prepareStackTrace, mostly for the -// use of coffee.run which we don't use. This conflicts with the tool's use of -// Error.prepareStackTrace to properly show error messages in linked code. -// Restore the tool's one after CoffeeScript clobbers it at import time. -if (Error.METEOR_prepareStackTrace) { - Error.prepareStackTrace = Error.METEOR_prepareStackTrace; -} - -Plugin.registerCompiler({ - extensions: ['coffee', 'litcoffee', 'coffee.md'] -}, () => new CoffeeCompiler()); - -// The CompileResult for this CachingCompiler is a {source, sourceMap} object. - -export class CoffeeCompiler extends CachingCompiler { - constructor() { - super({ - compilerName: 'coffeescript', - defaultCacheSize: 1024*1024*10, - }); - - this.babelCompiler = new BabelCompiler({ - // Prevent Babel from importing helpers from babel-runtime, since - // the CoffeeScript plugin does not imply the modules package, which - // means require may not be defined. Note that this in no way - // prevents CoffeeScript projects from using the modules package and - // putting require or import statements within backticks; it just - // won't happen automatically because of Babel. - runtime: false - }); - } - - _getCompileOptions(inputFile) { - return { - bare: true, - filename: inputFile.getPathInPackage(), - literate: inputFile.getExtension() !== 'coffee', - // Return a source map. - sourceMap: true, - // This becomes the "file" field of the source map. - generatedFile: '/' + this._outputFilePath(inputFile), - // This becomes the "sources" field of the source map. - sourceFiles: [inputFile.getDisplayPath()], - }; - } - - _outputFilePath(inputFile) { - return inputFile.getPathInPackage() + '.js'; - } - - getCacheKey(inputFile) { - return [ - inputFile.getSourceHash(), - inputFile.getDeclaredExports(), - this._getCompileOptions(inputFile), - ]; - } - - setDiskCacheDirectory(cacheDir) { - this.babelCompiler.setDiskCacheDirectory(cacheDir); - return super.setDiskCacheDirectory(cacheDir); - } - - compileOneFile(inputFile) { - const source = inputFile.getContentsAsString(); - const compileOptions = this._getCompileOptions(inputFile); - - let output; - try { - output = coffee.compile(source, compileOptions); - } catch (e) { - inputFile.error({ - message: e.message, - line: e.location && (e.location.first_line + 1), - column: e.location && (e.location.first_column + 1) - }); - return null; - } - - let sourceMap = JSON.parse(output.v3SourceMap); - sourceMap.sourcesContent = [source]; - - output.js = stripExportedVars( - output.js, - inputFile.getDeclaredExports().map(e => e.name) - ); - - // CoffeeScript contains a handful of features that output as ES2015+, - // such as modules, generator functions, for…of, and tagged template - // literals. Because they’re too varied to detect, pass all CoffeeScript - // compiler output through the Babel compiler. - const doubleRoastedCoffee = - this.babelCompiler.processOneFileForTarget(inputFile, output.js); - - if (doubleRoastedCoffee != null && - doubleRoastedCoffee.data != null) { - output.js = doubleRoastedCoffee.data; - - const coffeeSourceMap = doubleRoastedCoffee.sourceMap; - - if (coffeeSourceMap) { - // Reference the compiled CoffeeScript file so that `applySourceMap` - // below can match it with the source map produced by the CoffeeScript - // compiler. - coffeeSourceMap.sources[0] = '/' + this._outputFilePath(inputFile); - - // Combine the original CoffeeScript source map with the one - // produced by this.babelCompiler.processOneFileForTarget. - const smg = SourceMapGenerator.fromSourceMap( - new SourceMapConsumer(coffeeSourceMap) - ); - smg.applySourceMap(new SourceMapConsumer(sourceMap)); - sourceMap = smg.toJSON(); - } else { - // If the .coffee file is contained by a node_modules directory, - // then BabelCompiler will not transpile it, and there will be - // no sourceMap, but that's fine because the original - // CoffeeScript sourceMap will still be valid. - } - } - - return addSharedHeader(output.js, sourceMap); - } - - addCompileResult(inputFile, sourceWithMap) { - inputFile.addJavaScript({ - path: this._outputFilePath(inputFile), - sourcePath: inputFile.getPathInPackage(), - data: sourceWithMap.source, - sourceMap: sourceWithMap.sourceMap, - bare: inputFile.getFileOptions().bare - }); - } - - compileResultSize(sourceWithMap) { - return sourceWithMap.source.length + - this.sourceMapSize(sourceWithMap.sourceMap); - } -} - -function stripExportedVars(source, exports) { - if (!exports || !exports.length) - return source; - const lines = source.split("\n"); - - // We make the following assumptions, based on the output of CoffeeScript - // 1.7.1. - // - The var declaration in question is not indented and is the first such - // var declaration. (CoffeeScript only produces one var line at each - // scope and there's only one top-level scope.) All relevant variables - // are actually on this line. - // - The user hasn't used a ###-comment containing a line that looks like - // a var line, to produce something like - // /* bla - // var foo; - // */ - // before an actual var line. (ie, we do NOT attempt to figure out if - // we're inside a /**/ comment, which is produced by ### comments.) - // - The var in question is not assigned to in the declaration, nor are any - // other vars on this line. (CoffeeScript does produce some assignments - // but only for internal helpers generated by CoffeeScript, and they end - // up on subsequent lines.) - // XXX relax these assumptions by doing actual JS parsing (eg with jsparse). - // I'd do this now, but there's no easy way to "unparse" a jsparse AST. - // Or alternatively, hack the compiler to allow us to specify unbound - // symbols directly. - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - const match = /^var (.+)([,;])$/.exec(line); - if (!match) - continue; - - // If there's an assignment on this line, we assume that there are ONLY - // assignments and that the var we are looking for is not declared. (Part - // of our strong assumption about the layout of this code.) - if (match[1].indexOf('=') !== -1) - continue; - - // We want to replace the line with something no shorter, so that all - // records in the source map continue to point at valid - // characters. - function replaceLine(x) { - if (x.length >= lines[i].length) { - lines[i] = x; - } else { - lines[i] = x + new Array(1 + (lines[i].length - x.length)).join(' '); - } - } - - let vars = match[1].split(', ').filter(v => exports.indexOf(v) === -1); - if (vars.length) { - replaceLine('var ' + vars.join(', ') + match[2]); - } else { - // We got rid of all the vars on this line. Drop the whole line if this - // didn't continue to the next line, otherwise keep just the 'var '. - if (match[2] === ';') - replaceLine(''); - else - replaceLine('var'); - } - break; - } - - return lines.join('\n'); -} - -function addSharedHeader(source, sourceMap) { - // We want the symbol "share" to be visible to all CoffeeScript files in the - // package (and shared between them), but not visible to JavaScript - // files. (That's because we don't want to introduce two competing ways to - // make package-local variables into JS ("share" vs assigning to non-var - // variables).) The following hack accomplishes that: "__coffeescriptShare" - // will be visible at the package level and "share" at the file level. This - // should work both in "package" mode where __coffeescriptShare will be added - // as a var in the package closure, and in "app" mode where it will end up as - // a global. - // - // This ends in a newline to make the source map easier to adjust. - const header = ("__coffeescriptShare = typeof __coffeescriptShare === 'object' " + - "? __coffeescriptShare : {}; " + - "var share = __coffeescriptShare;\n"); - - // If the file begins with "use strict", we need to keep that as the first - // statement. - const processedSource = source.replace(/^(?:((['"])use strict\2;)\n)?/, (match, useStrict) => { - if (match) { - // There's a "use strict"; we keep this as the first statement and insert - // our header at the end of the line that it's on. This doesn't change - // line numbers or the part of the line that previous may have been - // annotated, so we don't need to update the source map. - return useStrict + ' ' + header; - } else { - // There's no use strict, so we can just add the header at the very - // beginning. This adds a line to the file, so we update the source map to - // add a single un-annotated line to the beginning. - sourceMap.mappings = ';' + sourceMap.mappings; - return header; - } - }); - return { - source: processedSource, - sourceMap: sourceMap - }; -} From 13fb390bc7e109a038d40bb68ad56094a7eb4083 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Mon, 14 Aug 2017 22:07:04 +0000 Subject: [PATCH 04/15] Move coffeescript and coffeescript-test-helper packages back into core. (#8960) They depend on core packages like caching-compiler, but coffeescript-compiler can remain in non-core, so it can update more frequently as npm coffeescript gets updated. --- packages/{non-core => }/coffeescript-test-helper/.gitignore | 0 packages/{non-core => }/coffeescript-test-helper/README.md | 0 packages/{non-core => }/coffeescript-test-helper/exporting.coffee | 0 packages/{non-core => }/coffeescript-test-helper/package.js | 0 packages/{non-core => }/coffeescript/.gitignore | 0 packages/{non-core => }/coffeescript/README.md | 0 packages/{non-core => }/coffeescript/compile-coffeescript.js | 0 packages/{non-core => }/coffeescript/package.js | 0 packages/{non-core => }/coffeescript/tests/bare_test_setup.coffee | 0 packages/{non-core => }/coffeescript/tests/bare_tests.js | 0 .../{non-core => }/coffeescript/tests/coffeescript_module.coffee | 0 .../coffeescript/tests/coffeescript_strict_tests.coffee | 0 .../{non-core => }/coffeescript/tests/coffeescript_test_setup.js | 0 .../{non-core => }/coffeescript/tests/coffeescript_tests.coffee | 0 packages/{non-core => }/coffeescript/tests/coffeescript_tests.js | 0 packages/{non-core => }/coffeescript/tests/es2015_module.js | 0 .../coffeescript/tests/litcoffeescript_tests.coffee.md | 0 .../coffeescript/tests/litcoffeescript_tests.litcoffee | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename packages/{non-core => }/coffeescript-test-helper/.gitignore (100%) rename packages/{non-core => }/coffeescript-test-helper/README.md (100%) rename packages/{non-core => }/coffeescript-test-helper/exporting.coffee (100%) rename packages/{non-core => }/coffeescript-test-helper/package.js (100%) rename packages/{non-core => }/coffeescript/.gitignore (100%) rename packages/{non-core => }/coffeescript/README.md (100%) rename packages/{non-core => }/coffeescript/compile-coffeescript.js (100%) rename packages/{non-core => }/coffeescript/package.js (100%) rename packages/{non-core => }/coffeescript/tests/bare_test_setup.coffee (100%) rename packages/{non-core => }/coffeescript/tests/bare_tests.js (100%) rename packages/{non-core => }/coffeescript/tests/coffeescript_module.coffee (100%) rename packages/{non-core => }/coffeescript/tests/coffeescript_strict_tests.coffee (100%) rename packages/{non-core => }/coffeescript/tests/coffeescript_test_setup.js (100%) rename packages/{non-core => }/coffeescript/tests/coffeescript_tests.coffee (100%) rename packages/{non-core => }/coffeescript/tests/coffeescript_tests.js (100%) rename packages/{non-core => }/coffeescript/tests/es2015_module.js (100%) rename packages/{non-core => }/coffeescript/tests/litcoffeescript_tests.coffee.md (100%) rename packages/{non-core => }/coffeescript/tests/litcoffeescript_tests.litcoffee (100%) diff --git a/packages/non-core/coffeescript-test-helper/.gitignore b/packages/coffeescript-test-helper/.gitignore similarity index 100% rename from packages/non-core/coffeescript-test-helper/.gitignore rename to packages/coffeescript-test-helper/.gitignore diff --git a/packages/non-core/coffeescript-test-helper/README.md b/packages/coffeescript-test-helper/README.md similarity index 100% rename from packages/non-core/coffeescript-test-helper/README.md rename to packages/coffeescript-test-helper/README.md diff --git a/packages/non-core/coffeescript-test-helper/exporting.coffee b/packages/coffeescript-test-helper/exporting.coffee similarity index 100% rename from packages/non-core/coffeescript-test-helper/exporting.coffee rename to packages/coffeescript-test-helper/exporting.coffee diff --git a/packages/non-core/coffeescript-test-helper/package.js b/packages/coffeescript-test-helper/package.js similarity index 100% rename from packages/non-core/coffeescript-test-helper/package.js rename to packages/coffeescript-test-helper/package.js diff --git a/packages/non-core/coffeescript/.gitignore b/packages/coffeescript/.gitignore similarity index 100% rename from packages/non-core/coffeescript/.gitignore rename to packages/coffeescript/.gitignore diff --git a/packages/non-core/coffeescript/README.md b/packages/coffeescript/README.md similarity index 100% rename from packages/non-core/coffeescript/README.md rename to packages/coffeescript/README.md diff --git a/packages/non-core/coffeescript/compile-coffeescript.js b/packages/coffeescript/compile-coffeescript.js similarity index 100% rename from packages/non-core/coffeescript/compile-coffeescript.js rename to packages/coffeescript/compile-coffeescript.js diff --git a/packages/non-core/coffeescript/package.js b/packages/coffeescript/package.js similarity index 100% rename from packages/non-core/coffeescript/package.js rename to packages/coffeescript/package.js diff --git a/packages/non-core/coffeescript/tests/bare_test_setup.coffee b/packages/coffeescript/tests/bare_test_setup.coffee similarity index 100% rename from packages/non-core/coffeescript/tests/bare_test_setup.coffee rename to packages/coffeescript/tests/bare_test_setup.coffee diff --git a/packages/non-core/coffeescript/tests/bare_tests.js b/packages/coffeescript/tests/bare_tests.js similarity index 100% rename from packages/non-core/coffeescript/tests/bare_tests.js rename to packages/coffeescript/tests/bare_tests.js diff --git a/packages/non-core/coffeescript/tests/coffeescript_module.coffee b/packages/coffeescript/tests/coffeescript_module.coffee similarity index 100% rename from packages/non-core/coffeescript/tests/coffeescript_module.coffee rename to packages/coffeescript/tests/coffeescript_module.coffee diff --git a/packages/non-core/coffeescript/tests/coffeescript_strict_tests.coffee b/packages/coffeescript/tests/coffeescript_strict_tests.coffee similarity index 100% rename from packages/non-core/coffeescript/tests/coffeescript_strict_tests.coffee rename to packages/coffeescript/tests/coffeescript_strict_tests.coffee diff --git a/packages/non-core/coffeescript/tests/coffeescript_test_setup.js b/packages/coffeescript/tests/coffeescript_test_setup.js similarity index 100% rename from packages/non-core/coffeescript/tests/coffeescript_test_setup.js rename to packages/coffeescript/tests/coffeescript_test_setup.js diff --git a/packages/non-core/coffeescript/tests/coffeescript_tests.coffee b/packages/coffeescript/tests/coffeescript_tests.coffee similarity index 100% rename from packages/non-core/coffeescript/tests/coffeescript_tests.coffee rename to packages/coffeescript/tests/coffeescript_tests.coffee diff --git a/packages/non-core/coffeescript/tests/coffeescript_tests.js b/packages/coffeescript/tests/coffeescript_tests.js similarity index 100% rename from packages/non-core/coffeescript/tests/coffeescript_tests.js rename to packages/coffeescript/tests/coffeescript_tests.js diff --git a/packages/non-core/coffeescript/tests/es2015_module.js b/packages/coffeescript/tests/es2015_module.js similarity index 100% rename from packages/non-core/coffeescript/tests/es2015_module.js rename to packages/coffeescript/tests/es2015_module.js diff --git a/packages/non-core/coffeescript/tests/litcoffeescript_tests.coffee.md b/packages/coffeescript/tests/litcoffeescript_tests.coffee.md similarity index 100% rename from packages/non-core/coffeescript/tests/litcoffeescript_tests.coffee.md rename to packages/coffeescript/tests/litcoffeescript_tests.coffee.md diff --git a/packages/non-core/coffeescript/tests/litcoffeescript_tests.litcoffee b/packages/coffeescript/tests/litcoffeescript_tests.litcoffee similarity index 100% rename from packages/non-core/coffeescript/tests/litcoffeescript_tests.litcoffee rename to packages/coffeescript/tests/litcoffeescript_tests.litcoffee From 3677e17a23af90dd05d64bcbddcb45967c7bc4e9 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Mon, 14 Aug 2017 18:33:23 -0400 Subject: [PATCH 05/15] Bump coffeescript package version to 1.13.0. This Meteor package version does not need to track the npm version of the coffeescript package, and probably should not change as often as the version of the packages/non-core/coffeescript-compiler package. --- packages/coffeescript/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/coffeescript/package.js b/packages/coffeescript/package.js index 0634a95762..9189fe8984 100644 --- a/packages/coffeescript/package.js +++ b/packages/coffeescript/package.js @@ -5,7 +5,7 @@ Package.describe({ // module, but now the Meteor package `coffeescript-compiler` tracks that // version; so in order for this to appear newer than the previous package // version 1.12.6_1, we jump to 10+. - version: '10.0.1' + version: '1.13.0' }); Package.registerBuildPlugin({ From dd6a0f703bec962f0452efc7ee53d9066cf2862d Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Tue, 15 Aug 2017 10:23:54 +0000 Subject: [PATCH 06/15] Move all coffeescript* packages back into non-core --- packages/{ => non-core}/coffeescript-test-helper/.gitignore | 0 packages/{ => non-core}/coffeescript-test-helper/README.md | 0 packages/{ => non-core}/coffeescript-test-helper/exporting.coffee | 0 packages/{ => non-core}/coffeescript-test-helper/package.js | 0 packages/{ => non-core}/coffeescript/.gitignore | 0 packages/{ => non-core}/coffeescript/README.md | 0 packages/{ => non-core}/coffeescript/compile-coffeescript.js | 0 packages/{ => non-core}/coffeescript/package.js | 0 packages/{ => non-core}/coffeescript/tests/bare_test_setup.coffee | 0 packages/{ => non-core}/coffeescript/tests/bare_tests.js | 0 .../{ => non-core}/coffeescript/tests/coffeescript_module.coffee | 0 .../coffeescript/tests/coffeescript_strict_tests.coffee | 0 .../{ => non-core}/coffeescript/tests/coffeescript_test_setup.js | 0 .../{ => non-core}/coffeescript/tests/coffeescript_tests.coffee | 0 packages/{ => non-core}/coffeescript/tests/coffeescript_tests.js | 0 packages/{ => non-core}/coffeescript/tests/es2015_module.js | 0 .../coffeescript/tests/litcoffeescript_tests.coffee.md | 0 .../coffeescript/tests/litcoffeescript_tests.litcoffee | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename packages/{ => non-core}/coffeescript-test-helper/.gitignore (100%) rename packages/{ => non-core}/coffeescript-test-helper/README.md (100%) rename packages/{ => non-core}/coffeescript-test-helper/exporting.coffee (100%) rename packages/{ => non-core}/coffeescript-test-helper/package.js (100%) rename packages/{ => non-core}/coffeescript/.gitignore (100%) rename packages/{ => non-core}/coffeescript/README.md (100%) rename packages/{ => non-core}/coffeescript/compile-coffeescript.js (100%) rename packages/{ => non-core}/coffeescript/package.js (100%) rename packages/{ => non-core}/coffeescript/tests/bare_test_setup.coffee (100%) rename packages/{ => non-core}/coffeescript/tests/bare_tests.js (100%) rename packages/{ => non-core}/coffeescript/tests/coffeescript_module.coffee (100%) rename packages/{ => non-core}/coffeescript/tests/coffeescript_strict_tests.coffee (100%) rename packages/{ => non-core}/coffeescript/tests/coffeescript_test_setup.js (100%) rename packages/{ => non-core}/coffeescript/tests/coffeescript_tests.coffee (100%) rename packages/{ => non-core}/coffeescript/tests/coffeescript_tests.js (100%) rename packages/{ => non-core}/coffeescript/tests/es2015_module.js (100%) rename packages/{ => non-core}/coffeescript/tests/litcoffeescript_tests.coffee.md (100%) rename packages/{ => non-core}/coffeescript/tests/litcoffeescript_tests.litcoffee (100%) diff --git a/packages/coffeescript-test-helper/.gitignore b/packages/non-core/coffeescript-test-helper/.gitignore similarity index 100% rename from packages/coffeescript-test-helper/.gitignore rename to packages/non-core/coffeescript-test-helper/.gitignore diff --git a/packages/coffeescript-test-helper/README.md b/packages/non-core/coffeescript-test-helper/README.md similarity index 100% rename from packages/coffeescript-test-helper/README.md rename to packages/non-core/coffeescript-test-helper/README.md diff --git a/packages/coffeescript-test-helper/exporting.coffee b/packages/non-core/coffeescript-test-helper/exporting.coffee similarity index 100% rename from packages/coffeescript-test-helper/exporting.coffee rename to packages/non-core/coffeescript-test-helper/exporting.coffee diff --git a/packages/coffeescript-test-helper/package.js b/packages/non-core/coffeescript-test-helper/package.js similarity index 100% rename from packages/coffeescript-test-helper/package.js rename to packages/non-core/coffeescript-test-helper/package.js diff --git a/packages/coffeescript/.gitignore b/packages/non-core/coffeescript/.gitignore similarity index 100% rename from packages/coffeescript/.gitignore rename to packages/non-core/coffeescript/.gitignore diff --git a/packages/coffeescript/README.md b/packages/non-core/coffeescript/README.md similarity index 100% rename from packages/coffeescript/README.md rename to packages/non-core/coffeescript/README.md diff --git a/packages/coffeescript/compile-coffeescript.js b/packages/non-core/coffeescript/compile-coffeescript.js similarity index 100% rename from packages/coffeescript/compile-coffeescript.js rename to packages/non-core/coffeescript/compile-coffeescript.js diff --git a/packages/coffeescript/package.js b/packages/non-core/coffeescript/package.js similarity index 100% rename from packages/coffeescript/package.js rename to packages/non-core/coffeescript/package.js diff --git a/packages/coffeescript/tests/bare_test_setup.coffee b/packages/non-core/coffeescript/tests/bare_test_setup.coffee similarity index 100% rename from packages/coffeescript/tests/bare_test_setup.coffee rename to packages/non-core/coffeescript/tests/bare_test_setup.coffee diff --git a/packages/coffeescript/tests/bare_tests.js b/packages/non-core/coffeescript/tests/bare_tests.js similarity index 100% rename from packages/coffeescript/tests/bare_tests.js rename to packages/non-core/coffeescript/tests/bare_tests.js diff --git a/packages/coffeescript/tests/coffeescript_module.coffee b/packages/non-core/coffeescript/tests/coffeescript_module.coffee similarity index 100% rename from packages/coffeescript/tests/coffeescript_module.coffee rename to packages/non-core/coffeescript/tests/coffeescript_module.coffee diff --git a/packages/coffeescript/tests/coffeescript_strict_tests.coffee b/packages/non-core/coffeescript/tests/coffeescript_strict_tests.coffee similarity index 100% rename from packages/coffeescript/tests/coffeescript_strict_tests.coffee rename to packages/non-core/coffeescript/tests/coffeescript_strict_tests.coffee diff --git a/packages/coffeescript/tests/coffeescript_test_setup.js b/packages/non-core/coffeescript/tests/coffeescript_test_setup.js similarity index 100% rename from packages/coffeescript/tests/coffeescript_test_setup.js rename to packages/non-core/coffeescript/tests/coffeescript_test_setup.js diff --git a/packages/coffeescript/tests/coffeescript_tests.coffee b/packages/non-core/coffeescript/tests/coffeescript_tests.coffee similarity index 100% rename from packages/coffeescript/tests/coffeescript_tests.coffee rename to packages/non-core/coffeescript/tests/coffeescript_tests.coffee diff --git a/packages/coffeescript/tests/coffeescript_tests.js b/packages/non-core/coffeescript/tests/coffeescript_tests.js similarity index 100% rename from packages/coffeescript/tests/coffeescript_tests.js rename to packages/non-core/coffeescript/tests/coffeescript_tests.js diff --git a/packages/coffeescript/tests/es2015_module.js b/packages/non-core/coffeescript/tests/es2015_module.js similarity index 100% rename from packages/coffeescript/tests/es2015_module.js rename to packages/non-core/coffeescript/tests/es2015_module.js diff --git a/packages/coffeescript/tests/litcoffeescript_tests.coffee.md b/packages/non-core/coffeescript/tests/litcoffeescript_tests.coffee.md similarity index 100% rename from packages/coffeescript/tests/litcoffeescript_tests.coffee.md rename to packages/non-core/coffeescript/tests/litcoffeescript_tests.coffee.md diff --git a/packages/coffeescript/tests/litcoffeescript_tests.litcoffee b/packages/non-core/coffeescript/tests/litcoffeescript_tests.litcoffee similarity index 100% rename from packages/coffeescript/tests/litcoffeescript_tests.litcoffee rename to packages/non-core/coffeescript/tests/litcoffeescript_tests.litcoffee From 89af934b54aeada8830393587256448c614abc1b Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Tue, 15 Aug 2017 16:40:27 +0000 Subject: [PATCH 07/15] Fix `coffeescript` package version to same as `coffeescript-compiler`; update documentation --- .../non-core/coffeescript-compiler/README.md | 2 +- packages/non-core/coffeescript/README.md | 2 +- packages/non-core/coffeescript/package.js | 18 +++++++----------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/packages/non-core/coffeescript-compiler/README.md b/packages/non-core/coffeescript-compiler/README.md index 2a394f6f5b..c561fe29e3 100644 --- a/packages/non-core/coffeescript-compiler/README.md +++ b/packages/non-core/coffeescript-compiler/README.md @@ -13,5 +13,5 @@ the official `coffeescript` package can compile CoffeeScript code. Testing the `coffeescript` package also tests this one: ```bash -./meteor test-packages coffeescript +./meteor test-packages packages/non-core/coffeescript ``` diff --git a/packages/non-core/coffeescript/README.md b/packages/non-core/coffeescript/README.md index b23b98c88d..040656445d 100644 --- a/packages/non-core/coffeescript/README.md +++ b/packages/non-core/coffeescript/README.md @@ -55,5 +55,5 @@ to check out the Meteor repo and run `test-packages`. Once you can do that successfully, to test the `coffeescript` package run: ```bash -./meteor test-packages coffeescript +./meteor test-packages packages/non-core/coffeescript ``` diff --git a/packages/non-core/coffeescript/package.js b/packages/non-core/coffeescript/package.js index 9189fe8984..73a68abebb 100644 --- a/packages/non-core/coffeescript/package.js +++ b/packages/non-core/coffeescript/package.js @@ -1,21 +1,17 @@ Package.describe({ name: 'coffeescript', summary: 'Javascript dialect with fewer braces and semicolons', - // This package version used to track the version of the NPM `coffeescript` - // module, but now the Meteor package `coffeescript-compiler` tracks that - // version; so in order for this to appear newer than the previous package - // version 1.12.6_1, we jump to 10+. - version: '1.13.0' + // This package version should track the version of the `coffeescript-compiler` + // package, because people will likely only have this one added to their apps; + // so bumping the version of this package will be how they get newer versions + // of `coffeescript-compiler`. + version: '1.12.7_1' }); Package.registerBuildPlugin({ name: 'compile-coffeescript', use: ['caching-compiler', 'coffeescript-compiler', 'ecmascript'], - sources: ['compile-coffeescript.js'], - npmDependencies: { - 'coffeescript': '1.12.7', - 'source-map': '0.5.6' - } + sources: ['compile-coffeescript.js'] }); Package.onUse(function (api) { @@ -25,7 +21,7 @@ Package.onUse(function (api) { // BabelCompiler.prototype.processOneFileForTarget for any ES2015+ // JavaScript or JavaScript enclosed by backticks, it must provide the // same runtime environment that the 'ecmascript' package provides. - // The following api.imply calls should match those in ../ecmascript/package.js, + // The following api.imply calls should match those in ../../ecmascript/package.js, // except that coffeescript does not api.imply('modules'). api.imply('ecmascript-runtime', 'server'); api.imply('babel-runtime'); From 27c6a52d3582d9629d05967d8bf7ef00c3b39879 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Tue, 15 Aug 2017 16:52:40 +0000 Subject: [PATCH 08/15] Fix coffeescript / coffeescript-compiler dependency versions --- packages/non-core/coffeescript-compiler/package.js | 4 ++-- packages/non-core/coffeescript/package.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/non-core/coffeescript-compiler/package.js b/packages/non-core/coffeescript-compiler/package.js index fc394b7751..e6be016080 100644 --- a/packages/non-core/coffeescript-compiler/package.js +++ b/packages/non-core/coffeescript-compiler/package.js @@ -10,8 +10,8 @@ Npm.depends({ }); Package.onUse(function (api) { - api.use('babel-compiler'); - api.use('ecmascript'); + api.use('babel-compiler@6.19.4'); + api.use('ecmascript@0.8.2'); api.addFiles(['coffeescript-compiler.js'], 'server'); diff --git a/packages/non-core/coffeescript/package.js b/packages/non-core/coffeescript/package.js index 73a68abebb..10f73947c1 100644 --- a/packages/non-core/coffeescript/package.js +++ b/packages/non-core/coffeescript/package.js @@ -10,7 +10,7 @@ Package.describe({ Package.registerBuildPlugin({ name: 'compile-coffeescript', - use: ['caching-compiler', 'coffeescript-compiler', 'ecmascript'], + use: ['caching-compiler@1.1.9', 'ecmascript@0.8.2', 'coffeescript-compiler@1.12.7_1'], sources: ['compile-coffeescript.js'] }); From 6a612f4213acd07e90e16d99127c742f09a88221 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Tue, 15 Aug 2017 18:19:48 +0000 Subject: [PATCH 09/15] Fix coffeescript-compiler version; make more ecmascript-y --- .../non-core/coffeescript-compiler/coffeescript-compiler.js | 2 +- packages/non-core/coffeescript-compiler/package.js | 6 ++++-- packages/non-core/coffeescript/package.js | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/non-core/coffeescript-compiler/coffeescript-compiler.js b/packages/non-core/coffeescript-compiler/coffeescript-compiler.js index ed228594cc..52652d0518 100644 --- a/packages/non-core/coffeescript-compiler/coffeescript-compiler.js +++ b/packages/non-core/coffeescript-compiler/coffeescript-compiler.js @@ -13,7 +13,7 @@ if (Error.METEOR_prepareStackTrace) { // The CompileResult for this CachingCompiler is a {source, sourceMap} object. -CoffeeScriptCompiler = class CoffeeScriptCompiler { +export class CoffeeScriptCompiler { constructor() { this.babelCompiler = new BabelCompiler({ // Prevent Babel from importing helpers from babel-runtime, since diff --git a/packages/non-core/coffeescript-compiler/package.js b/packages/non-core/coffeescript-compiler/package.js index e6be016080..74c02728a7 100644 --- a/packages/non-core/coffeescript-compiler/package.js +++ b/packages/non-core/coffeescript-compiler/package.js @@ -1,7 +1,9 @@ Package.describe({ name: 'coffeescript-compiler', summary: 'Compiler for CoffeeScript code, supporting the coffeescript package', - version: '1.12.7_1' // Tracks version of NPM `coffeescript` module, with _1, _2 etc. + // This version of NPM `coffeescript` module, with _1, _2 etc. + // If you change this, make sure to also update ../coffeescript/package.js to match. + version: '1.12.7_1' }); Npm.depends({ @@ -13,7 +15,7 @@ Package.onUse(function (api) { api.use('babel-compiler@6.19.4'); api.use('ecmascript@0.8.2'); - api.addFiles(['coffeescript-compiler.js'], 'server'); + api.mainModule(['coffeescript-compiler.js'], 'server'); api.export('CoffeeScriptCompiler', 'server'); }); diff --git a/packages/non-core/coffeescript/package.js b/packages/non-core/coffeescript/package.js index 10f73947c1..c5bdc576bc 100644 --- a/packages/non-core/coffeescript/package.js +++ b/packages/non-core/coffeescript/package.js @@ -4,13 +4,14 @@ Package.describe({ // This package version should track the version of the `coffeescript-compiler` // package, because people will likely only have this one added to their apps; // so bumping the version of this package will be how they get newer versions - // of `coffeescript-compiler`. + // of `coffeescript-compiler`. If you change this, make sure to also update + // ../coffeescript-compiler/package.js to match. version: '1.12.7_1' }); Package.registerBuildPlugin({ name: 'compile-coffeescript', - use: ['caching-compiler@1.1.9', 'ecmascript@0.8.2', 'coffeescript-compiler@1.12.7_1'], + use: ['caching-compiler@1.1.9', 'ecmascript@0.8.2', 'coffeescript-compiler@=1.12.7_1'], sources: ['compile-coffeescript.js'] }); From 5626ad7deec61b2a9fab4cdef52c873a4e261c06 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Wed, 16 Aug 2017 18:21:07 +0300 Subject: [PATCH 10/15] JUnit support for `meteor self-test` test runner. (#9014) --- .circleci/config.yml | 44 +++++++++ tools/cli/commands.js | 2 + tools/tool-testing/selftest.js | 158 +++++++++++++++++++++++++++++---- 3 files changed, 189 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f3474cfcd3..38c0968f0e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,6 +17,10 @@ run_env_change: &run_env_change sudo mkdir -p /tmp/core_dumps sudo chmod a+rwx /tmp/core_dumps + # Make a place for JUnit tests to live. + sudo mkdir -p /tmp/results/junit + sudo chmod -R a+rwx /tmp/results/ + # Set the pattern for core dumps, so we can find them. echo kernel.core_pattern="/tmp/core_dumps/core.%e.%p.%h.%t" | \ sudo tee -a /etc/sysctl.conf @@ -167,6 +171,7 @@ jobs: ./meteor self-test \ --exclude "${SELF_TEST_EXCLUDE}" \ --headless \ + --junit /tmp/results/junit/0.xml \ --with-tag "custom-warehouse" no_output_timeout: 20m - run: @@ -174,6 +179,10 @@ jobs: - save_cache: key: meteor-cache <<: *meteor_cache_dirs + - store_test_results: + path: /tmp/results + - store_artifacts: + path: /tmp/results - store_artifacts: path: /tmp/core_dumps - store_artifacts: @@ -195,6 +204,7 @@ jobs: ./meteor self-test \ --exclude "${SELF_TEST_EXCLUDE}" \ --headless \ + --junit /tmp/results/junit/1.xml \ --file '^[a-b]|^c[a-n]|^co[a-l]|^compiler-plugins' \ --without-tag "custom-warehouse" no_output_timeout: 20m @@ -203,6 +213,10 @@ jobs: - save_cache: key: meteor-cache <<: *meteor_cache_dirs + - store_test_results: + path: /tmp/results + - store_artifacts: + path: /tmp/results - store_artifacts: path: /tmp/core_dumps - store_artifacts: @@ -224,6 +238,7 @@ jobs: ./meteor self-test \ --exclude "${SELF_TEST_EXCLUDE}" \ --headless \ + --junit /tmp/results/junit/2.xml \ --file "^co[n-z]|^c[p-z]|^[d-k]" \ --without-tag "custom-warehouse" no_output_timeout: 20m @@ -232,6 +247,10 @@ jobs: - save_cache: key: meteor-cache <<: *meteor_cache_dirs + - store_test_results: + path: /tmp/results + - store_artifacts: + path: /tmp/results - store_artifacts: path: /tmp/core_dumps - store_artifacts: @@ -253,6 +272,7 @@ jobs: ./meteor self-test \ --exclude "${SELF_TEST_EXCLUDE}" \ --headless \ + --junit /tmp/results/junit/3.xml \ --file '^[l-o]' \ --without-tag "custom-warehouse" no_output_timeout: 20m @@ -261,6 +281,10 @@ jobs: - save_cache: key: meteor-cache <<: *meteor_cache_dirs + - store_test_results: + path: /tmp/results + - store_artifacts: + path: /tmp/results - store_artifacts: path: /tmp/core_dumps - store_artifacts: @@ -282,6 +306,7 @@ jobs: ./meteor self-test \ --exclude "${SELF_TEST_EXCLUDE}" \ --headless \ + --junit /tmp/results/junit/4.xml \ --file '^p' \ --without-tag "custom-warehouse" no_output_timeout: 20m @@ -290,6 +315,10 @@ jobs: - save_cache: key: meteor-cache <<: *meteor_cache_dirs + - store_test_results: + path: /tmp/results + - store_artifacts: + path: /tmp/results - store_artifacts: path: /tmp/core_dumps - store_artifacts: @@ -311,6 +340,7 @@ jobs: ./meteor self-test \ --exclude "${SELF_TEST_EXCLUDE}" \ --headless \ + --junit /tmp/results/junit/5.xml \ --file '^run' \ --without-tag "custom-warehouse" no_output_timeout: 20m @@ -319,6 +349,10 @@ jobs: - save_cache: key: meteor-cache <<: *meteor_cache_dirs + - store_test_results: + path: /tmp/results + - store_artifacts: + path: /tmp/results - store_artifacts: path: /tmp/core_dumps - store_artifacts: @@ -340,6 +374,7 @@ jobs: ./meteor self-test \ --exclude "${SELF_TEST_EXCLUDE}" \ --headless \ + --junit /tmp/results/junit/6.xml \ --file '^r(?!un)|^s' \ --without-tag "custom-warehouse" no_output_timeout: 20m @@ -348,6 +383,10 @@ jobs: - save_cache: key: meteor-cache <<: *meteor_cache_dirs + - store_test_results: + path: /tmp/results + - store_artifacts: + path: /tmp/results - store_artifacts: path: /tmp/core_dumps - store_artifacts: @@ -369,6 +408,7 @@ jobs: ./meteor self-test \ --exclude "${SELF_TEST_EXCLUDE}" \ --headless \ + --junit /tmp/results/junit/7.xml \ --file '^[t-z]|^command-line' \ --without-tag "custom-warehouse" no_output_timeout: 20m @@ -377,6 +417,10 @@ jobs: - save_cache: key: meteor-cache <<: *meteor_cache_dirs + - store_test_results: + path: /tmp/results + - store_artifacts: + path: /tmp/results - store_artifacts: path: /tmp/core_dumps - store_artifacts: diff --git a/tools/cli/commands.js b/tools/cli/commands.js index 09b4387dcb..4d76c2b420 100644 --- a/tools/cli/commands.js +++ b/tools/cli/commands.js @@ -2079,6 +2079,7 @@ main.registerCommand({ 'without-tag': { type: String }, // Only run tests with this tag 'with-tag': { type: String }, + junit: { type: String }, }, hidden: true, catalogRefresh: new catalog.Refresh.Never() @@ -2175,6 +2176,7 @@ main.registerCommand({ // other options historyLines: options.history, clients: clients, + junit: options.junit && files.pathResolve(options.junit), 'without-tag': options['without-tag'], 'with-tag': options['with-tag'] }); diff --git a/tools/tool-testing/selftest.js b/tools/tool-testing/selftest.js index 1bf2a21a6b..4935d531d0 100644 --- a/tools/tool-testing/selftest.js +++ b/tools/tool-testing/selftest.js @@ -1,3 +1,4 @@ +import { inspect } from 'util'; import { makeFulfillablePromise } from '../utils/fiber-helpers.js'; import { spawn, execFile } from 'child_process'; import * as files from '../fs/files.js'; @@ -1605,6 +1606,7 @@ class Test { this.fileHash = options.fileHash; this.tags = options.tags || []; this.f = options.func; + this.durationMs = null; this.cleanupHandlers = []; } @@ -1797,6 +1799,16 @@ function getFilteredTests(options) { return new TestList(allTests, tagsToSkip, tagsToMatch, testState); }; +function groupTestsByFile(tests) { + const grouped = {}; + tests.forEach(test => { + grouped[test.file] = grouped[test.file] || []; + grouped[test.file].push(test); + }); + + return grouped; +} + // A TestList is the result of getFilteredTests. It holds the original // list of all tests, the filtered list, and stats on how many tests // were skipped (see generateSkipReport). @@ -1856,8 +1868,120 @@ class TestList { // Mark a test's file as having failures. This prevents // saveTestState from saving its hash as a potentially // "unchanged" file to be skipped in a future run. - notifyFailed(test) { + notifyFailed(test, failureObject) { + // Mark the file that this test lives in as having failures. this.fileInfo[test.file].hasFailures = true; + + // Mark that the specific test failed. + test.failed = true; + + // If there is a failure object, store that for potential output. + if (failureObject) { + test.failureObject = failureObject; + } + } + + saveJUnitOutput(path) { + const grouped = groupTestsByFile(this.filteredTests); + + // We'll form an collection of "testsuites" + const testSuites = []; + + const attrSafe = attr => (attr || "").replace('"', """); + const durationForOutput = durationMs => durationMs / 1000; + + // Each file is a testsuite. + Object.keys(grouped).forEach((file) => { + const testCases = []; + + let countError = 0; + let countFailure = 0; + + // Each test is a "testcase". + grouped[file].forEach((test) => { + const testCaseAttrs = [ + `name="${attrSafe(test.name)}"`, + ]; + + if (test.durationMs) { + testCaseAttrs.push(`time="${durationForOutput(test.durationMs)}"`); + } + + const testCaseAttrsString = testCaseAttrs.join(' '); + + if (test.failed) { + let failureElement = ""; + + if (test.failureObject instanceof TestFailure) { + countFailure++; + + failureElement = [ + ``, + '', + '', + ].join('\n'); + } else if (test.failureObject && test.failureObject.stack) { + countError++; + + failureElement = [ + '', + '', + '', + ].join('\n'); + } else { + countError++; + + failureElement = ''; + } + + testCases.push( + [ + ``, + failureElement, + '', + ].join('\n'), + ); + } else { + testCases.push(``); + } + }); + + const testSuiteAttrs = [ + `name="${file}"`, + `tests="${testCases.length}"`, + `failures="${countFailure}"`, + `errors="${countError}"`, + `time="${durationForOutput(this.durationMs)}"`, + ]; + + const testSuiteAttrsString = testSuiteAttrs.join(' '); + + testSuites.push( + [ + ``, + testCases.join('\n'), + '', + ].join('\n'), + ); + }); + + const xmlHeader = ''; + + const testSuitesString = testSuites.join('\n'); + + files.writeFile(path, + [ + xmlHeader, + ``, + testSuitesString, + ``, + ].join('\n'), + 'utf8', + ); } // If this TestList was constructed with a testState, @@ -1933,17 +2057,11 @@ export function listTests(options) { return; } - const testsGroupedByFile = {}; - testList.filteredTests.forEach(filteredTest => { - testsGroupedByFile[filteredTest.file] = - testsGroupedByFile[filteredTest.file] || []; + const grouped = groupTestsByFile(testList.filteredTests); - testsGroupedByFile[filteredTest.file].push(filteredTest); - }); - - Object.keys(testsGroupedByFile).forEach((file) => { + Object.keys(grouped).forEach((file) => { Console.rawInfo(file + ':\n'); - testsGroupedByFile[file].forEach((test) => { + grouped[file].forEach((test) => { Console.rawInfo(' - ' + test.name + (test.tags.length ? ' [' + test.tags.join(' ') + ']' : '') + '\n'); @@ -1971,6 +2089,8 @@ export function runTests(options) { return 0; } + testList.startTime = new Date; + let totalRun = 0; const failedTests = []; @@ -1980,6 +2100,9 @@ export function runTests(options) { runTest(test); }); + testList.endTime = new Date; + testList.durationMs = testList.endTime - testList.startTime; + function runTest(test, tries = 3) { let failure = null; let startTime; @@ -1997,6 +2120,8 @@ export function runTests(options) { test.cleanup(); } + test.durationMs = +(new Date) - startTime; + if (failure) { Console.error("... fail!", Console.options({ indent: 2 })); @@ -2009,9 +2134,6 @@ export function runTests(options) { return runTest(test, tries); } - failedTests.push(test); - testList.notifyFailed(test); - if (failure instanceof TestFailure) { const frames = parseStackParse(failure).outsideFiber; const relpath = files.pathRelative(files.getCurrentToolsDir(), @@ -2064,16 +2186,22 @@ export function runTests(options) { } else { Console.rawError(" => Test threw exception: " + failure.stack + "\n"); } + + failedTests.push(test); + testList.notifyFailed(test, failure); } else { - const durationMs = +(new Date) - startTime; Console.error( - "... ok (" + durationMs + " ms)", + "... ok (" + test.durationMs + " ms)", Console.options({ indent: 2 })); } } testList.saveTestState(); + if (options.junit) { + testList.saveJUnitOutput(options.junit); + } + if (totalRun > 0) { Console.error(); } From d86b0c712eebc96d08e52663aaf4c9d07b74df2d Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Wed, 16 Aug 2017 18:21:53 +0300 Subject: [PATCH 11/15] Be more considerate of interactive environments and expired tokens. (#9015) If a login token is expired, or no longer valid, make sure that Meteor doesn't just sit there at a login prompt that the user can't see. This currently only applies if `headless` mode is enabled, though a follow-up to this commit might consider setting `headless = true` automatically in a CI environment using environment variables such as: `CI`, `TRAVIS`, `JENKINS_URL`, etc., as the npm-registry-client does in a similar way. See: https://github.com/npm/npm-registry-client/pull/129/files Fixes #8839. --- tools/console/console.js | 4 ++++ tools/meteor-services/deploy.js | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/tools/console/console.js b/tools/console/console.js index f04c2bfd70..4501ae3473 100644 --- a/tools/console/console.js +++ b/tools/console/console.js @@ -584,6 +584,10 @@ class Console extends ConsoleBase { }); } + isInteractive() { + return !this._headless; + } + setPretty(pretty) { // If we're being forced, do nothing. if (FORCE_PRETTY !== undefined) { diff --git a/tools/meteor-services/deploy.js b/tools/meteor-services/deploy.js index e0ff7afcaa..b4f6148730 100644 --- a/tools/meteor-services/deploy.js +++ b/tools/meteor-services/deploy.js @@ -179,6 +179,15 @@ function authedRpc(options) { delete rpcOptions.printDeployURL; if (infoResult.statusCode === 401 && rpcOptions.promptIfAuthFails) { + Console.error("Authentication failed or login token expired."); + + if (!Console.isInteractive()) { + return { + statusCode: 401, + errorMessage: "login failed." + }; + } + // Our authentication didn't validate, so prompt the user to log in // again, and resend the RPC if the login succeeds. var username = Console.readLine({ From 4bd17e3f3075953d8dfb0304a1dc62f1b000e4fa Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Wed, 16 Aug 2017 12:37:31 -0700 Subject: [PATCH 12/15] Fix syntax of api.mainModule --- packages/non-core/coffeescript-compiler/package.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/non-core/coffeescript-compiler/package.js b/packages/non-core/coffeescript-compiler/package.js index 74c02728a7..0696cdfc62 100644 --- a/packages/non-core/coffeescript-compiler/package.js +++ b/packages/non-core/coffeescript-compiler/package.js @@ -15,7 +15,7 @@ Package.onUse(function (api) { api.use('babel-compiler@6.19.4'); api.use('ecmascript@0.8.2'); - api.mainModule(['coffeescript-compiler.js'], 'server'); + api.mainModule('coffeescript-compiler.js', 'server'); api.export('CoffeeScriptCompiler', 'server'); }); From 65c8b481e20d02aa06b994c75d83c7db79ce37df Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 17 Aug 2017 09:44:07 -0400 Subject: [PATCH 13/15] Specify a few more version constraints in coffeescript packages. Small follow-up to #9018. Note (especially @GeoffreyBooth): these version constraints do two things: (1) specify a minimum version, and (2) fix the major version. In other words, the coffeescript package should not need to be republished when we publish new minor versions of these core packages in Meteor 1.5.2 or 1.6. When/if we publish a new major version of these packages, the coffeescript package can simply bump its version constraints, but that probably won't happen any time soon. I think that's reasonable because a major version bump suggests there are some significant changes that need to be acknowledged by dependent packages. --- packages/non-core/coffeescript-test-helper/package.js | 4 ++-- packages/non-core/coffeescript/package.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/non-core/coffeescript-test-helper/package.js b/packages/non-core/coffeescript-test-helper/package.js index b79b10367e..1789bee55a 100644 --- a/packages/non-core/coffeescript-test-helper/package.js +++ b/packages/non-core/coffeescript-test-helper/package.js @@ -1,10 +1,10 @@ Package.describe({ summary: "Used by the coffeescript package's tests", - version: "1.0.8" + version: "1.0.9" }); Package.onUse(function (api) { - api.use('coffeescript', ['client', 'server']); + api.use('coffeescript@1.12.7', ['client', 'server']); api.export('COFFEESCRIPT_EXPORTED'); api.export('COFFEESCRIPT_EXPORTED_ONE_MORE'); api.export('COFFEESCRIPT_EXPORTED_WITH_BACKTICKS'); diff --git a/packages/non-core/coffeescript/package.js b/packages/non-core/coffeescript/package.js index c5bdc576bc..a4b4511c76 100644 --- a/packages/non-core/coffeescript/package.js +++ b/packages/non-core/coffeescript/package.js @@ -24,9 +24,9 @@ Package.onUse(function (api) { // same runtime environment that the 'ecmascript' package provides. // The following api.imply calls should match those in ../../ecmascript/package.js, // except that coffeescript does not api.imply('modules'). - api.imply('ecmascript-runtime', 'server'); - api.imply('babel-runtime'); - api.imply('promise'); + api.imply('ecmascript-runtime@0.4.1', 'server'); + api.imply('babel-runtime@1.0.1'); + api.imply('promise@0.8.9'); }); Package.onTest(function (api) { From 70ab06aa9433f4d70b3455c2607dd811a950d3d9 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 17 Aug 2017 10:02:46 -0400 Subject: [PATCH 14/15] Undo coffeescript-related changes made on release-1.5.2. This will make it easier to merge devel into release-1.5.2, since devel now contains the final verison of these changes, as implemented by @GeoffreyBooth in #9018. Revert "Bump coffeescript package version to 1.13.0." This reverts commit d727ad02a71678eaee668aa37efe29ac87d05c84. Revert "Move coffeescript and coffeescript-test-helper packages back into core. (#8960)" This reverts commit eb3c7dd3443497ee33c04784cf5536c81867ff82. Revert "Split coffeescript package into coffeescript / coffeescript-compiler." This reverts commit 8344cbf59d9fa28bc16bffe6aaf8ced1256b81be. Revert "Instructions for how to test the coffeescript package" This reverts commit 491cbc3bfe98699be1a5ffa12500241cda989af9. --- packages/coffeescript/compile-coffeescript.js | 48 ---- .../non-core/coffeescript-compiler/.gitignore | 1 - .../non-core/coffeescript-compiler/README.md | 17 -- .../coffeescript-compiler.js | 214 --------------- .../non-core/coffeescript-compiler/package.js | 21 -- .../{ => non-core}/coffeescript/.gitignore | 1 - .../plugin/compileCoffeescript}/.gitignore | 0 .../.npm/plugin/compileCoffeescript}/README | 0 .../compileCoffeescript}/npm-shrinkwrap.json | 0 .../{ => non-core}/coffeescript/README.md | 14 +- .../{ => non-core}/coffeescript/package.js | 22 +- .../plugin/compile-coffeescript.js | 252 ++++++++++++++++++ .../coffeescript/tests/bare_test_setup.coffee | 0 .../coffeescript/tests/bare_tests.js | 0 .../tests/coffeescript_module.coffee | 0 .../tests/coffeescript_strict_tests.coffee | 0 .../tests/coffeescript_test_setup.js | 0 .../tests/coffeescript_tests.coffee | 0 .../coffeescript/tests/coffeescript_tests.js | 0 .../coffeescript/tests/es2015_module.js | 0 .../tests/litcoffeescript_tests.coffee.md | 0 .../tests/litcoffeescript_tests.litcoffee | 0 22 files changed, 265 insertions(+), 325 deletions(-) delete mode 100644 packages/coffeescript/compile-coffeescript.js delete mode 100644 packages/non-core/coffeescript-compiler/.gitignore delete mode 100644 packages/non-core/coffeescript-compiler/README.md delete mode 100644 packages/non-core/coffeescript-compiler/coffeescript-compiler.js delete mode 100644 packages/non-core/coffeescript-compiler/package.js rename packages/{ => non-core}/coffeescript/.gitignore (61%) rename packages/non-core/{coffeescript-compiler/.npm/package => coffeescript/.npm/plugin/compileCoffeescript}/.gitignore (100%) rename packages/non-core/{coffeescript-compiler/.npm/package => coffeescript/.npm/plugin/compileCoffeescript}/README (100%) rename packages/non-core/{coffeescript-compiler/.npm/package => coffeescript/.npm/plugin/compileCoffeescript}/npm-shrinkwrap.json (100%) rename packages/{ => non-core}/coffeescript/README.md (88%) rename packages/{ => non-core}/coffeescript/package.js (68%) create mode 100644 packages/non-core/coffeescript/plugin/compile-coffeescript.js rename packages/{ => non-core}/coffeescript/tests/bare_test_setup.coffee (100%) rename packages/{ => non-core}/coffeescript/tests/bare_tests.js (100%) rename packages/{ => non-core}/coffeescript/tests/coffeescript_module.coffee (100%) rename packages/{ => non-core}/coffeescript/tests/coffeescript_strict_tests.coffee (100%) rename packages/{ => non-core}/coffeescript/tests/coffeescript_test_setup.js (100%) rename packages/{ => non-core}/coffeescript/tests/coffeescript_tests.coffee (100%) rename packages/{ => non-core}/coffeescript/tests/coffeescript_tests.js (100%) rename packages/{ => non-core}/coffeescript/tests/es2015_module.js (100%) rename packages/{ => non-core}/coffeescript/tests/litcoffeescript_tests.coffee.md (100%) rename packages/{ => non-core}/coffeescript/tests/litcoffeescript_tests.litcoffee (100%) diff --git a/packages/coffeescript/compile-coffeescript.js b/packages/coffeescript/compile-coffeescript.js deleted file mode 100644 index c8c940b770..0000000000 --- a/packages/coffeescript/compile-coffeescript.js +++ /dev/null @@ -1,48 +0,0 @@ -Plugin.registerCompiler({ - extensions: ['coffee', 'litcoffee', 'coffee.md'] -}, () => new CachedCoffeeScriptCompiler()); - - -// The CompileResult for this CachingCompiler is a {source, sourceMap} object. -class CachedCoffeeScriptCompiler extends CachingCompiler { - constructor() { - super({ - compilerName: 'coffeescript', - defaultCacheSize: 1024*1024*10, - }); - - this.coffeeScriptCompiler = new CoffeeScriptCompiler(); - } - - getCacheKey(inputFile) { - return [ - inputFile.getSourceHash(), - inputFile.getDeclaredExports(), - this.coffeeScriptCompiler.getCompileOptions(inputFile), - ]; - } - - setDiskCacheDirectory(cacheDir) { - this.coffeeScriptCompiler.babelCompiler.setDiskCacheDirectory(cacheDir); - return super.setDiskCacheDirectory(cacheDir); - } - - compileOneFile(inputFile) { - return this.coffeeScriptCompiler.compileOneFile(inputFile); - } - - addCompileResult(inputFile, sourceWithMap) { - inputFile.addJavaScript({ - path: this.coffeeScriptCompiler.outputFilePath(inputFile), - sourcePath: inputFile.getPathInPackage(), - data: sourceWithMap.source, - sourceMap: sourceWithMap.sourceMap, - bare: inputFile.getFileOptions().bare - }); - } - - compileResultSize(sourceWithMap) { - return sourceWithMap.source.length + - this.sourceMapSize(sourceWithMap.sourceMap); - } -} diff --git a/packages/non-core/coffeescript-compiler/.gitignore b/packages/non-core/coffeescript-compiler/.gitignore deleted file mode 100644 index 918ef5d781..0000000000 --- a/packages/non-core/coffeescript-compiler/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.npm diff --git a/packages/non-core/coffeescript-compiler/README.md b/packages/non-core/coffeescript-compiler/README.md deleted file mode 100644 index 2a394f6f5b..0000000000 --- a/packages/non-core/coffeescript-compiler/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# coffeescript-compiler -[Source code of released version](https://github.com/meteor/meteor/tree/master/packages/coffeescript-compiler) | [Source code of development version](https://github.com/meteor/meteor/tree/devel/packages/coffeescript-compiler) -*** - -This package supports the [`coffeescript`](../coffeescript/README.md) package, -and any other packages that wish to compile CoffeeScript code into JavaScript. -Like the [`babel-compiler`](../babel-compiler/README.md) package, the actual -compilation is separated out from the build plugin so that packages besides -the official `coffeescript` package can compile CoffeeScript code. - -### Testing This Package - -Testing the `coffeescript` package also tests this one: - -```bash -./meteor test-packages coffeescript -``` diff --git a/packages/non-core/coffeescript-compiler/coffeescript-compiler.js b/packages/non-core/coffeescript-compiler/coffeescript-compiler.js deleted file mode 100644 index ed228594cc..0000000000 --- a/packages/non-core/coffeescript-compiler/coffeescript-compiler.js +++ /dev/null @@ -1,214 +0,0 @@ -import { BabelCompiler } from 'meteor/babel-compiler'; -import CoffeeScript from 'coffeescript'; -import { SourceMapConsumer, SourceMapGenerator } from 'source-map'; - - -// The CoffeeScript compiler overrides Error.prepareStackTrace, mostly for the -// use of coffee.run which we don't use. This conflicts with the tool's use of -// Error.prepareStackTrace to properly show error messages in linked code. -// Restore the tool's one after CoffeeScript clobbers it at import time. -if (Error.METEOR_prepareStackTrace) { - Error.prepareStackTrace = Error.METEOR_prepareStackTrace; -} - - -// The CompileResult for this CachingCompiler is a {source, sourceMap} object. -CoffeeScriptCompiler = class CoffeeScriptCompiler { - constructor() { - this.babelCompiler = new BabelCompiler({ - // Prevent Babel from importing helpers from babel-runtime, since - // the CoffeeScript plugin does not imply the modules package, which - // means require may not be defined. Note that this in no way - // prevents CoffeeScript projects from using the modules package and - // putting require or import statements within backticks; it just - // won't happen automatically because of Babel. - runtime: false - }); - } - - getCompileOptions(inputFile) { - return { - bare: true, - filename: inputFile.getPathInPackage(), - literate: inputFile.getExtension() !== 'coffee', - // Return a source map. - sourceMap: true, - // This becomes the `file` field of the source map. - generatedFile: '/' + this.outputFilePath(inputFile), - // This becomes the `sources` field of the source map. - sourceFiles: [inputFile.getDisplayPath()], - }; - } - - outputFilePath(inputFile) { - return inputFile.getPathInPackage() + '.js'; - } - - compileOneFile(inputFile) { - const source = inputFile.getContentsAsString(); - const compileOptions = this.getCompileOptions(inputFile); - - let output; - try { - output = CoffeeScript.compile(source, compileOptions); - } catch (e) { - inputFile.error({ - message: e.message, - line: e.location && (e.location.first_line + 1), - column: e.location && (e.location.first_column + 1) - }); - return null; - } - - let sourceMap = JSON.parse(output.v3SourceMap); - sourceMap.sourcesContent = [source]; - - output.js = this.stripExportedVars( - output.js, - inputFile.getDeclaredExports().map(e => e.name) - ); - - // CoffeeScript contains a handful of features that output as ES2015+, - // such as modules, generator functions, for…of, and tagged template - // literals. Because they’re too varied to detect, pass all CoffeeScript - // compiler output through the Babel compiler. - const doubleRoastedCoffee = - this.babelCompiler.processOneFileForTarget(inputFile, output.js); - - if (doubleRoastedCoffee != null && - doubleRoastedCoffee.data != null) { - output.js = doubleRoastedCoffee.data; - - const coffeeSourceMap = doubleRoastedCoffee.sourceMap; - - if (coffeeSourceMap) { - // Reference the compiled CoffeeScript file so that `applySourceMap` - // below can match it with the source map produced by the CoffeeScript - // compiler. - coffeeSourceMap.sources[0] = '/' + this.outputFilePath(inputFile); - - // Combine the original CoffeeScript source map with the one - // produced by this.babelCompiler.processOneFileForTarget. - const smg = SourceMapGenerator.fromSourceMap( - new SourceMapConsumer(coffeeSourceMap) - ); - smg.applySourceMap(new SourceMapConsumer(sourceMap)); - sourceMap = smg.toJSON(); - } else { - // If the .coffee file is contained by a node_modules directory, - // then BabelCompiler will not transpile it, and there will be - // no sourceMap, but that's fine because the original - // CoffeeScript sourceMap will still be valid. - } - } - - return this.addSharedHeader(output.js, sourceMap); - } - - stripExportedVars(source, exports) { - if (!exports || !exports.length) - return source; - const lines = source.split("\n"); - - // We make the following assumptions, based on the output of CoffeeScript - // 1.7.1. - // - The var declaration in question is not indented and is the first such - // var declaration. (CoffeeScript only produces one var line at each - // scope and there's only one top-level scope.) All relevant variables - // are actually on this line. - // - The user hasn't used a ###-comment containing a line that looks like - // a var line, to produce something like - // /* bla - // var foo; - // */ - // before an actual var line. (ie, we do NOT attempt to figure out if - // we're inside a /**/ comment, which is produced by ### comments.) - // - The var in question is not assigned to in the declaration, nor are any - // other vars on this line. (CoffeeScript does produce some assignments - // but only for internal helpers generated by CoffeeScript, and they end - // up on subsequent lines.) - // XXX relax these assumptions by doing actual JS parsing (eg with jsparse). - // I'd do this now, but there's no easy way to "unparse" a jsparse AST. - // Or alternatively, hack the compiler to allow us to specify unbound - // symbols directly. - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - const match = /^var (.+)([,;])$/.exec(line); - if (!match) - continue; - - // If there's an assignment on this line, we assume that there are ONLY - // assignments and that the var we are looking for is not declared. (Part - // of our strong assumption about the layout of this code.) - if (match[1].indexOf('=') !== -1) - continue; - - // We want to replace the line with something no shorter, so that all - // records in the source map continue to point at valid - // characters. - function replaceLine(x) { - if (x.length >= lines[i].length) { - lines[i] = x; - } else { - lines[i] = x + new Array(1 + (lines[i].length - x.length)).join(' '); - } - } - - let vars = match[1].split(', ').filter(v => exports.indexOf(v) === -1); - if (vars.length) { - replaceLine('var ' + vars.join(', ') + match[2]); - } else { - // We got rid of all the vars on this line. Drop the whole line if this - // didn't continue to the next line, otherwise keep just the 'var '. - if (match[2] === ';') - replaceLine(''); - else - replaceLine('var'); - } - break; - } - - return lines.join('\n'); - } - - addSharedHeader(source, sourceMap) { - // We want the symbol "share" to be visible to all CoffeeScript files in the - // package (and shared between them), but not visible to JavaScript - // files. (That's because we don't want to introduce two competing ways to - // make package-local variables into JS ("share" vs assigning to non-var - // variables).) The following hack accomplishes that: "__coffeescriptShare" - // will be visible at the package level and "share" at the file level. This - // should work both in "package" mode where __coffeescriptShare will be added - // as a var in the package closure, and in "app" mode where it will end up as - // a global. - // - // This ends in a newline to make the source map easier to adjust. - const header = ("__coffeescriptShare = typeof __coffeescriptShare === 'object' " + - "? __coffeescriptShare : {}; " + - "var share = __coffeescriptShare;\n"); - - // If the file begins with "use strict", we need to keep that as the first - // statement. - const processedSource = source.replace(/^(?:((['"])use strict\2;)\n)?/, (match, useStrict) => { - if (match) { - // There's a "use strict"; we keep this as the first statement and insert - // our header at the end of the line that it's on. This doesn't change - // line numbers or the part of the line that previous may have been - // annotated, so we don't need to update the source map. - return useStrict + ' ' + header; - } else { - // There's no use strict, so we can just add the header at the very - // beginning. This adds a line to the file, so we update the source map to - // add a single un-annotated line to the beginning. - sourceMap.mappings = ';' + sourceMap.mappings; - return header; - } - }); - return { - source: processedSource, - sourceMap: sourceMap - }; - } - -} diff --git a/packages/non-core/coffeescript-compiler/package.js b/packages/non-core/coffeescript-compiler/package.js deleted file mode 100644 index fc394b7751..0000000000 --- a/packages/non-core/coffeescript-compiler/package.js +++ /dev/null @@ -1,21 +0,0 @@ -Package.describe({ - name: 'coffeescript-compiler', - summary: 'Compiler for CoffeeScript code, supporting the coffeescript package', - version: '1.12.7_1' // Tracks version of NPM `coffeescript` module, with _1, _2 etc. -}); - -Npm.depends({ - 'coffeescript': '1.12.7', - 'source-map': '0.5.6' -}); - -Package.onUse(function (api) { - api.use('babel-compiler'); - api.use('ecmascript'); - - api.addFiles(['coffeescript-compiler.js'], 'server'); - - api.export('CoffeeScriptCompiler', 'server'); -}); - -// See `coffeescript` package for tests. diff --git a/packages/coffeescript/.gitignore b/packages/non-core/coffeescript/.gitignore similarity index 61% rename from packages/coffeescript/.gitignore rename to packages/non-core/coffeescript/.gitignore index c01644335c..677a6fc263 100644 --- a/packages/coffeescript/.gitignore +++ b/packages/non-core/coffeescript/.gitignore @@ -1,2 +1 @@ .build* -.npm diff --git a/packages/non-core/coffeescript-compiler/.npm/package/.gitignore b/packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/.gitignore similarity index 100% rename from packages/non-core/coffeescript-compiler/.npm/package/.gitignore rename to packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/.gitignore diff --git a/packages/non-core/coffeescript-compiler/.npm/package/README b/packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/README similarity index 100% rename from packages/non-core/coffeescript-compiler/.npm/package/README rename to packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/README diff --git a/packages/non-core/coffeescript-compiler/.npm/package/npm-shrinkwrap.json b/packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/npm-shrinkwrap.json similarity index 100% rename from packages/non-core/coffeescript-compiler/.npm/package/npm-shrinkwrap.json rename to packages/non-core/coffeescript/.npm/plugin/compileCoffeescript/npm-shrinkwrap.json diff --git a/packages/coffeescript/README.md b/packages/non-core/coffeescript/README.md similarity index 88% rename from packages/coffeescript/README.md rename to packages/non-core/coffeescript/README.md index b23b98c88d..711ff02abd 100644 --- a/packages/coffeescript/README.md +++ b/packages/non-core/coffeescript/README.md @@ -44,16 +44,10 @@ Here's how CoffeeScript works with Meteor's namespacing. for a value that is shared between all CoffeeScript code in a package, but doesn't escape that package. +Heavy CoffeeScript users, please let us know how this arrangement +works for you, whether `share` is helpful for you, and anything else +you'd like to see changed. + ### Modules and CoffeeScript See [Modules » CoffeeScript Syntax](http://docs.meteor.com/packages/modules.html#CoffeeScript). - -### Testing This Package - -Follow the [instructions](https://github.com/meteor/meteor/blob/devel/Development.md#tests) -to check out the Meteor repo and run `test-packages`. -Once you can do that successfully, to test the `coffeescript` package run: - -```bash -./meteor test-packages coffeescript -``` diff --git a/packages/coffeescript/package.js b/packages/non-core/coffeescript/package.js similarity index 68% rename from packages/coffeescript/package.js rename to packages/non-core/coffeescript/package.js index 9189fe8984..298d1c8a51 100644 --- a/packages/coffeescript/package.js +++ b/packages/non-core/coffeescript/package.js @@ -1,25 +1,21 @@ Package.describe({ - name: 'coffeescript', - summary: 'Javascript dialect with fewer braces and semicolons', - // This package version used to track the version of the NPM `coffeescript` - // module, but now the Meteor package `coffeescript-compiler` tracks that - // version; so in order for this to appear newer than the previous package - // version 1.12.6_1, we jump to 10+. - version: '1.13.0' + summary: "Javascript dialect with fewer braces and semicolons", + version: "1.12.7_1" }); Package.registerBuildPlugin({ - name: 'compile-coffeescript', - use: ['caching-compiler', 'coffeescript-compiler', 'ecmascript'], - sources: ['compile-coffeescript.js'], + name: "compileCoffeescript", + use: ['caching-compiler', 'ecmascript'], + sources: ['plugin/compile-coffeescript.js'], npmDependencies: { - 'coffeescript': '1.12.7', - 'source-map': '0.5.6' + "coffeescript": "1.12.7", + "source-map": "0.5.6" } }); Package.onUse(function (api) { api.use('isobuild:compiler-plugin@1.0.0'); + api.use('babel-compiler'); // Because the CoffeeScript plugin now calls // BabelCompiler.prototype.processOneFileForTarget for any ES2015+ @@ -27,7 +23,7 @@ Package.onUse(function (api) { // same runtime environment that the 'ecmascript' package provides. // The following api.imply calls should match those in ../ecmascript/package.js, // except that coffeescript does not api.imply('modules'). - api.imply('ecmascript-runtime', 'server'); + api.imply('ecmascript-runtime'); api.imply('babel-runtime'); api.imply('promise'); }); diff --git a/packages/non-core/coffeescript/plugin/compile-coffeescript.js b/packages/non-core/coffeescript/plugin/compile-coffeescript.js new file mode 100644 index 0000000000..03abcbe842 --- /dev/null +++ b/packages/non-core/coffeescript/plugin/compile-coffeescript.js @@ -0,0 +1,252 @@ +import { + SourceMapConsumer, + SourceMapGenerator, +} from 'source-map'; +import coffee from 'coffeescript'; +import { BabelCompiler } from 'meteor/babel-compiler'; + +// The CoffeeScript compiler overrides Error.prepareStackTrace, mostly for the +// use of coffee.run which we don't use. This conflicts with the tool's use of +// Error.prepareStackTrace to properly show error messages in linked code. +// Restore the tool's one after CoffeeScript clobbers it at import time. +if (Error.METEOR_prepareStackTrace) { + Error.prepareStackTrace = Error.METEOR_prepareStackTrace; +} + +Plugin.registerCompiler({ + extensions: ['coffee', 'litcoffee', 'coffee.md'] +}, () => new CoffeeCompiler()); + +// The CompileResult for this CachingCompiler is a {source, sourceMap} object. + +export class CoffeeCompiler extends CachingCompiler { + constructor() { + super({ + compilerName: 'coffeescript', + defaultCacheSize: 1024*1024*10, + }); + + this.babelCompiler = new BabelCompiler({ + // Prevent Babel from importing helpers from babel-runtime, since + // the CoffeeScript plugin does not imply the modules package, which + // means require may not be defined. Note that this in no way + // prevents CoffeeScript projects from using the modules package and + // putting require or import statements within backticks; it just + // won't happen automatically because of Babel. + runtime: false + }); + } + + _getCompileOptions(inputFile) { + return { + bare: true, + filename: inputFile.getPathInPackage(), + literate: inputFile.getExtension() !== 'coffee', + // Return a source map. + sourceMap: true, + // This becomes the "file" field of the source map. + generatedFile: '/' + this._outputFilePath(inputFile), + // This becomes the "sources" field of the source map. + sourceFiles: [inputFile.getDisplayPath()], + }; + } + + _outputFilePath(inputFile) { + return inputFile.getPathInPackage() + '.js'; + } + + getCacheKey(inputFile) { + return [ + inputFile.getSourceHash(), + inputFile.getDeclaredExports(), + this._getCompileOptions(inputFile), + ]; + } + + setDiskCacheDirectory(cacheDir) { + this.babelCompiler.setDiskCacheDirectory(cacheDir); + return super.setDiskCacheDirectory(cacheDir); + } + + compileOneFile(inputFile) { + const source = inputFile.getContentsAsString(); + const compileOptions = this._getCompileOptions(inputFile); + + let output; + try { + output = coffee.compile(source, compileOptions); + } catch (e) { + inputFile.error({ + message: e.message, + line: e.location && (e.location.first_line + 1), + column: e.location && (e.location.first_column + 1) + }); + return null; + } + + let sourceMap = JSON.parse(output.v3SourceMap); + sourceMap.sourcesContent = [source]; + + output.js = stripExportedVars( + output.js, + inputFile.getDeclaredExports().map(e => e.name) + ); + + // CoffeeScript contains a handful of features that output as ES2015+, + // such as modules, generator functions, for…of, and tagged template + // literals. Because they’re too varied to detect, pass all CoffeeScript + // compiler output through the Babel compiler. + const doubleRoastedCoffee = + this.babelCompiler.processOneFileForTarget(inputFile, output.js); + + if (doubleRoastedCoffee != null && + doubleRoastedCoffee.data != null) { + output.js = doubleRoastedCoffee.data; + + const coffeeSourceMap = doubleRoastedCoffee.sourceMap; + + if (coffeeSourceMap) { + // Reference the compiled CoffeeScript file so that `applySourceMap` + // below can match it with the source map produced by the CoffeeScript + // compiler. + coffeeSourceMap.sources[0] = '/' + this._outputFilePath(inputFile); + + // Combine the original CoffeeScript source map with the one + // produced by this.babelCompiler.processOneFileForTarget. + const smg = SourceMapGenerator.fromSourceMap( + new SourceMapConsumer(coffeeSourceMap) + ); + smg.applySourceMap(new SourceMapConsumer(sourceMap)); + sourceMap = smg.toJSON(); + } else { + // If the .coffee file is contained by a node_modules directory, + // then BabelCompiler will not transpile it, and there will be + // no sourceMap, but that's fine because the original + // CoffeeScript sourceMap will still be valid. + } + } + + return addSharedHeader(output.js, sourceMap); + } + + addCompileResult(inputFile, sourceWithMap) { + inputFile.addJavaScript({ + path: this._outputFilePath(inputFile), + sourcePath: inputFile.getPathInPackage(), + data: sourceWithMap.source, + sourceMap: sourceWithMap.sourceMap, + bare: inputFile.getFileOptions().bare + }); + } + + compileResultSize(sourceWithMap) { + return sourceWithMap.source.length + + this.sourceMapSize(sourceWithMap.sourceMap); + } +} + +function stripExportedVars(source, exports) { + if (!exports || !exports.length) + return source; + const lines = source.split("\n"); + + // We make the following assumptions, based on the output of CoffeeScript + // 1.7.1. + // - The var declaration in question is not indented and is the first such + // var declaration. (CoffeeScript only produces one var line at each + // scope and there's only one top-level scope.) All relevant variables + // are actually on this line. + // - The user hasn't used a ###-comment containing a line that looks like + // a var line, to produce something like + // /* bla + // var foo; + // */ + // before an actual var line. (ie, we do NOT attempt to figure out if + // we're inside a /**/ comment, which is produced by ### comments.) + // - The var in question is not assigned to in the declaration, nor are any + // other vars on this line. (CoffeeScript does produce some assignments + // but only for internal helpers generated by CoffeeScript, and they end + // up on subsequent lines.) + // XXX relax these assumptions by doing actual JS parsing (eg with jsparse). + // I'd do this now, but there's no easy way to "unparse" a jsparse AST. + // Or alternatively, hack the compiler to allow us to specify unbound + // symbols directly. + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + const match = /^var (.+)([,;])$/.exec(line); + if (!match) + continue; + + // If there's an assignment on this line, we assume that there are ONLY + // assignments and that the var we are looking for is not declared. (Part + // of our strong assumption about the layout of this code.) + if (match[1].indexOf('=') !== -1) + continue; + + // We want to replace the line with something no shorter, so that all + // records in the source map continue to point at valid + // characters. + function replaceLine(x) { + if (x.length >= lines[i].length) { + lines[i] = x; + } else { + lines[i] = x + new Array(1 + (lines[i].length - x.length)).join(' '); + } + } + + let vars = match[1].split(', ').filter(v => exports.indexOf(v) === -1); + if (vars.length) { + replaceLine('var ' + vars.join(', ') + match[2]); + } else { + // We got rid of all the vars on this line. Drop the whole line if this + // didn't continue to the next line, otherwise keep just the 'var '. + if (match[2] === ';') + replaceLine(''); + else + replaceLine('var'); + } + break; + } + + return lines.join('\n'); +} + +function addSharedHeader(source, sourceMap) { + // We want the symbol "share" to be visible to all CoffeeScript files in the + // package (and shared between them), but not visible to JavaScript + // files. (That's because we don't want to introduce two competing ways to + // make package-local variables into JS ("share" vs assigning to non-var + // variables).) The following hack accomplishes that: "__coffeescriptShare" + // will be visible at the package level and "share" at the file level. This + // should work both in "package" mode where __coffeescriptShare will be added + // as a var in the package closure, and in "app" mode where it will end up as + // a global. + // + // This ends in a newline to make the source map easier to adjust. + const header = ("__coffeescriptShare = typeof __coffeescriptShare === 'object' " + + "? __coffeescriptShare : {}; " + + "var share = __coffeescriptShare;\n"); + + // If the file begins with "use strict", we need to keep that as the first + // statement. + const processedSource = source.replace(/^(?:((['"])use strict\2;)\n)?/, (match, useStrict) => { + if (match) { + // There's a "use strict"; we keep this as the first statement and insert + // our header at the end of the line that it's on. This doesn't change + // line numbers or the part of the line that previous may have been + // annotated, so we don't need to update the source map. + return useStrict + ' ' + header; + } else { + // There's no use strict, so we can just add the header at the very + // beginning. This adds a line to the file, so we update the source map to + // add a single un-annotated line to the beginning. + sourceMap.mappings = ';' + sourceMap.mappings; + return header; + } + }); + return { + source: processedSource, + sourceMap: sourceMap + }; +} diff --git a/packages/coffeescript/tests/bare_test_setup.coffee b/packages/non-core/coffeescript/tests/bare_test_setup.coffee similarity index 100% rename from packages/coffeescript/tests/bare_test_setup.coffee rename to packages/non-core/coffeescript/tests/bare_test_setup.coffee diff --git a/packages/coffeescript/tests/bare_tests.js b/packages/non-core/coffeescript/tests/bare_tests.js similarity index 100% rename from packages/coffeescript/tests/bare_tests.js rename to packages/non-core/coffeescript/tests/bare_tests.js diff --git a/packages/coffeescript/tests/coffeescript_module.coffee b/packages/non-core/coffeescript/tests/coffeescript_module.coffee similarity index 100% rename from packages/coffeescript/tests/coffeescript_module.coffee rename to packages/non-core/coffeescript/tests/coffeescript_module.coffee diff --git a/packages/coffeescript/tests/coffeescript_strict_tests.coffee b/packages/non-core/coffeescript/tests/coffeescript_strict_tests.coffee similarity index 100% rename from packages/coffeescript/tests/coffeescript_strict_tests.coffee rename to packages/non-core/coffeescript/tests/coffeescript_strict_tests.coffee diff --git a/packages/coffeescript/tests/coffeescript_test_setup.js b/packages/non-core/coffeescript/tests/coffeescript_test_setup.js similarity index 100% rename from packages/coffeescript/tests/coffeescript_test_setup.js rename to packages/non-core/coffeescript/tests/coffeescript_test_setup.js diff --git a/packages/coffeescript/tests/coffeescript_tests.coffee b/packages/non-core/coffeescript/tests/coffeescript_tests.coffee similarity index 100% rename from packages/coffeescript/tests/coffeescript_tests.coffee rename to packages/non-core/coffeescript/tests/coffeescript_tests.coffee diff --git a/packages/coffeescript/tests/coffeescript_tests.js b/packages/non-core/coffeescript/tests/coffeescript_tests.js similarity index 100% rename from packages/coffeescript/tests/coffeescript_tests.js rename to packages/non-core/coffeescript/tests/coffeescript_tests.js diff --git a/packages/coffeescript/tests/es2015_module.js b/packages/non-core/coffeescript/tests/es2015_module.js similarity index 100% rename from packages/coffeescript/tests/es2015_module.js rename to packages/non-core/coffeescript/tests/es2015_module.js diff --git a/packages/coffeescript/tests/litcoffeescript_tests.coffee.md b/packages/non-core/coffeescript/tests/litcoffeescript_tests.coffee.md similarity index 100% rename from packages/coffeescript/tests/litcoffeescript_tests.coffee.md rename to packages/non-core/coffeescript/tests/litcoffeescript_tests.coffee.md diff --git a/packages/coffeescript/tests/litcoffeescript_tests.litcoffee b/packages/non-core/coffeescript/tests/litcoffeescript_tests.litcoffee similarity index 100% rename from packages/coffeescript/tests/litcoffeescript_tests.litcoffee rename to packages/non-core/coffeescript/tests/litcoffeescript_tests.litcoffee From 27d3584b79a7ed2b8271b18aee226864ad82cde2 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 17 Aug 2017 10:11:04 -0400 Subject: [PATCH 15/15] Bump package versions for 1.5.2-beta.11 release. --- packages/accounts-base/package.js | 2 +- packages/babel-compiler/package.js | 2 +- packages/boilerplate-generator-tests/package.js | 2 +- packages/boilerplate-generator/package.js | 2 +- packages/ddp-client/package.js | 2 +- packages/ejson/package.js | 2 +- packages/meteor-tool/package.js | 2 +- packages/minimongo/package.js | 2 +- packages/modules/package.js | 2 +- packages/mongo-dev-server/package.js | 2 +- packages/mongo/package.js | 2 +- packages/promise/package.js | 2 +- packages/webapp/package.js | 2 +- scripts/admin/meteor-release-experimental.json | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/accounts-base/package.js b/packages/accounts-base/package.js index d729045898..b2c98f89ed 100644 --- a/packages/accounts-base/package.js +++ b/packages/accounts-base/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "A user account system", - version: "1.3.2-beta152.10" + version: "1.3.2-beta152.11" }); Package.onUse(function (api) { diff --git a/packages/babel-compiler/package.js b/packages/babel-compiler/package.js index 8c98c263ae..791093df8d 100644 --- a/packages/babel-compiler/package.js +++ b/packages/babel-compiler/package.js @@ -6,7 +6,7 @@ Package.describe({ // isn't possible because you can't publish a non-recommended // release with package versions that don't have a pre-release // identifier at the end (eg, -dev) - version: '6.20.0-beta152.10' + version: '6.20.0-beta152.11' }); Npm.depends({ diff --git a/packages/boilerplate-generator-tests/package.js b/packages/boilerplate-generator-tests/package.js index 77965af310..a5abab904b 100644 --- a/packages/boilerplate-generator-tests/package.js +++ b/packages/boilerplate-generator-tests/package.js @@ -2,7 +2,7 @@ Package.describe({ // These tests are in a separate package so that we can Npm.depend on // parse5, a html parsing library. summary: "Tests for the boilerplate-generator package", - version: '1.0.0-beta152.10', + version: '1.0.0-beta152.11', documentation: null }); diff --git a/packages/boilerplate-generator/package.js b/packages/boilerplate-generator/package.js index 25426a1a51..2153f9910d 100644 --- a/packages/boilerplate-generator/package.js +++ b/packages/boilerplate-generator/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Generates the boilerplate html from program's manifest", - version: '1.2.0-beta152.10' + version: '1.2.0-beta152.11' }); Package.onUse(api => { diff --git a/packages/ddp-client/package.js b/packages/ddp-client/package.js index f000900705..ed09a716f7 100644 --- a/packages/ddp-client/package.js +++ b/packages/ddp-client/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's latency-compensated distributed data client", - version: '2.1.0-beta152.10', + version: '2.1.0-beta152.11', documentation: null }); diff --git a/packages/ejson/package.js b/packages/ejson/package.js index 63149e9d97..ef7c0704fe 100644 --- a/packages/ejson/package.js +++ b/packages/ejson/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: 'Extended and Extensible JSON library', - version: '1.0.14-beta152.10' + version: '1.0.14-beta152.11' }); Package.onUse(function onUse(api) { diff --git a/packages/meteor-tool/package.js b/packages/meteor-tool/package.js index 1073314d0d..862e79d72c 100644 --- a/packages/meteor-tool/package.js +++ b/packages/meteor-tool/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "The Meteor command-line tool", - version: "1.5.2-beta.10" + version: "1.5.2-beta.11" }); Package.includeTool(); diff --git a/packages/minimongo/package.js b/packages/minimongo/package.js index 42401394f2..97014ae4e9 100644 --- a/packages/minimongo/package.js +++ b/packages/minimongo/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Meteor's client-side datastore: a port of MongoDB to Javascript", - version: '1.3.0-beta152.10' + version: '1.3.0-beta152.11' }); Package.onUse(api => { diff --git a/packages/modules/package.js b/packages/modules/package.js index d994253027..1b4357a32a 100644 --- a/packages/modules/package.js +++ b/packages/modules/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "modules", - version: "0.10.0-beta152.10", + version: "0.10.0-beta152.11", summary: "CommonJS module system", documentation: "README.md" }); diff --git a/packages/mongo-dev-server/package.js b/packages/mongo-dev-server/package.js index 41b87513b9..0968fc5ddd 100644 --- a/packages/mongo-dev-server/package.js +++ b/packages/mongo-dev-server/package.js @@ -3,7 +3,7 @@ Package.describe({ documentation: 'README.md', name: 'mongo-dev-server', summary: 'Start MongoDB alongside Meteor, in development mode.', - version: '1.0.1-beta152.10', + version: '1.0.1-beta152.11', }); Package.onUse(function (api) { diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 5b0b1657e1..d608e8bb15 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -9,7 +9,7 @@ Package.describe({ summary: "Adaptor for using MongoDB and Minimongo over DDP", - version: '1.2.0-beta152.10' + version: '1.2.0-beta152.11' }); Npm.depends({ diff --git a/packages/promise/package.js b/packages/promise/package.js index 04f4f11d9f..007d95c79b 100644 --- a/packages/promise/package.js +++ b/packages/promise/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "promise", - version: "0.9.0-beta152.10", + version: "0.9.0-beta152.11", summary: "ECMAScript 2015 Promise polyfill with Fiber support", git: "https://github.com/meteor/promise", documentation: "README.md" diff --git a/packages/webapp/package.js b/packages/webapp/package.js index 3944610a39..eb531f73c7 100644 --- a/packages/webapp/package.js +++ b/packages/webapp/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "Serves a Meteor app over HTTP", - version: '1.3.18-beta152.10' + version: '1.3.18-beta152.11' }); Npm.depends({connect: "2.30.2", diff --git a/scripts/admin/meteor-release-experimental.json b/scripts/admin/meteor-release-experimental.json index 14d0812763..6c670fb3d9 100644 --- a/scripts/admin/meteor-release-experimental.json +++ b/scripts/admin/meteor-release-experimental.json @@ -1,6 +1,6 @@ { "track": "METEOR", - "version": "1.5.2-beta.10", + "version": "1.5.2-beta.11", "recommended": false, "official": false, "description": "Meteor"