From 78e9b9de793c13b494ea84c7f0f9c86708dd2b2c Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Tue, 13 Sep 2016 14:31:07 -0700 Subject: [PATCH 01/46] [REFACTOR] stubs now gets imports provided via set, rather than extracting them itself. --- lib/imports-for.js | 87 ++++++++++++++++++++++++++++++++++++++++++ lib/stub-generator.js | 6 ++- lib/stubs.js | 89 +------------------------------------------ test/stubs-test.js | 17 +++++---- 4 files changed, 103 insertions(+), 96 deletions(-) create mode 100644 lib/imports-for.js diff --git a/lib/imports-for.js b/lib/imports-for.js new file mode 100644 index 0000000..ccb2def --- /dev/null +++ b/lib/imports-for.js @@ -0,0 +1,87 @@ +'use strict'; + +var acorn = require('acorn'); +module.exports = importsFor; +function importsFor(src, fullPath) { + // In ember cli 2.x, src is es5 code, whereas in ember cli 1.x, src is still es6 code. + + // First, try to parse as es5 code. Es6 code will return an error. + var result = tryCatch(parseEs5, src); + // If a syntax error is thrown, we assume this is because src is es6 code. + if (result instanceof Error) { + result = tryCatch(parseEs6, src); + } + + // If result is still an error, there must have been a parse error + if (result instanceof Error) { + throw new Error('Error parsing code while looking for "npm:" imports: ' + result.stack || result + ' in file: ' + fullPath); + } + + return result; +} + +function forEachNode(node, visit) { + if (node && typeof node === 'object' && !node._eb_visited) { + node._eb_visited = true; + visit(node); + var keys = Object.keys(node); + for (var i=0; i < keys.length; i++) { + forEachNode(node[keys[i]], visit); + } + } +} + +function head(array) { + return array[0]; +} + +function parseEs5(src) { + var imports = {}; + + var ast = acorn.parse(src); + + forEachNode(ast, function(entry) { + if (entry.type === 'CallExpression' && entry.callee.name === 'define') { + head(entry.arguments.filter(function(item) { + return item.type === 'ArrayExpression'; + })).elements.filter(function(element) { + return element.value.slice(0, 4) === 'npm:'; + }).forEach(function(element) { + imports[element.value.slice(4)] = true; + }); + } + }); + return imports; +} + +function parseEs6(src) { + var imports = {}; + + var ast = acorn.parse(src, { + ecmaVersion: 6, + sourceType: 'module' + }); + + forEachNode(ast, function(entry) { + if (entry.type === 'ImportDeclaration') { + var source = entry.source.value; + if (source.slice(0,4) === 'npm:') { + if (entry.kind === 'named') { + throw new Error("ember-browserify doesn't support named imports (you tried to import " + entry.specifiers[0].id.name + " from " + source); + } + imports[source.slice(4)] = true; + } + } + }); + + return imports; +} + +function tryCatch(func, arg) { + try { + return func.call(null, arg); + } + catch(e) { + return e; + } +} diff --git a/lib/stub-generator.js b/lib/stub-generator.js index 6574d4a..af23cae 100644 --- a/lib/stub-generator.js +++ b/lib/stub-generator.js @@ -5,6 +5,7 @@ var Stubs = require('./stubs'); var fs = require('fs'); var md5Hex = require('md5-hex'); var debug = require('debug')('ember-browserify:stub-generator:'); +var importsFor = require('./imports-for'); module.exports = StubGenerator; function StubGenerator(inputTree, options) { @@ -54,7 +55,10 @@ StubGenerator.prototype.build = function() { switch (operation) { case 'unlink': this.stubs.delete(fullPath); break; case 'create': - case 'change': this.stubs.set(fullPath, fs.readFileSync(fullPath)); break; + case 'change': + var content = fs.readFileSync(fullPath, 'UTF8'); + this.stubs.set(fullPath, importsFor(content)); + break; } }, this); diff --git a/lib/stubs.js b/lib/stubs.js index 6fa0803..d5730cb 100644 --- a/lib/stubs.js +++ b/lib/stubs.js @@ -1,5 +1,4 @@ module.exports = Stub; -var acorn = require('acorn'); var debug = require('debug')('ember-browserify:stubs'); function Stub() { @@ -25,10 +24,10 @@ Stub.prototype.delete = function(fullPath) { } }; -Stub.prototype.set = function(fullPath, content) { +Stub.prototype.set = function(fullPath, imports) { this._isDirty = true; var start = Date.now(); - this._map[fullPath] = importsFor(content, fullPath); + this._map[fullPath] = imports; this._stats.importTime += (Date.now() - start); }; @@ -59,87 +58,3 @@ Stub.prototype.toAMD = function() { return this._amd; }; - -function importsFor(src, fullPath) { - // In ember cli 2.x, src is es5 code, whereas in ember cli 1.x, src is still es6 code. - - // First, try to parse as es5 code. Es6 code will return an error. - var result = tryCatch(parseEs5, src); - // If a syntax error is thrown, we assume this is because src is es6 code. - if (result instanceof Error) { - result = tryCatch(parseEs6, src); - } - - // If result is still an error, there must have been a parse error - if (result instanceof Error) { - throw new Error('Error parsing code while looking for "npm:" imports: ' + result.stack || result + ' in file: ' + fullPath); - } - - return result; -} - -function forEachNode(node, visit) { - if (node && typeof node === 'object' && !node._eb_visited) { - node._eb_visited = true; - visit(node); - var keys = Object.keys(node); - for (var i=0; i < keys.length; i++) { - forEachNode(node[keys[i]], visit); - } - } -} - -function head(array) { - return array[0]; -} - -function parseEs5(src) { - var imports = {}; - - var ast = acorn.parse(src); - - forEachNode(ast, function(entry) { - if (entry.type === 'CallExpression' && entry.callee.name === 'define') { - head(entry.arguments.filter(function(item) { - return item.type === 'ArrayExpression'; - })).elements.filter(function(element) { - return element.value.slice(0, 4) === 'npm:'; - }).forEach(function(element) { - imports[element.value.slice(4)] = true; - }); - } - }); - return imports; -} - -function parseEs6(src) { - var imports = {}; - - var ast = acorn.parse(src, { - ecmaVersion: 6, - sourceType: 'module' - }); - - forEachNode(ast, function(entry) { - if (entry.type === 'ImportDeclaration') { - var source = entry.source.value; - if (source.slice(0,4) === 'npm:') { - if (entry.kind === 'named') { - throw new Error("ember-browserify doesn't support named imports (you tried to import " + entry.specifiers[0].id.name + " from " + source); - } - imports[source.slice(4)] = true; - } - } - }); - - return imports; -} - -function tryCatch(func, arg) { - try { - return func.call(null, arg); - } - catch(e) { - return e; - } -} diff --git a/test/stubs-test.js b/test/stubs-test.js index 4d69474..4334b3b 100644 --- a/test/stubs-test.js +++ b/test/stubs-test.js @@ -1,6 +1,7 @@ var Stubs = require('../lib/stubs'); var chai = require('chai'); var expect = chai.expect; // jshint ignore:line +var importsFor = require('../lib/imports-for'); describe('Stubs', function() { var stubs; @@ -18,7 +19,7 @@ describe('Stubs', function() { describe('basic', function() { describe('es6', function() { beforeEach(function() { - stubs.set('foo/bar', 'import asdf from "npm:asdf"'); + stubs.set('foo/bar', importsFor('import asdf from "npm:asdf"')); }); it('toAMD', function() { @@ -31,7 +32,7 @@ describe('Stubs', function() { }); it('set', function() { - stubs.set('foo', 'import asdf from "npm:asdf"'); + stubs.set('foo', importsFor('import asdf from "npm:asdf"')); expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})"); }); @@ -48,12 +49,12 @@ describe('Stubs', function() { it('delete then add back', function() { stubs.delete('foo/bar'); expect(stubs.toAMD()).to.eql(""); - stubs.set('foo', 'import asdf from "npm:asdf"'); + stubs.set('foo', importsFor('import asdf from "npm:asdf"')); expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})"); }); it('set', function() { - stubs.set('apple', 'import apple from "npm:foo"'); + stubs.set('apple', importsFor('import apple from "npm:foo"')); expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})\ndefine('npm:foo', function(){ return { 'default': require('foo')};})"); }); }); @@ -61,7 +62,7 @@ describe('Stubs', function() { describe('es5', function() { beforeEach(function() { - stubs.set('foo/bar', 'define("asdf", ["npm:asdf"], function() { });'); + stubs.set('foo/bar', importsFor('define("asdf", ["npm:asdf"], function() { });')); }); it('toAMD', function() { @@ -74,7 +75,7 @@ describe('Stubs', function() { }); it('set', function() { - stubs.set('foo', 'define("asdf", ["npm:asdf"], function() { });'); + stubs.set('foo', importsFor('define("asdf", ["npm:asdf"], function() { });')); expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})"); }); @@ -91,12 +92,12 @@ describe('Stubs', function() { it('delete then add back', function() { stubs.delete('foo/bar'); expect(stubs.toAMD()).to.eql(""); - stubs.set('foo', 'define("asdf", ["npm:asdf"], function() { });'); + stubs.set('foo', importsFor('define("asdf", ["npm:asdf"], function() { });')); expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})"); }); it('set', function() { - stubs.set('apple', 'define("apple", ["npm:foo"], function() { });'); + stubs.set('apple', importsFor('define("apple", ["npm:foo"], function() { });')); expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})\ndefine('npm:foo', function(){ return { 'default': require('foo')};})"); }); }); From eae97f36e7dca5931f3958431035f7cfa28deef3 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Tue, 13 Sep 2016 16:02:16 -0700 Subject: [PATCH 02/46] first pass of import/export identifier mangling @nathanhammond & @stefanpenner --- lib/stub-generator.js | 46 +++++- lib/stubs.js | 7 +- package.json | 2 +- test/fixtures/stubs/es5/inner/other.js | 2 +- test/fixtures/stubs/es5/sample.js | 2 +- test/imports-for-test.js | 18 +++ test/stubs-test.js | 32 ++--- test/test.js | 192 +++++++++---------------- 8 files changed, 153 insertions(+), 148 deletions(-) create mode 100644 test/imports-for-test.js diff --git a/lib/stub-generator.js b/lib/stub-generator.js index af23cae..04cf8cf 100644 --- a/lib/stub-generator.js +++ b/lib/stub-generator.js @@ -32,10 +32,11 @@ StubGenerator.prototype.constructor = StubGenerator; StubGenerator.prototype.build = function() { var start = Date.now(); var inputPath = this.inputPaths[0]; + var outputPath = this.outputPath; var previous = this._previousTree; // get patchset - var input = walkSync.entries(inputPath, [ '**/*.js' ]); + var input = walkSync.entries(inputPath); debug('input: %d', input.length); @@ -50,14 +51,39 @@ StubGenerator.prototype.build = function() { patchset.forEach(function(patch) { var operation = patch[0]; var path = patch[1]; - var fullPath = inputPath + '/' + path; + var fullInputPath = inputPath + '/' + path; + var fullOutputPath = outputPath + '/' + path; switch (operation) { - case 'unlink': this.stubs.delete(fullPath); break; + case 'unlink': + if (!/\.js$/.test(path)) { break; } + // TODO: only add files that required rewriting + fs.unlinkSync(fullOutputPath); + this.stubs.delete(fullInputPath); + break; + case 'mkdir': fs.mkdirSync(fullOutputPath); break; + case 'rmdir': fs.rmdir(fullOutputPath); break; case 'create': case 'change': - var content = fs.readFileSync(fullPath, 'UTF8'); - this.stubs.set(fullPath, importsFor(content)); + if (!/\.js$/.test(path)) { break; } + + + var content = fs.readFileSync(fullInputPath, 'UTF8'); + var version = '3.0.0'; // TODO: get real identifier + var data = {}; + var imports = importsFor(content); + + Object.keys(imports).forEach(function(key) { + data[key] = { + version: version + }; + }); + + // TODO: only add files that required rewriting + fs.writeFileSync(fullOutputPath, rewriteImports(content, data)); + + this.stubs.set(fullInputPath, data); + break; } }, this); @@ -70,6 +96,16 @@ StubGenerator.prototype.build = function() { debug('build in %dms', Date.now() - start); }; +function rewriteImports(content, data) { + // TODO: real AST printing might be a good plan.. + Object.keys(data).forEach(function(name) { + var version = data[name].version; + content = content.replace(new RegExp('["]npm:' + name + '["]', 'g'), '"npm:' + name + '@' + version + '"'); + content = content.replace(new RegExp('[\']npm:' + name + '[\']', 'g'), '\'npm:' + name + '@' + version + '\''); + }); + return content; +} + StubGenerator.prototype.writeFileIfContentChanged = function(fullPath, content) { var previous = this._fileToChecksumMap[fullPath]; var next = md5Hex(content); diff --git a/lib/stubs.js b/lib/stubs.js index d5730cb..42140a5 100644 --- a/lib/stubs.js +++ b/lib/stubs.js @@ -47,13 +47,14 @@ Stub.prototype.toAMD = function() { // find unique modules Object.keys(this._map).forEach(function(filePath) { (Object.keys(this._map[filePath] || {})).forEach(function(moduleName) { - imports[moduleName] = true; - }); + imports[moduleName] = this._map[filePath][moduleName]; + }, this); }, this); // generate stub this._amd = Object.keys(imports).sort().map(function(moduleName) { - return "define('npm:" + moduleName + "', function(){ return { 'default': require('" + moduleName + "')};})"; + var version = imports[moduleName].version; + return "define('npm:" + moduleName + '@' + version + "', function(){ return { 'default': require('" + moduleName + "')};})"; }).join("\n"); return this._amd; diff --git a/package.json b/package.json index 052ca74..2a07406 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "fs-tree-diff": "^0.5.0", "lodash": "^4.5.1", "md5-hex": "^1.3.0", - "mkdirp": "^0.5.0", + "mkdirp": "^0.5.1", "promise-map-series": "^0.2.0", "quick-temp": "^0.1.2", "rimraf": "^2.2.8", diff --git a/test/fixtures/stubs/es5/inner/other.js b/test/fixtures/stubs/es5/inner/other.js index 6bd002e..3cd9b3d 100644 --- a/test/fixtures/stubs/es5/inner/other.js +++ b/test/fixtures/stubs/es5/inner/other.js @@ -1,3 +1,3 @@ -define('foo', ['exports', 'npm:x', 'npm:y'], function(exports, _npmX, _npmY) { +define('inner/other', ['exports', 'npm:x', 'npm:y'], function(exports, _npmX, _npmY) { }); diff --git a/test/fixtures/stubs/es5/sample.js b/test/fixtures/stubs/es5/sample.js index 2b94680..c1f0874 100644 --- a/test/fixtures/stubs/es5/sample.js +++ b/test/fixtures/stubs/es5/sample.js @@ -1,3 +1,3 @@ -define('foo', ['exports', 'npm:broccoli'], function(exports, Broccoli) { +define('sample', ['exports', 'npm:broccoli'], function(exports, Broccoli) { exports['default'] = Broccoli; }); diff --git a/test/imports-for-test.js b/test/imports-for-test.js new file mode 100644 index 0000000..c7df9c4 --- /dev/null +++ b/test/imports-for-test.js @@ -0,0 +1,18 @@ +var expect = require('chai').expect; +var importsFor = require('../lib/imports-for'); + +describe('importsFor', function() { + it('parses ES6', function() { + expect(importsFor('import asdf from "npm:asdf"')).to.eql({ asdf: true }); + expect(importsFor('import asdf from "npm:asdf"')).to.eql({ asdf: true }); + expect(importsFor('import asdf from "npm:asdf"')).to.eql({ asdf: true }); + expect(importsFor('import apple from "npm:foo"')).to.eql({ foo: true }); + }) + + it('parses AMD (ES5)', function() { + expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); + expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); + expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); + expect(importsFor('define("apple", ["npm:foo"], function() { });')).to.eql({ foo: true}); + }); +}); diff --git a/test/stubs-test.js b/test/stubs-test.js index 4334b3b..1d665f3 100644 --- a/test/stubs-test.js +++ b/test/stubs-test.js @@ -19,11 +19,11 @@ describe('Stubs', function() { describe('basic', function() { describe('es6', function() { beforeEach(function() { - stubs.set('foo/bar', importsFor('import asdf from "npm:asdf"')); + stubs.set('foo/bar', { asdf: { version: '1.0.0' }}); }); it('toAMD', function() { - expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})"); + expect(stubs.toAMD()).to.eql("define('npm:asdf@1.0.0', function(){ return { 'default': require('asdf')};})"); }); it('delete', function() { @@ -32,8 +32,8 @@ describe('Stubs', function() { }); it('set', function() { - stubs.set('foo', importsFor('import asdf from "npm:asdf"')); - expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})"); + stubs.set('foo', { asdf: { version: '42' }}); + expect(stubs.toAMD()).to.eql("define('npm:asdf@42', function(){ return { 'default': require('asdf')};})"); }); describe('cache busting', function() { @@ -49,24 +49,24 @@ describe('Stubs', function() { it('delete then add back', function() { stubs.delete('foo/bar'); expect(stubs.toAMD()).to.eql(""); - stubs.set('foo', importsFor('import asdf from "npm:asdf"')); - expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})"); + stubs.set('foo', { asdf: { version: 1 }}); + expect(stubs.toAMD()).to.eql("define('npm:asdf@1', function(){ return { 'default': require('asdf')};})"); }); it('set', function() { - stubs.set('apple', importsFor('import apple from "npm:foo"')); - expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})\ndefine('npm:foo', function(){ return { 'default': require('foo')};})"); + stubs.set('apple', { asdf: { version: 'OMG' }, foo: { version: '22' }}); + expect(stubs.toAMD()).to.eql("define('npm:asdf@OMG', function(){ return { 'default': require('asdf')};})\ndefine('npm:foo@22', function(){ return { 'default': require('foo')};})"); }); }); }); describe('es5', function() { beforeEach(function() { - stubs.set('foo/bar', importsFor('define("asdf", ["npm:asdf"], function() { });')); + stubs.set('foo/bar', { asdf: { version: '3.0.0' }}); }); it('toAMD', function() { - expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})"); + expect(stubs.toAMD()).to.eql("define('npm:asdf@3.0.0', function(){ return { 'default': require('asdf')};})"); }); it('delete', function() { @@ -75,8 +75,8 @@ describe('Stubs', function() { }); it('set', function() { - stubs.set('foo', importsFor('define("asdf", ["npm:asdf"], function() { });')); - expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})"); + stubs.set('foo', { asdf: { version: '3.0.0' }}); + expect(stubs.toAMD()).to.eql("define('npm:asdf@3.0.0', function(){ return { 'default': require('asdf')};})"); }); describe('cache busting', function() { @@ -92,13 +92,13 @@ describe('Stubs', function() { it('delete then add back', function() { stubs.delete('foo/bar'); expect(stubs.toAMD()).to.eql(""); - stubs.set('foo', importsFor('define("asdf", ["npm:asdf"], function() { });')); - expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})"); + stubs.set('foo', { asdf: { version: '1'}}); + expect(stubs.toAMD()).to.eql("define('npm:asdf@1', function(){ return { 'default': require('asdf')};})"); }); it('set', function() { - stubs.set('apple', importsFor('define("apple", ["npm:foo"], function() { });')); - expect(stubs.toAMD()).to.eql("define('npm:asdf', function(){ return { 'default': require('asdf')};})\ndefine('npm:foo', function(){ return { 'default': require('foo')};})"); + stubs.set('apple', { foo: { version: 16 }}); + expect(stubs.toAMD()).to.eql("define('npm:asdf@3.0.0', function(){ return { 'default': require('asdf')};})\ndefine('npm:foo@16', function(){ return { 'default': require('foo')};})"); }); }); }); diff --git a/test/test.js b/test/test.js index bd40f25..de03b20 100644 --- a/test/test.js +++ b/test/test.js @@ -15,44 +15,47 @@ var path = require('path'); var broccoli = require('broccoli'); var quickTemp = require('quick-temp'); var copy = require('copy-dereference').sync; +var walkSync = require('walk-sync'); var FIRST = { keys: [ - 'npm:broccoli', - 'npm:x', - 'npm:y', + 'sample', + 'inner/other', + 'npm:broccoli@3.0.0', + 'npm:x@3.0.0', + 'npm:y@3.0.0', ] }; var SECOND = { keys: [ - 'npm:broccoli', - 'npm:x', - 'npm:y', - 'npm:something-new', + 'npm:broccoli@3.0.0', + 'npm:x@3.0.0', + 'npm:y@3.0.0', + 'npm:something-new@3.0.0', ] }; var THIRD = { keys: [ - 'npm:x', - 'npm:y', + 'npm:x@3.0.0', + 'npm:y@3.0.0', ] }; var FOURTH = { keys: [ - 'npm:additional-thing', - 'npm:broccoli', - 'npm:x', - 'npm:y', + 'npm:additional-thing@3.0.0', + 'npm:broccoli@3.0.0', + 'npm:x@3.0.0', + 'npm:y@3.0.0', ] }; var FIFTH = { keys: [ - 'npm:broccoli', - 'npm:y', + 'npm:broccoli@3.0.0', + 'npm:y@3.0.0', ] }; @@ -124,7 +127,7 @@ describe('Ember CLI 2.x Stub Generator', function() { }); describe('input', function() { - it('only supports 1 inputTree', function() { + it('supports 1 inputTree', function() { expect(function() { new StubGenerator(); }).to.throw(/Expects one inputTree/); @@ -144,10 +147,12 @@ describe('Ember CLI 2.x Stub Generator', function() { return builder.build().then(function(result) { loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); expect(loader.entries).to.have.keys(FIRST.keys); - var broc = loader.require('npm:broccoli'); + var broc = loader.require('npm:broccoli@3.0.0'); expect(broc).to.have.keys(['default']); expect(broc.default).to.have.keys([ @@ -185,10 +190,19 @@ describe('Ember CLI 2.x Stub Generator', function() { builder = new broccoli.Builder(tree); return builder.build().then(function(result) { loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); expect(loader.entries).to.have.keys(FIRST.keys); - var broc = loader.require('npm:broccoli'); + var broc = loader.require('npm:broccoli@3.0.0'); expect(broc).to.have.keys(['default']); expect(broc.default).to.have.keys([ @@ -206,6 +220,13 @@ describe('Ember CLI 2.x Stub Generator', function() { fs.writeFileSync(src.inputTree + '/new.js', "define(\"fizz\", [\"exports\", \"npm:something-new\"], function(exports, SomethingNew) {});"); return builder.build(); }).then(function(result){ + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'new.js', + 'sample.js', + ]); loader.reload(result.directory + '/browserify_stubs.js'); @@ -218,6 +239,8 @@ describe('Ember CLI 2.x Stub Generator', function() { builder = new broccoli.Builder(tree); return builder.build().then(function(result) { loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); expect(loader.entries).to.have.keys(FIRST.keys); fs.unlinkSync(src.inputTree + '/sample.js'); @@ -235,6 +258,15 @@ describe('Ember CLI 2.x Stub Generator', function() { builder = new broccoli.Builder(tree); return builder.build().then(function(result) { loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); expect(loader.entries).to.have.keys(FIRST.keys); @@ -244,6 +276,13 @@ describe('Ember CLI 2.x Stub Generator', function() { return builder.build(); }).then(function(result){ + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + loader.reload(result.directory + '/browserify_stubs.js'); expect(loader.entries).to.have.keys(FOURTH.keys); @@ -255,9 +294,18 @@ describe('Ember CLI 2.x Stub Generator', function() { builder = new broccoli.Builder(tree); return builder.build().then(function(result) { loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); expect(loader.entries).to.have.keys(FIRST.keys); + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + var was = "define('foo', ['exports', 'npm:y'], function(exports, _npmY) {});"; fs.writeFileSync(src.inputTree + '/inner/other.js', was); @@ -265,116 +313,18 @@ describe('Ember CLI 2.x Stub Generator', function() { }).then(function(result){ loader.reload(result.directory + '/browserify_stubs.js'); - expect(loader.entries).to.have.keys(FIFTH.keys); - }); - }); -}); - -describe('Ember CLI 1.x Stub Generator', function() { - var src = {}; - var builder; - - var loader; - - beforeEach(function() { - loader = new Loader(); - quickTemp.makeOrRemake(src, 'tmp'); - src.inputTree = src.tmp + '/inputTree'; - copy(__dirname + '/fixtures/stubs/es6', src.inputTree); - }); - - afterEach(function() { - loader.teardown(); - - if (src.tmp) { - quickTemp.remove(src, 'tmp'); - } - if (builder) { - return builder.cleanup(); - } - }); - - it('generates stub file', function() { - var tree = new StubGenerator(src.inputTree); - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - - expect(loader.entries).to.have.keys(FIRST.keys); - }); - }); - - it('adds deps from new file', function() { - var tree = new StubGenerator(src.inputTree); - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - expect(loader.entries).to.have.keys(FIRST.keys); - fs.writeFileSync(src.inputTree + '/new.js', "import SomethingNew from \"npm:something-new\"\n"); - return builder.build(); - }).then(function(result){ - loader.reload(result.directory + '/browserify_stubs.js'); - expect(loader.entries).to.have.keys([ - 'npm:broccoli', - 'npm:x', - 'npm:y', - 'npm:something-new' - ]); - }); - }); - - it('removes deps from deleted file', function() { - var tree = new StubGenerator(src.inputTree); - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - expect(loader.entries).to.have.keys(FIRST.keys); - fs.unlinkSync(src.inputTree + '/sample.js'); - return builder.build(); - }).then(function(result){ - loader.reload(result.directory + '/browserify_stubs.js'); - expect(loader.entries).to.have.keys([ - 'npm:x', - 'npm:y' + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', ]); - }); - }); - - it('adds deps in modified file', function() { - var tree = new StubGenerator(src.inputTree); - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - expect(loader.entries).to.have.keys(FIRST.keys); - var was = fs.readFileSync(src.inputTree + '/sample.js'); - was += "\nimport Additional from 'npm:additional-thing';"; - fs.writeFileSync(src.inputTree + '/sample.js', was); - return builder.build(); - }).then(function(result){ - loader.reload(result.directory + '/browserify_stubs.js'); - expect(loader.entries).to.have.keys(FOURTH.keys); - }); - }); - it('removes deps in modified file', function() { - var tree = new StubGenerator(src.inputTree); - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - expect(loader.entries).to.have.keys(FIRST.keys); - var was = fs.readFileSync(src.inputTree + '/inner/other.js', 'utf-8'); - was = was.split("\n").slice(1).join("\n"); - - fs.writeFileSync(src.inputTree + '/inner/other.js', was); - return builder.build(); - }).then(function(result){ - loader.reload(result.directory + '/browserify_stubs.js'); expect(loader.entries).to.have.keys(FIFTH.keys); }); }); }); - describe('CachingBrowserify', function() { var src = {}; var builder; From c388ac6404ad820fb7c7e722c909427f86570001 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Tue, 13 Sep 2016 16:12:38 -0700 Subject: [PATCH 03/46] more ember-cli 1.x related removals --- lib/imports-for.js | 44 ++------------------------ test/fixtures/stubs/es6/inner/other.js | 2 -- test/fixtures/stubs/es6/sample.js | 2 -- test/imports-for-test.js | 7 ---- 4 files changed, 2 insertions(+), 53 deletions(-) delete mode 100644 test/fixtures/stubs/es6/inner/other.js delete mode 100644 test/fixtures/stubs/es6/sample.js diff --git a/lib/imports-for.js b/lib/imports-for.js index ccb2def..cff76c0 100644 --- a/lib/imports-for.js +++ b/lib/imports-for.js @@ -3,16 +3,8 @@ var acorn = require('acorn'); module.exports = importsFor; function importsFor(src, fullPath) { - // In ember cli 2.x, src is es5 code, whereas in ember cli 1.x, src is still es6 code. + var result = parse(src); - // First, try to parse as es5 code. Es6 code will return an error. - var result = tryCatch(parseEs5, src); - // If a syntax error is thrown, we assume this is because src is es6 code. - if (result instanceof Error) { - result = tryCatch(parseEs6, src); - } - - // If result is still an error, there must have been a parse error if (result instanceof Error) { throw new Error('Error parsing code while looking for "npm:" imports: ' + result.stack || result + ' in file: ' + fullPath); } @@ -35,7 +27,7 @@ function head(array) { return array[0]; } -function parseEs5(src) { +function parse(src) { var imports = {}; var ast = acorn.parse(src); @@ -53,35 +45,3 @@ function parseEs5(src) { }); return imports; } - -function parseEs6(src) { - var imports = {}; - - var ast = acorn.parse(src, { - ecmaVersion: 6, - sourceType: 'module' - }); - - forEachNode(ast, function(entry) { - if (entry.type === 'ImportDeclaration') { - var source = entry.source.value; - if (source.slice(0,4) === 'npm:') { - if (entry.kind === 'named') { - throw new Error("ember-browserify doesn't support named imports (you tried to import " + entry.specifiers[0].id.name + " from " + source); - } - imports[source.slice(4)] = true; - } - } - }); - - return imports; -} - -function tryCatch(func, arg) { - try { - return func.call(null, arg); - } - catch(e) { - return e; - } -} diff --git a/test/fixtures/stubs/es6/inner/other.js b/test/fixtures/stubs/es6/inner/other.js deleted file mode 100644 index 8cb4e3b..0000000 --- a/test/fixtures/stubs/es6/inner/other.js +++ /dev/null @@ -1,2 +0,0 @@ -import X from "npm:x"; -import "npm:y"; \ No newline at end of file diff --git a/test/fixtures/stubs/es6/sample.js b/test/fixtures/stubs/es6/sample.js deleted file mode 100644 index 3ab7d72..0000000 --- a/test/fixtures/stubs/es6/sample.js +++ /dev/null @@ -1,2 +0,0 @@ -import Broccoli from "npm:broccoli"; -export default Broccoli; \ No newline at end of file diff --git a/test/imports-for-test.js b/test/imports-for-test.js index c7df9c4..1189c03 100644 --- a/test/imports-for-test.js +++ b/test/imports-for-test.js @@ -2,13 +2,6 @@ var expect = require('chai').expect; var importsFor = require('../lib/imports-for'); describe('importsFor', function() { - it('parses ES6', function() { - expect(importsFor('import asdf from "npm:asdf"')).to.eql({ asdf: true }); - expect(importsFor('import asdf from "npm:asdf"')).to.eql({ asdf: true }); - expect(importsFor('import asdf from "npm:asdf"')).to.eql({ asdf: true }); - expect(importsFor('import apple from "npm:foo"')).to.eql({ foo: true }); - }) - it('parses AMD (ES5)', function() { expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); From b4e6a04dfc04e40e7605c5f30513eef210b59b88 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Tue, 13 Sep 2016 16:18:33 -0700 Subject: [PATCH 04/46] allow StubGenerator -> CachingBrowserify to overwrite output from app. This is to allow StubGenerator to rewrite app files which import npm modules. Allowing them to uniquely address Browserify modules. --- lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index 3b2e06a..1b2e047 100644 --- a/lib/index.js +++ b/lib/index.js @@ -79,7 +79,7 @@ module.exports = { tree = new MergeTrees([ tree, new CachingBrowserify(new StubGenerator(tree), options) - ]); + ], { overwrite: true }); } return tree; } From b0387a9392b8599fe6ff14041a53fad61da5a304 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Tue, 13 Sep 2016 16:18:52 -0700 Subject: [PATCH 05/46] remove more ember-cli 1.x stuff --- lib/index.js | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lib/index.js b/lib/index.js index 1b2e047..1de3206 100644 --- a/lib/index.js +++ b/lib/index.js @@ -22,10 +22,9 @@ module.exports = { var checker = new VersionChecker(this); var emberCliVersion = checker.for('ember-cli', 'npm'); - var newImportApi; - if (emberCliVersion.isAbove('1.13.8')) { - newImportApi = true; + if (emberCliVersion.satisfies('< 2.0.0')) { + throw new TypeError('ember-browserify@^2.0.0 no longer supports ember-cli versions less then 2.0.0.'); } app = findHost.call(this); @@ -43,15 +42,9 @@ module.exports = { app.import('browserify/browserify.js'); if (app.tests && (process.env.BROWSERIFY_TESTS || this.options.browserifyOptions.tests)) { - if (newImportApi) { - app.import('browserify-tests/browserify.js', { - type: 'test' - }); - } else { - app.import({ - test: 'browserify-tests/browserify.js' - }); - } + app.import('browserify-tests/browserify.js', { + type: 'test' + }); } if (app.importWhitelistFilters) { From d29a10e1bbdd7bde0fc24adca4fc23dafebfc04a Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Tue, 13 Sep 2016 16:39:48 -0700 Subject: [PATCH 06/46] StubGenerator output needs to be merged into tree * browserify_stubs needs to be provided to CachingBrowserify * everything else, is merged with the existing tree. This should only include the files that contain `npm:x` import statements. --- lib/index.js | 19 +++++++++++++++++-- package.json | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/index.js b/lib/index.js index 1de3206..810443c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -14,6 +14,8 @@ function findHost() { return app; } +var Funnel = require('broccoli-funnel'); + module.exports = { name: 'ember-browserify', @@ -69,11 +71,24 @@ module.exports = { options = Object.create(this.options); options.outputFile = outputFile; + + // produces: + // - browserify_stubs.js (for CachingBrowserify, to build a bundle); + // - any inputFiles that had npm imports + var stubs = new StubGenerator(tree, options); + tree = new MergeTrees([ + // original files tree, - new CachingBrowserify(new StubGenerator(tree), options) + + // copies rewritten inputFiles over (overwriting original files) + new Funnel(stubs, { exclude: ['browserify_stubs.js'] }), + + // produces browserify bundle, named options.outputFile (defaulting to browserify/browserify.js) + new CachingBrowserify(stubs, options) ], { overwrite: true }); } + return tree; } -}; + }; diff --git a/package.json b/package.json index 2a07406..fb835c5 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "dependencies": { "acorn": "^2.6.4", "broccoli-caching-writer": "^3.0.3", + "broccoli-funnel": "^1.0.6", "broccoli-kitchen-sink-helpers": "^0.3.1", "broccoli-merge-trees": "^1.1.2", "broccoli-plugin": "^1.2.1", From 1532cac78427508cb60aef7f2c9d49883d6eb43d Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Tue, 13 Sep 2016 17:22:48 -0700 Subject: [PATCH 07/46] resolve actual versions --- lib/index.js | 1 + lib/stub-generator.js | 23 +++++++++---- package.json | 2 ++ .../node_modules/additional-thing/index.js | 0 .../additional-thing/package.json | 4 +++ .../modules/node_modules/broccoli/index.js | 0 .../node_modules/broccoli/package.json | 4 +++ .../modules/node_modules/package.json | 0 .../node_modules/something-new/index.js | 0 .../node_modules/something-new/package.json | 4 +++ test/fixtures/modules/node_modules/x/index.js | 0 .../modules/node_modules/x/package.json | 4 +++ test/fixtures/modules/node_modules/y/index.js | 0 .../modules/node_modules/y/package.json | 4 +++ test/test.js | 34 +++++++++++++------ 15 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 test/fixtures/modules/node_modules/additional-thing/index.js create mode 100644 test/fixtures/modules/node_modules/additional-thing/package.json create mode 100644 test/fixtures/modules/node_modules/broccoli/index.js create mode 100644 test/fixtures/modules/node_modules/broccoli/package.json create mode 100644 test/fixtures/modules/node_modules/package.json create mode 100644 test/fixtures/modules/node_modules/something-new/index.js create mode 100644 test/fixtures/modules/node_modules/something-new/package.json create mode 100644 test/fixtures/modules/node_modules/x/index.js create mode 100644 test/fixtures/modules/node_modules/x/package.json create mode 100644 test/fixtures/modules/node_modules/y/index.js create mode 100644 test/fixtures/modules/node_modules/y/package.json diff --git a/lib/index.js b/lib/index.js index 810443c..5181252 100644 --- a/lib/index.js +++ b/lib/index.js @@ -71,6 +71,7 @@ module.exports = { options = Object.create(this.options); options.outputFile = outputFile; + options.basedir = this.app.root; // produces: // - browserify_stubs.js (for CachingBrowserify, to build a bundle); diff --git a/lib/stub-generator.js b/lib/stub-generator.js index 04cf8cf..7adbe5f 100644 --- a/lib/stub-generator.js +++ b/lib/stub-generator.js @@ -8,7 +8,8 @@ var debug = require('debug')('ember-browserify:stub-generator:'); var importsFor = require('./imports-for'); module.exports = StubGenerator; -function StubGenerator(inputTree, options) { +function StubGenerator(inputTree, _options) { + var options = _options || {}; if (!(this instanceof StubGenerator)) { return new StubGenerator([inputTree], options); } @@ -19,6 +20,7 @@ function StubGenerator(inputTree, options) { Plugin.call(this, [inputTree], options); this._persistentOutput = true; + this.basedir = options.basedir; // setup persistent state this._previousTree = new FSTree(); @@ -69,15 +71,14 @@ StubGenerator.prototype.build = function() { var content = fs.readFileSync(fullInputPath, 'UTF8'); - var version = '3.0.0'; // TODO: get real identifier var data = {}; var imports = importsFor(content); - Object.keys(imports).forEach(function(key) { - data[key] = { - version: version + Object.keys(imports).forEach(function(name) { + data[name] = { + version: versionForModuleName(name, this.basedir) }; - }); + }, this); // TODO: only add files that required rewriting fs.writeFileSync(fullOutputPath, rewriteImports(content, data)); @@ -119,3 +120,13 @@ StubGenerator.prototype.writeFileIfContentChanged = function(fullPath, content) this._fileToChecksumMap[fullPath] = next; // update map } }; + +function versionForModuleName(name, basedir) { + var resolve = require('resolve'); + var findUp = require('find-up'); + var path = require('path'); + var fs = require('fs'); + + var cwd = path.dirname(resolve.sync(name, { basedir: basedir })); + return JSON.parse(fs.readFileSync(findUp.sync('package.json', { cwd: cwd }), 'UTF8')).version; +} diff --git a/package.json b/package.json index fb835c5..e866201 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "debug": "^2.2.0", "derequire": "^2.0.3", "ember-cli-version-checker": "^1.1.4", + "find-up": "^1.1.2", "fs-tree": "^1.0.0", "fs-tree-diff": "^0.5.0", "lodash": "^4.5.1", @@ -48,6 +49,7 @@ "mkdirp": "^0.5.1", "promise-map-series": "^0.2.0", "quick-temp": "^0.1.2", + "resolve": "^1.1.7", "rimraf": "^2.2.8", "rsvp": "^3.0.14", "symlink-or-copy": "^1.0.0", diff --git a/test/fixtures/modules/node_modules/additional-thing/index.js b/test/fixtures/modules/node_modules/additional-thing/index.js new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/modules/node_modules/additional-thing/package.json b/test/fixtures/modules/node_modules/additional-thing/package.json new file mode 100644 index 0000000..62df650 --- /dev/null +++ b/test/fixtures/modules/node_modules/additional-thing/package.json @@ -0,0 +1,4 @@ +{ + "name": "additional-thing", + "version": "2.2.0" +} diff --git a/test/fixtures/modules/node_modules/broccoli/index.js b/test/fixtures/modules/node_modules/broccoli/index.js new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/modules/node_modules/broccoli/package.json b/test/fixtures/modules/node_modules/broccoli/package.json new file mode 100644 index 0000000..38d493e --- /dev/null +++ b/test/fixtures/modules/node_modules/broccoli/package.json @@ -0,0 +1,4 @@ +{ + "name": "broccoli", + "version": "3.0.0" +} diff --git a/test/fixtures/modules/node_modules/package.json b/test/fixtures/modules/node_modules/package.json new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/modules/node_modules/something-new/index.js b/test/fixtures/modules/node_modules/something-new/index.js new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/modules/node_modules/something-new/package.json b/test/fixtures/modules/node_modules/something-new/package.json new file mode 100644 index 0000000..e7767df --- /dev/null +++ b/test/fixtures/modules/node_modules/something-new/package.json @@ -0,0 +1,4 @@ +{ + "name": "something-new", + "version": "2.2.2" +} diff --git a/test/fixtures/modules/node_modules/x/index.js b/test/fixtures/modules/node_modules/x/index.js new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/modules/node_modules/x/package.json b/test/fixtures/modules/node_modules/x/package.json new file mode 100644 index 0000000..c573c1d --- /dev/null +++ b/test/fixtures/modules/node_modules/x/package.json @@ -0,0 +1,4 @@ +{ + "name": "x", + "version": "3.0.0" +} diff --git a/test/fixtures/modules/node_modules/y/index.js b/test/fixtures/modules/node_modules/y/index.js new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/modules/node_modules/y/package.json b/test/fixtures/modules/node_modules/y/package.json new file mode 100644 index 0000000..677f431 --- /dev/null +++ b/test/fixtures/modules/node_modules/y/package.json @@ -0,0 +1,4 @@ +{ + "name": "y", + "version": "3.0.0" +} diff --git a/test/test.js b/test/test.js index de03b20..5c971f8 100644 --- a/test/test.js +++ b/test/test.js @@ -32,7 +32,7 @@ var SECOND = { 'npm:broccoli@3.0.0', 'npm:x@3.0.0', 'npm:y@3.0.0', - 'npm:something-new@3.0.0', + 'npm:something-new@2.2.2', ] }; @@ -45,7 +45,7 @@ var THIRD = { var FOURTH = { keys: [ - 'npm:additional-thing@3.0.0', + 'npm:additional-thing@2.2.0', 'npm:broccoli@3.0.0', 'npm:x@3.0.0', 'npm:y@3.0.0', @@ -141,7 +141,9 @@ describe('Ember CLI 2.x Stub Generator', function() { }); it('generates stub file', function() { - var tree = new StubGenerator(src.inputTree); + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); builder = new broccoli.Builder(tree); @@ -170,7 +172,9 @@ describe('Ember CLI 2.x Stub Generator', function() { }); it('generates same stubFile if inputs do not change', function() { - var tree = new StubGenerator(src.inputTree); + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); builder = new broccoli.Builder(tree); @@ -186,7 +190,10 @@ describe('Ember CLI 2.x Stub Generator', function() { }); it('adds deps from new file', function() { - var tree = new StubGenerator(src.inputTree); + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); + builder = new broccoli.Builder(tree); return builder.build().then(function(result) { loader.load(result.directory + '/browserify_stubs.js'); @@ -235,7 +242,10 @@ describe('Ember CLI 2.x Stub Generator', function() { }); it('removes deps from deleted file', function() { - var tree = new StubGenerator(src.inputTree); + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); + builder = new broccoli.Builder(tree); return builder.build().then(function(result) { loader.load(result.directory + '/browserify_stubs.js'); @@ -254,7 +264,10 @@ describe('Ember CLI 2.x Stub Generator', function() { }); it('adds deps in modified file', function() { - var tree = new StubGenerator(src.inputTree); + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); + builder = new broccoli.Builder(tree); return builder.build().then(function(result) { loader.load(result.directory + '/browserify_stubs.js'); @@ -290,7 +303,9 @@ describe('Ember CLI 2.x Stub Generator', function() { }); it('removes deps in modified file', function() { - var tree = new StubGenerator(src.inputTree); + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); builder = new broccoli.Builder(tree); return builder.build().then(function(result) { loader.load(result.directory + '/browserify_stubs.js'); @@ -345,10 +360,9 @@ describe('CachingBrowserify', function() { try { fs.lstatSync(parentLink); fs.unlinkSync(parentLink); + fs.symlinkSync(childLink, parentLink); } catch(err) {} - fs.symlinkSync(childLink, parentLink); }); - }); afterEach(function() { From 9a81644050574047f7295d15b25080081657ec3f Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Wed, 14 Sep 2016 08:51:09 -0700 Subject: [PATCH 08/46] refactor tests (split up concerns) --- test/helpers/keys.js | 44 +++++ test/helpers/loader.js | 45 +++++ test/stub-generator-tests.js | 261 +++++++++++++++++++++++++++ test/test.js | 332 +---------------------------------- 4 files changed, 358 insertions(+), 324 deletions(-) create mode 100644 test/helpers/keys.js create mode 100644 test/helpers/loader.js create mode 100644 test/stub-generator-tests.js diff --git a/test/helpers/keys.js b/test/helpers/keys.js new file mode 100644 index 0000000..f23cae4 --- /dev/null +++ b/test/helpers/keys.js @@ -0,0 +1,44 @@ +'use strict'; + +module.exports.FIRST = { + keys: [ + 'sample', + 'inner/other', + 'npm:broccoli@3.0.0', + 'npm:x@3.0.0', + 'npm:y@3.0.0', + ] +}; + +module.exports.SECOND = { + keys: [ + 'npm:broccoli@3.0.0', + 'npm:x@3.0.0', + 'npm:y@3.0.0', + 'npm:something-new@2.2.2', + ] +}; + +module.exports.THIRD = { + keys: [ + 'npm:x@3.0.0', + 'npm:y@3.0.0', + ] +}; + +module.exports.FOURTH = { + keys: [ + 'npm:additional-thing@2.2.0', + 'npm:broccoli@3.0.0', + 'npm:x@3.0.0', + 'npm:y@3.0.0', + ] +}; + +module.exports. FIFTH = { + keys: [ + 'npm:broccoli@3.0.0', + 'npm:y@3.0.0', + ] +}; + diff --git a/test/helpers/loader.js b/test/helpers/loader.js new file mode 100644 index 0000000..bb607ac --- /dev/null +++ b/test/helpers/loader.js @@ -0,0 +1,45 @@ +'use strict'; +var fs = require('fs'); +module.exports = Loader; +function Loader() { + this.entries = {}; + this.setGlobalDefine(); +} + +Loader.prototype.load = function(path) { + require(path); +}; + +Loader.prototype.unload = function(_path) { + var path = fs.realpathSync(_path); + delete require('module')._cache[path]; + delete require.cache[path]; + delete require('module')._cache[_path]; + delete require.cache[_path]; + this.entries = {}; +}; + +Loader.prototype.reload = function(path) { + this.unload(path); + this.load(path); +}; + +Loader.prototype.require = function(name) { + if (!(name in this.entries)) { + throw new TypeError('no such module: `' + name + '`'); + } + + return this.entries[name](); +}; + +Loader.prototype.setGlobalDefine = function() { + global.define = function(name, callback) { + this.entries[name] = callback; + }.bind(this); +}; + +Loader.prototype.teardown = function() { + this.entries = undefined; + delete global.define; +}; + diff --git a/test/stub-generator-tests.js b/test/stub-generator-tests.js new file mode 100644 index 0000000..b8f99f4 --- /dev/null +++ b/test/stub-generator-tests.js @@ -0,0 +1,261 @@ +/* global describe, afterEach, it, expect, beforeEach */ + +var chai = require('chai'); +var expect = chai.expect; // jshint ignore:line +var Loader = require('./helpers/loader'); + +var StubGenerator = require('../lib/stub-generator'); + +var fs = require('fs'); +var path = require('path'); +var broccoli = require('broccoli'); +var quickTemp = require('quick-temp'); +var copy = require('copy-dereference').sync; +var walkSync = require('walk-sync'); + +var keys = require('./helpers/keys'); + +var FIRST = keys.FIRST; +var SECOND = keys.SECOND; +var THIRD = keys.THIRD; +var FOURTH = keys.FOURTH; +var FIFTH = keys.FIFTH; + +describe('Stub Generator', function() { + var src = {}; + var builder; + var loader; + + beforeEach(function() { + loader = new Loader(); + + quickTemp.makeOrRemake(src, 'tmp'); + src.inputTree = src.tmp + '/inputTree'; + copy(__dirname + '/fixtures/stubs/es5', src.inputTree); + }); + + afterEach(function() { + loader.teardown(); + + if (src.tmp) { + quickTemp.remove(src, 'tmp'); + } + + if (builder) { + return builder.cleanup(); + } + }); + + describe('input', function() { + it('supports 1 inputTree', function() { + expect(function() { + new StubGenerator(); + }).to.throw(/Expects one inputTree/); + expect(function() { + new StubGenerator([]); + }).to.throw(/Expects one inputTree/); + expect(function() { + new StubGenerator(['a','b']); + }).to.throw(/Expects one inputTree/); + }); + }); + + it('generates stub file', function() { + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); + + builder = new broccoli.Builder(tree); + + return builder.build().then(function(result) { + loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(loader.entries).to.have.keys(FIRST.keys); + + var broc = loader.require('npm:broccoli@3.0.0'); + + expect(broc).to.have.keys(['default']); + expect(broc.default).to.have.keys([ + 'loadBrocfile', + 'server', + 'getMiddleware', + 'Watcher', + 'cli', + 'makeTree', + 'bowerTrees', + 'MergedTree', + 'Builder' + ]); + }); + }); + + it('generates same stubFile if inputs do not change', function() { + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); + + builder = new broccoli.Builder(tree); + + var firstRun; + return builder.build().then(function(result) { + firstRun = fs.statSync(result.directory + '/browserify_stubs.js'); + return builder.build(); + }).then(function(result) { + nextRun = fs.statSync(result.directory + '/browserify_stubs.js'); + + expect(firstRun, 'stat information should remain the same').to.deep.equal(nextRun); + }); + }); + + it('adds deps from new file', function() { + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); + + builder = new broccoli.Builder(tree); + return builder.build().then(function(result) { + loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + + expect(loader.entries).to.have.keys(FIRST.keys); + + var broc = loader.require('npm:broccoli@3.0.0'); + + expect(broc).to.have.keys(['default']); + expect(broc.default).to.have.keys([ + 'loadBrocfile', + 'server', + 'getMiddleware', + 'Watcher', + 'cli', + 'makeTree', + 'bowerTrees', + 'MergedTree', + 'Builder' + ]); + + fs.writeFileSync(src.inputTree + '/new.js', "define(\"fizz\", [\"exports\", \"npm:something-new\"], function(exports, SomethingNew) {});"); + return builder.build(); + }).then(function(result){ + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'new.js', + 'sample.js', + ]); + + loader.reload(result.directory + '/browserify_stubs.js'); + + expect(loader.entries).to.have.keys(SECOND.keys); + }); + }); + + it('removes deps from deleted file', function() { + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); + + builder = new broccoli.Builder(tree); + return builder.build().then(function(result) { + loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(loader.entries).to.have.keys(FIRST.keys); + fs.unlinkSync(src.inputTree + '/sample.js'); + return builder.build(); + }).then(function(result){ + + loader.reload(result.directory + '/browserify_stubs.js'); + + expect(loader.entries).to.have.keys(THIRD.keys); + }); + }); + + it('adds deps in modified file', function() { + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); + + builder = new broccoli.Builder(tree); + return builder.build().then(function(result) { + loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + + expect(loader.entries).to.have.keys(FIRST.keys); + + var was = "define('foo', ['exports', 'npm:broccoli', 'npm:additional-thing'], function(exports, Broccoli, Additional) { exports['default'] = Broccoli;});"; + + fs.writeFileSync(src.inputTree + '/sample.js', was); + return builder.build(); + }).then(function(result){ + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + + loader.reload(result.directory + '/browserify_stubs.js'); + + expect(loader.entries).to.have.keys(FOURTH.keys); + }); + }); + + it('removes deps in modified file', function() { + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); + builder = new broccoli.Builder(tree); + return builder.build().then(function(result) { + loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(loader.entries).to.have.keys(FIRST.keys); + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + + var was = "define('foo', ['exports', 'npm:y'], function(exports, _npmY) {});"; + + fs.writeFileSync(src.inputTree + '/inner/other.js', was); + return builder.build(); + }).then(function(result){ + loader.reload(result.directory + '/browserify_stubs.js'); + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + + expect(loader.entries).to.have.keys(FIFTH.keys); + }); + }); +}); diff --git a/test/test.js b/test/test.js index 5c971f8..23e5d8b 100644 --- a/test/test.js +++ b/test/test.js @@ -3,13 +3,11 @@ var chai = require('chai'); var expect = chai.expect; // jshint ignore:line var sinon = require('sinon'); -var sinonChai = require("sinon-chai"); +var sinonChai = require('sinon-chai'); +var Loader = require('./helpers/loader'); chai.use(sinonChai); -var StubGenerator = require('../lib/stub-generator'); var CachingBrowserify = require('../lib/caching-browserify'); -var RSVP = require('rsvp'); -RSVP.on('error', function(err){throw err;}); var fs = require('fs'); var path = require('path'); var broccoli = require('broccoli'); @@ -17,328 +15,14 @@ var quickTemp = require('quick-temp'); var copy = require('copy-dereference').sync; var walkSync = require('walk-sync'); -var FIRST = { - keys: [ - 'sample', - 'inner/other', - 'npm:broccoli@3.0.0', - 'npm:x@3.0.0', - 'npm:y@3.0.0', - ] -}; - -var SECOND = { - keys: [ - 'npm:broccoli@3.0.0', - 'npm:x@3.0.0', - 'npm:y@3.0.0', - 'npm:something-new@2.2.2', - ] -}; - -var THIRD = { - keys: [ - 'npm:x@3.0.0', - 'npm:y@3.0.0', - ] -}; - -var FOURTH = { - keys: [ - 'npm:additional-thing@2.2.0', - 'npm:broccoli@3.0.0', - 'npm:x@3.0.0', - 'npm:y@3.0.0', - ] -}; - -var FIFTH = { - keys: [ - 'npm:broccoli@3.0.0', - 'npm:y@3.0.0', - ] -}; - -function Loader() { - this.entries = {}; - this.setGlobalDefine(); -} - -Loader.prototype.load = function(path) { - require(path); -}; - -Loader.prototype.unload = function(_path) { - var path = fs.realpathSync(_path); - delete require('module')._cache[path]; - delete require.cache[path]; - delete require('module')._cache[_path]; - delete require.cache[_path]; - this.entries = {}; -}; - -Loader.prototype.reload = function(path) { - this.unload(path); - this.load(path); -}; - -Loader.prototype.require = function(name) { - if (!(name in this.entries)) { - throw new TypeError('no such module: `' + name + '`'); - } - - return this.entries[name](); -}; - -Loader.prototype.setGlobalDefine = function() { - global.define = function(name, callback) { - this.entries[name] = callback; - }.bind(this); -}; - -Loader.prototype.teardown = function() { - this.entries = undefined; - delete global.define; -}; - -describe('Ember CLI 2.x Stub Generator', function() { - var src = {}; - var builder; - var loader; - - beforeEach(function() { - loader = new Loader(); - - quickTemp.makeOrRemake(src, 'tmp'); - src.inputTree = src.tmp + '/inputTree'; - copy(__dirname + '/fixtures/stubs/es5', src.inputTree); - }); - afterEach(function() { - loader.teardown(); - - if (src.tmp) { - quickTemp.remove(src, 'tmp'); - } - - if (builder) { - return builder.cleanup(); - } - }); - - describe('input', function() { - it('supports 1 inputTree', function() { - expect(function() { - new StubGenerator(); - }).to.throw(/Expects one inputTree/); - expect(function() { - new StubGenerator([]); - }).to.throw(/Expects one inputTree/); - expect(function() { - new StubGenerator(['a','b']); - }).to.throw(/Expects one inputTree/); - }); - }); - - it('generates stub file', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' - }); - - builder = new broccoli.Builder(tree); - - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - loader.load(result.directory + '/sample.js'); - loader.load(result.directory + '/inner/other.js'); - - expect(loader.entries).to.have.keys(FIRST.keys); - - var broc = loader.require('npm:broccoli@3.0.0'); - - expect(broc).to.have.keys(['default']); - expect(broc.default).to.have.keys([ - 'loadBrocfile', - 'server', - 'getMiddleware', - 'Watcher', - 'cli', - 'makeTree', - 'bowerTrees', - 'MergedTree', - 'Builder' - ]); - }); - }); - - it('generates same stubFile if inputs do not change', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' - }); - - builder = new broccoli.Builder(tree); - - var firstRun; - return builder.build().then(function(result) { - firstRun = fs.statSync(result.directory + '/browserify_stubs.js'); - return builder.build(); - }).then(function(result) { - nextRun = fs.statSync(result.directory + '/browserify_stubs.js'); - - expect(firstRun, 'stat information should remain the same').to.deep.equal(nextRun); - }); - }); - - it('adds deps from new file', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' - }); - - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - loader.load(result.directory + '/sample.js'); - loader.load(result.directory + '/inner/other.js'); - - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'sample.js', - ]); +var keys = require('./helpers/keys'); - expect(loader.entries).to.have.keys(FIRST.keys); - - var broc = loader.require('npm:broccoli@3.0.0'); - - expect(broc).to.have.keys(['default']); - expect(broc.default).to.have.keys([ - 'loadBrocfile', - 'server', - 'getMiddleware', - 'Watcher', - 'cli', - 'makeTree', - 'bowerTrees', - 'MergedTree', - 'Builder' - ]); - - fs.writeFileSync(src.inputTree + '/new.js', "define(\"fizz\", [\"exports\", \"npm:something-new\"], function(exports, SomethingNew) {});"); - return builder.build(); - }).then(function(result){ - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'new.js', - 'sample.js', - ]); - - loader.reload(result.directory + '/browserify_stubs.js'); - - expect(loader.entries).to.have.keys(SECOND.keys); - }); - }); - - it('removes deps from deleted file', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' - }); - - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - loader.load(result.directory + '/sample.js'); - loader.load(result.directory + '/inner/other.js'); - - expect(loader.entries).to.have.keys(FIRST.keys); - fs.unlinkSync(src.inputTree + '/sample.js'); - return builder.build(); - }).then(function(result){ - - loader.reload(result.directory + '/browserify_stubs.js'); - - expect(loader.entries).to.have.keys(THIRD.keys); - }); - }); - - it('adds deps in modified file', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' - }); - - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - loader.load(result.directory + '/sample.js'); - loader.load(result.directory + '/inner/other.js'); - - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'sample.js', - ]); - - expect(loader.entries).to.have.keys(FIRST.keys); - - var was = "define('foo', ['exports', 'npm:broccoli', 'npm:additional-thing'], function(exports, Broccoli, Additional) { exports['default'] = Broccoli;});"; - - fs.writeFileSync(src.inputTree + '/sample.js', was); - return builder.build(); - }).then(function(result){ - - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'sample.js', - ]); - - loader.reload(result.directory + '/browserify_stubs.js'); - - expect(loader.entries).to.have.keys(FOURTH.keys); - }); - }); - - it('removes deps in modified file', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' - }); - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - loader.load(result.directory + '/sample.js'); - loader.load(result.directory + '/inner/other.js'); - - expect(loader.entries).to.have.keys(FIRST.keys); - - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'sample.js', - ]); - - var was = "define('foo', ['exports', 'npm:y'], function(exports, _npmY) {});"; - - fs.writeFileSync(src.inputTree + '/inner/other.js', was); - return builder.build(); - }).then(function(result){ - loader.reload(result.directory + '/browserify_stubs.js'); - - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'sample.js', - ]); - - expect(loader.entries).to.have.keys(FIFTH.keys); - }); - }); -}); +var FIRST = keys.FIRST; +var SECOND = keys.SECOND; +var THIRD = keys.THIRD; +var FOURTH = keys.FOURTH; +var FIFTH = keys.FIFTH; describe('CachingBrowserify', function() { var src = {}; From 71ab74fd7dc564203b1313597febcf0f264ff1fd Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Wed, 14 Sep 2016 12:23:16 -0700 Subject: [PATCH 09/46] Fixed test for multiple input rewrites. --- test/test.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/test.js b/test/test.js index 23e5d8b..3f8e29f 100644 --- a/test/test.js +++ b/test/test.js @@ -106,6 +106,9 @@ describe('CachingBrowserify', function() { }); it('rebuilds when an npm module changes', function(){ + var module = src.inputTree + '/node_modules/my-module'; + var target = module + '/index.js'; + var tree = new CachingBrowserify(src.entryTree); var spy = sinon.spy(tree, 'updateCache'); @@ -118,15 +121,13 @@ describe('CachingBrowserify', function() { expect(loader.require('npm:my-module').default.toString()).to.contain('other.something();'); - var module = path.resolve(__dirname + '/../node_modules/my-module'); - var target = module + '/index.js'; - expect(Object.keys(readTrees).filter(function(readTree) { return /my-module/.test(readTree); }), 'expected readTrees to contain a path that matched `/node_modules\/my-module/`').to.not.be.empty; var code = fs.readFileSync(target, 'utf-8'); code = code.replace('other.something()', 'other.something()+1'); + fs.unlinkSync(target); fs.writeFileSync(target, code); return builder.build(); From cdf0067a292d1853505261f23ff3b1f97fade038 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Wed, 14 Sep 2016 12:35:09 -0700 Subject: [PATCH 10/46] add jshinting to tests --- package.json | 4 ++-- test/jshint.js | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e866201..b5bac26 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "chai": "^1.10.0", "copy-dereference": "^1.0.0", "mocha": "^2.0.1", - "mocha-jshint": "0.0.9", + "mocha-jshint": "2.3.1", "sinon": "^1.12.2", "sinon-chai": "^2.6.0" }, @@ -54,6 +54,6 @@ "rsvp": "^3.0.14", "symlink-or-copy": "^1.0.0", "through2": "^2.0.0", - "walk-sync": "^0.2.7" + "walk-sync": "^0.3.1" } } diff --git a/test/jshint.js b/test/jshint.js index 26f4b22..1f3033d 100644 --- a/test/jshint.js +++ b/test/jshint.js @@ -1,3 +1,9 @@ -require('mocha-jshint')([ - 'lib' -]); +var walkSync = require('walk-sync'); +var path = require('path'); + +require('mocha-jshint')({ + paths: ['lib'].concat(walkSync(__dirname, { ignore: ['fixtures'] }). + map(function(relativePath) { + return path.join(__dirname, relativePath); + })) +}); From 831f46478e125253669cfbffda61c1b3a6e0ad1b Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Wed, 14 Sep 2016 13:36:30 -0700 Subject: [PATCH 11/46] fix hinting --- test/{test.js => caching-browserify-test.js} | 13 ++----------- test/imports-for-test.js | 2 ++ test/jshint.js | 2 +- test/stub-generator-tests.js | 5 ++--- test/stubs-test.js | 5 +++-- 5 files changed, 10 insertions(+), 17 deletions(-) rename test/{test.js => caching-browserify-test.js} (96%) diff --git a/test/test.js b/test/caching-browserify-test.js similarity index 96% rename from test/test.js rename to test/caching-browserify-test.js index 3f8e29f..609dcca 100644 --- a/test/test.js +++ b/test/caching-browserify-test.js @@ -1,4 +1,5 @@ -/* global describe, afterEach, it, expect, beforeEach */ +/* global describe, afterEach, it, beforeEach */ +/* jshint expr: true */ var chai = require('chai'); var expect = chai.expect; // jshint ignore:line @@ -13,16 +14,6 @@ var path = require('path'); var broccoli = require('broccoli'); var quickTemp = require('quick-temp'); var copy = require('copy-dereference').sync; -var walkSync = require('walk-sync'); - - -var keys = require('./helpers/keys'); - -var FIRST = keys.FIRST; -var SECOND = keys.SECOND; -var THIRD = keys.THIRD; -var FOURTH = keys.FOURTH; -var FIFTH = keys.FIFTH; describe('CachingBrowserify', function() { var src = {}; diff --git a/test/imports-for-test.js b/test/imports-for-test.js index 1189c03..2f9ae7a 100644 --- a/test/imports-for-test.js +++ b/test/imports-for-test.js @@ -1,3 +1,5 @@ +/* global describe, it */ + var expect = require('chai').expect; var importsFor = require('../lib/imports-for'); diff --git a/test/jshint.js b/test/jshint.js index 1f3033d..7af4cde 100644 --- a/test/jshint.js +++ b/test/jshint.js @@ -2,7 +2,7 @@ var walkSync = require('walk-sync'); var path = require('path'); require('mocha-jshint')({ - paths: ['lib'].concat(walkSync(__dirname, { ignore: ['fixtures'] }). + paths: ['lib'].concat(walkSync(__dirname, { ignore: ['fixtures', '.gitignore'] }). map(function(relativePath) { return path.join(__dirname, relativePath); })) diff --git a/test/stub-generator-tests.js b/test/stub-generator-tests.js index b8f99f4..50c76c2 100644 --- a/test/stub-generator-tests.js +++ b/test/stub-generator-tests.js @@ -1,4 +1,4 @@ -/* global describe, afterEach, it, expect, beforeEach */ +/* global describe, afterEach, it, beforeEach */ var chai = require('chai'); var expect = chai.expect; // jshint ignore:line @@ -7,7 +7,6 @@ var Loader = require('./helpers/loader'); var StubGenerator = require('../lib/stub-generator'); var fs = require('fs'); -var path = require('path'); var broccoli = require('broccoli'); var quickTemp = require('quick-temp'); var copy = require('copy-dereference').sync; @@ -103,7 +102,7 @@ describe('Stub Generator', function() { firstRun = fs.statSync(result.directory + '/browserify_stubs.js'); return builder.build(); }).then(function(result) { - nextRun = fs.statSync(result.directory + '/browserify_stubs.js'); + var nextRun = fs.statSync(result.directory + '/browserify_stubs.js'); expect(firstRun, 'stat information should remain the same').to.deep.equal(nextRun); }); diff --git a/test/stubs-test.js b/test/stubs-test.js index 1d665f3..6750437 100644 --- a/test/stubs-test.js +++ b/test/stubs-test.js @@ -1,7 +1,8 @@ +/* global describe, it, beforeEach */ + var Stubs = require('../lib/stubs'); var chai = require('chai'); var expect = chai.expect; // jshint ignore:line -var importsFor = require('../lib/imports-for'); describe('Stubs', function() { var stubs; @@ -13,7 +14,7 @@ describe('Stubs', function() { describe('no-data', function() { it('toAMD', function() { expect(stubs.toAMD()).to.eql(''); - }) + }); }); describe('basic', function() { From ee94775d0dfc100363a2df8c4d0a3f2e9288a75e Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Wed, 14 Sep 2016 13:47:25 -0700 Subject: [PATCH 12/46] fixup spacing --- lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index 5181252..ba39d51 100644 --- a/lib/index.js +++ b/lib/index.js @@ -92,4 +92,4 @@ module.exports = { return tree; } - }; +}; From d30025b27ae1d04827e82c6c1f9d41b2810afb2e Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Wed, 14 Sep 2016 14:00:15 -0700 Subject: [PATCH 13/46] use chai-files --- package.json | 3 ++- test/caching-browserify-test.js | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index b5bac26..6785246 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "license": "MIT", "devDependencies": { "broccoli": "^0.16.8", - "chai": "^1.10.0", + "chai": "^3.5.0", + "chai-files": "^1.4.0", "copy-dereference": "^1.0.0", "mocha": "^2.0.1", "mocha-jshint": "2.3.1", diff --git a/test/caching-browserify-test.js b/test/caching-browserify-test.js index 609dcca..d23521d 100644 --- a/test/caching-browserify-test.js +++ b/test/caching-browserify-test.js @@ -1,12 +1,20 @@ /* global describe, afterEach, it, beforeEach */ /* jshint expr: true */ -var chai = require('chai'); -var expect = chai.expect; // jshint ignore:line var sinon = require('sinon'); +var chai = require('chai'); var sinonChai = require('sinon-chai'); -var Loader = require('./helpers/loader'); +var chaiFiles = require('chai-files'); + chai.use(sinonChai); +chai.use(chaiFiles); + +var expect = chai.expect; + +var Loader = require('./helpers/loader'); + + +var file = chaiFiles.file; var CachingBrowserify = require('../lib/caching-browserify'); var fs = require('fs'); @@ -87,8 +95,7 @@ describe('CachingBrowserify', function() { loader.load(result.directory + '/browserify/browserify.js'); expect(loader.entries).to.have.keys(['npm:my-module']); - var file = fs.readFileSync(result.directory + '/browserify/browserify.js', 'UTF8'); - expect(file).to.match(/sourceMappingURL=data:application\/json;.*base64,/); + expect(file(result.directory + '/browserify/browserify.js')).to.match(/sourceMappingURL=data:application\/json;.*base64,/); expect(spy).to.have.callCount(1); return builder.build(); }).then(function(){ From b3f7faa41884bf382e61395d1677c952d2aaac7a Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Wed, 14 Sep 2016 14:06:35 -0700 Subject: [PATCH 14/46] tidy up test files --- test/caching-browserify-test.js | 6 +- test/imports-for-test.js | 2 +- test/stub-generator-tests.js | 351 +++++++++++++++----------------- 3 files changed, 166 insertions(+), 193 deletions(-) diff --git a/test/caching-browserify-test.js b/test/caching-browserify-test.js index d23521d..1985ee6 100644 --- a/test/caching-browserify-test.js +++ b/test/caching-browserify-test.js @@ -24,12 +24,10 @@ var quickTemp = require('quick-temp'); var copy = require('copy-dereference').sync; describe('CachingBrowserify', function() { - var src = {}; - var builder; - var readTrees; - var loader; + var src, builder, readTrees, loader; beforeEach(function() { + src = {}; loader = new Loader(); quickTemp.makeOrRemake(src, 'tmp'); diff --git a/test/imports-for-test.js b/test/imports-for-test.js index 2f9ae7a..5217d7d 100644 --- a/test/imports-for-test.js +++ b/test/imports-for-test.js @@ -8,6 +8,6 @@ describe('importsFor', function() { expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); - expect(importsFor('define("apple", ["npm:foo"], function() { });')).to.eql({ foo: true}); + expect(importsFor('define("apple", ["npm:foo"], function() { });')).to.eql({ foo: true }); }); }); diff --git a/test/stub-generator-tests.js b/test/stub-generator-tests.js index 50c76c2..b04f289 100644 --- a/test/stub-generator-tests.js +++ b/test/stub-generator-tests.js @@ -21,12 +21,11 @@ var FOURTH = keys.FOURTH; var FIFTH = keys.FIFTH; describe('Stub Generator', function() { - var src = {}; - var builder; - var loader; + var src, loader; beforeEach(function() { loader = new Loader(); + src = {}; quickTemp.makeOrRemake(src, 'tmp'); src.inputTree = src.tmp + '/inputTree'; @@ -36,13 +35,7 @@ describe('Stub Generator', function() { afterEach(function() { loader.teardown(); - if (src.tmp) { - quickTemp.remove(src, 'tmp'); - } - - if (builder) { - return builder.cleanup(); - } + quickTemp.remove(src, 'tmp'); }); describe('input', function() { @@ -59,202 +52,184 @@ describe('Stub Generator', function() { }); }); - it('generates stub file', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' - }); + describe('building', function() { + var builder; + beforeEach(function() { + var tree = new StubGenerator(src.inputTree, { + basedir: __dirname + '/fixtures/modules' + }); - builder = new broccoli.Builder(tree); - - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - loader.load(result.directory + '/sample.js'); - loader.load(result.directory + '/inner/other.js'); - - expect(loader.entries).to.have.keys(FIRST.keys); - - var broc = loader.require('npm:broccoli@3.0.0'); - - expect(broc).to.have.keys(['default']); - expect(broc.default).to.have.keys([ - 'loadBrocfile', - 'server', - 'getMiddleware', - 'Watcher', - 'cli', - 'makeTree', - 'bowerTrees', - 'MergedTree', - 'Builder' - ]); + builder = new broccoli.Builder(tree); }); - }); - it('generates same stubFile if inputs do not change', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' + afterEach(function() { + return builder.cleanup(); }); - builder = new broccoli.Builder(tree); - - var firstRun; - return builder.build().then(function(result) { - firstRun = fs.statSync(result.directory + '/browserify_stubs.js'); - return builder.build(); - }).then(function(result) { - var nextRun = fs.statSync(result.directory + '/browserify_stubs.js'); - - expect(firstRun, 'stat information should remain the same').to.deep.equal(nextRun); + it('generates stub file', function() { + return builder.build().then(function(result) { + loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(loader.entries).to.have.keys(FIRST.keys); + + var broc = loader.require('npm:broccoli@3.0.0'); + + expect(broc).to.have.keys(['default']); + expect(broc.default).to.have.keys([ + 'loadBrocfile', + 'server', + 'getMiddleware', + 'Watcher', + 'cli', + 'makeTree', + 'bowerTrees', + 'MergedTree', + 'Builder' + ]); + }); }); - }); - it('adds deps from new file', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' - }); + it('generates same stubFile if inputs do not change', function() { + var firstRun; + return builder.build().then(function(result) { + firstRun = fs.statSync(result.directory + '/browserify_stubs.js'); + return builder.build(); + }).then(function(result) { + var nextRun = fs.statSync(result.directory + '/browserify_stubs.js'); - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - loader.load(result.directory + '/sample.js'); - loader.load(result.directory + '/inner/other.js'); - - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'sample.js', - ]); - - expect(loader.entries).to.have.keys(FIRST.keys); - - var broc = loader.require('npm:broccoli@3.0.0'); - - expect(broc).to.have.keys(['default']); - expect(broc.default).to.have.keys([ - 'loadBrocfile', - 'server', - 'getMiddleware', - 'Watcher', - 'cli', - 'makeTree', - 'bowerTrees', - 'MergedTree', - 'Builder' - ]); - - fs.writeFileSync(src.inputTree + '/new.js', "define(\"fizz\", [\"exports\", \"npm:something-new\"], function(exports, SomethingNew) {});"); - return builder.build(); - }).then(function(result){ - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'new.js', - 'sample.js', - ]); - - loader.reload(result.directory + '/browserify_stubs.js'); - - expect(loader.entries).to.have.keys(SECOND.keys); + expect(firstRun, 'stat information should remain the same').to.deep.equal(nextRun); + }); }); - }); - it('removes deps from deleted file', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' + it('adds deps from new file', function() { + return builder.build().then(function(result) { + loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + + expect(loader.entries).to.have.keys(FIRST.keys); + + var broc = loader.require('npm:broccoli@3.0.0'); + + expect(broc).to.have.keys(['default']); + expect(broc.default).to.have.keys([ + 'loadBrocfile', + 'server', + 'getMiddleware', + 'Watcher', + 'cli', + 'makeTree', + 'bowerTrees', + 'MergedTree', + 'Builder' + ]); + + fs.writeFileSync(src.inputTree + '/new.js', "define(\"fizz\", [\"exports\", \"npm:something-new\"], function(exports, SomethingNew) {});"); + return builder.build(); + }).then(function(result) { + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'new.js', + 'sample.js', + ]); + + loader.reload(result.directory + '/browserify_stubs.js'); + + expect(loader.entries).to.have.keys(SECOND.keys); + }); }); - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - loader.load(result.directory + '/sample.js'); - loader.load(result.directory + '/inner/other.js'); - - expect(loader.entries).to.have.keys(FIRST.keys); - fs.unlinkSync(src.inputTree + '/sample.js'); - return builder.build(); - }).then(function(result){ + it('removes deps from deleted file', function() { + return builder.build().then(function(result) { + loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); - loader.reload(result.directory + '/browserify_stubs.js'); + expect(loader.entries).to.have.keys(FIRST.keys); + fs.unlinkSync(src.inputTree + '/sample.js'); + return builder.build(); + }).then(function(result) { + loader.reload(result.directory + '/browserify_stubs.js'); - expect(loader.entries).to.have.keys(THIRD.keys); + expect(loader.entries).to.have.keys(THIRD.keys); + }); }); - }); - it('adds deps in modified file', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' + it('adds deps in modified file', function() { + return builder.build().then(function(result) { + loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + + expect(loader.entries).to.have.keys(FIRST.keys); + + var was = "define('foo', ['exports', 'npm:broccoli', 'npm:additional-thing'], function(exports, Broccoli, Additional) { exports['default'] = Broccoli;});"; + + fs.writeFileSync(src.inputTree + '/sample.js', was); + return builder.build(); + }).then(function(result) { + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + + loader.reload(result.directory + '/browserify_stubs.js'); + + expect(loader.entries).to.have.keys(FOURTH.keys); + }); }); - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - loader.load(result.directory + '/sample.js'); - loader.load(result.directory + '/inner/other.js'); - - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'sample.js', - ]); - - expect(loader.entries).to.have.keys(FIRST.keys); - - var was = "define('foo', ['exports', 'npm:broccoli', 'npm:additional-thing'], function(exports, Broccoli, Additional) { exports['default'] = Broccoli;});"; - - fs.writeFileSync(src.inputTree + '/sample.js', was); - return builder.build(); - }).then(function(result){ - - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'sample.js', - ]); - - loader.reload(result.directory + '/browserify_stubs.js'); - - expect(loader.entries).to.have.keys(FOURTH.keys); - }); - }); - - it('removes deps in modified file', function() { - var tree = new StubGenerator(src.inputTree, { - basedir: __dirname + '/fixtures/modules' - }); - builder = new broccoli.Builder(tree); - return builder.build().then(function(result) { - loader.load(result.directory + '/browserify_stubs.js'); - loader.load(result.directory + '/sample.js'); - loader.load(result.directory + '/inner/other.js'); - - expect(loader.entries).to.have.keys(FIRST.keys); - - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'sample.js', - ]); - - var was = "define('foo', ['exports', 'npm:y'], function(exports, _npmY) {});"; - - fs.writeFileSync(src.inputTree + '/inner/other.js', was); - return builder.build(); - }).then(function(result){ - loader.reload(result.directory + '/browserify_stubs.js'); - - expect(walkSync(result.directory)).to.eql([ - 'browserify_stubs.js', - 'inner/', - 'inner/other.js', - 'sample.js', - ]); - - expect(loader.entries).to.have.keys(FIFTH.keys); + it('removes deps in modified file', function() { + return builder.build().then(function(result) { + loader.load(result.directory + '/browserify_stubs.js'); + loader.load(result.directory + '/sample.js'); + loader.load(result.directory + '/inner/other.js'); + + expect(loader.entries).to.have.keys(FIRST.keys); + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + + var was = "define('foo', ['exports', 'npm:y'], function(exports, _npmY) {});"; + + fs.writeFileSync(src.inputTree + '/inner/other.js', was); + return builder.build(); + }).then(function(result) { + loader.reload(result.directory + '/browserify_stubs.js'); + + expect(walkSync(result.directory)).to.eql([ + 'browserify_stubs.js', + 'inner/', + 'inner/other.js', + 'sample.js', + ]); + + expect(loader.entries).to.have.keys(FIFTH.keys); + }); }); }); }); From 75f48c14933a2386be6368e3a4760befb0b5f6df Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Wed, 14 Sep 2016 14:18:20 -0700 Subject: [PATCH 15/46] more cleanup --- index.js | 2 ++ lib/caching-browserify.js | 50 ++++++++++++++++++++------------- lib/imports-for.js | 1 + lib/index.js | 14 +++++---- lib/stub-generator.js | 16 ++++------- lib/version-for-module-name.js | 18 ++++++++++++ test/caching-browserify-test.js | 50 ++++++++++++++++++++------------- test/helpers/loader.js | 1 + 8 files changed, 97 insertions(+), 55 deletions(-) create mode 100644 lib/version-for-module-name.js diff --git a/index.js b/index.js index b58e228..486e543 100644 --- a/index.js +++ b/index.js @@ -1 +1,3 @@ +'use strict'; + module.exports = require('./lib/index'); diff --git a/lib/caching-browserify.js b/lib/caching-browserify.js index d9b35ad..212660f 100644 --- a/lib/caching-browserify.js +++ b/lib/caching-browserify.js @@ -1,3 +1,5 @@ +'use strict'; + var fs = require('fs'); var path = require('path'); var browserify = require('browserify'); @@ -16,7 +18,7 @@ var debug = require('debug')('ember-browserify:caching-browserify'); var through = require('through2'); module.exports = CoreObject.extend({ - init: function(inputTree, options){ + init: function(inputTree, options) { if (!options) { options = {}; } @@ -28,6 +30,7 @@ module.exports = CoreObject.extend({ this.fullPaths = typeof options.fullPaths !== 'undefined' ? options.fullPaths : true; this.outputFile = options.outputFile || 'browserify/browserify.js'; this.cache = {}; + quickTemp.makeOrRemake(this, '_inputStaging'); quickTemp.makeOrRemake(this, '_destDir'); }, @@ -48,16 +51,18 @@ module.exports = CoreObject.extend({ read: function (readTree) { var self = this; - return readTree(this.inputTree).then(function(inDir){ - return self.checkCache(inDir).then(function(cacheValid){ + + return readTree(this.inputTree).then(function(inDir) { + return self.checkCache(inDir).then(function(cacheValid) { if (!self._outputCache || !cacheValid) { return self._rebuild(inDir); } }); - }).then(function(){ + }).then(function() { rimraf.sync(self._destDir); symlinkOrCopy.sync(self._outputCache, self._destDir); - return self.watchNodeModules(readTree).then(function(){ + + return self.watchNodeModules(readTree).then(function() { return self._destDir; }); }); @@ -65,6 +70,7 @@ module.exports = CoreObject.extend({ _rebuild: function(inDir){ var self = this; + this._watchModules = Object.create(null); // _inputStaging needs to stay at the same path, because the @@ -74,7 +80,8 @@ module.exports = CoreObject.extend({ symlinkOrCopy.sync(inDir + '/' + this.inFile, this._inputStaging + '/' + this.inFile); quickTemp.makeOrRemake(this, '_outputCache'); - return this.updateCache(this._outputCache).catch(function(err){ + + return this.updateCache(this._outputCache).catch(function(err) { rimraf.sync(self._outputCache); delete self._outputCache; throw err; @@ -101,7 +108,7 @@ module.exports = CoreObject.extend({ var b = browserify(opts); ['transforms', 'externals', 'ignores', 'includes'].forEach(function(thing) { if (!opts[thing]) { return; } - opts[thing].forEach(function(args){ + opts[thing].forEach(function(args) { if (!Array.isArray(args)) { args = [args]; } @@ -114,9 +121,10 @@ module.exports = CoreObject.extend({ b = b[thing.replace(/s$/, '')].apply(b, args); }); }); + b.add('./' + self.inFile); - b.on('package', function(pkg){ + b.on('package', function(pkg) { // browserify *used to* reliably put the package's directory in // pkg.__dirname. But as of browser-resolve 1.7.0 that isn't // true, and we sometimes get a value here like @@ -137,7 +145,7 @@ module.exports = CoreObject.extend({ self._watchModules[pkgDir] = true; }); - b.on('dep', function (dep) { + b.on('dep', function(dep) { dep.source = derequire(dep.source); if (typeof dep.id === 'string') { self.cache[dep.id] = dep; @@ -158,7 +166,7 @@ module.exports = CoreObject.extend({ // to prevent unwanted interactions with other code when concatenated // See https://github.com/ef4/ember-browserify/issues/63 // and https://github.com/substack/node-browserify/issues/806 - b.pipeline.get('wrap').push(through.obj(function (row, enc, next) { + b.pipeline.get('wrap').push(through.obj(function(row, enc, next) { var contents = row.toString(); if (contents[contents.length - 1] === ')') { contents += ';'; @@ -178,14 +186,18 @@ module.exports = CoreObject.extend({ var self = this; fs.mkdirSync(path.dirname(outPath)); var start = Date.now(); - return new RSVP.Promise(function (resolve, reject) { - self.bundler().bundle(function (err, data) { - debug('bundle in: %dms', Date.now() - start); - if (err) { - reject(err); - } else { - fs.writeFileSync(outPath, data); - resolve(destDir); + return new RSVP.Promise(function(resolve, reject) { + self.bundler().bundle(function(err, data) { + try { + debug('bundle in: %dms', Date.now() - start); + if (err) { + reject(err); + } else { + fs.writeFileSync(outPath, data); + resolve(destDir); + } + } catch(e) { + reject(e); } }); }); @@ -195,7 +207,7 @@ module.exports = CoreObject.extend({ var self = this; var root = self.normalizePath(self.root); - return mapSeries(Object.keys(self._watchModules), function(dir){ + return mapSeries(Object.keys(self._watchModules), function(dir) { if (!root || root.indexOf(self.normalizePath(dir)) !== 0){ return readTree(dir); } diff --git a/lib/imports-for.js b/lib/imports-for.js index cff76c0..a0a6cb1 100644 --- a/lib/imports-for.js +++ b/lib/imports-for.js @@ -1,6 +1,7 @@ 'use strict'; var acorn = require('acorn'); + module.exports = importsFor; function importsFor(src, fullPath) { var result = parse(src); diff --git a/lib/index.js b/lib/index.js index ba39d51..f78629b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,6 +1,7 @@ +'use strict'; + // Support old versions of Ember CLI. -function findHost() { - var current = this; +function findHost(current) { var app; // Keep iterating upward until we don't have a grandparent. @@ -19,7 +20,7 @@ var Funnel = require('broccoli-funnel'); module.exports = { name: 'ember-browserify', - included: function(app){ + included: function(app) { var VersionChecker = require('ember-cli-version-checker'); var checker = new VersionChecker(this); @@ -29,7 +30,7 @@ module.exports = { throw new TypeError('ember-browserify@^2.0.0 no longer supports ember-cli versions less then 2.0.0.'); } - app = findHost.call(this); + app = findHost(this); var enableSourcemaps = app.options.sourcemaps && app.options.sourcemaps.enabled && app.options.sourcemaps.extensions.indexOf('js') > -1; @@ -50,14 +51,15 @@ module.exports = { } if (app.importWhitelistFilters) { - app.importWhitelistFilters.push(function(moduleName){ + app.importWhitelistFilters.push(function(moduleName) { return moduleName.slice(0,4) === 'npm:'; }); } }, - postprocessTree: function(type, tree){ + postprocessTree: function(type, tree) { var outputFile, options; + if (type === 'js'){ outputFile = 'browserify/browserify.js'; } else if (type === 'test'){ diff --git a/lib/stub-generator.js b/lib/stub-generator.js index 7adbe5f..7760781 100644 --- a/lib/stub-generator.js +++ b/lib/stub-generator.js @@ -1,3 +1,5 @@ +'use strict'; + var Plugin = require('broccoli-plugin'); var FSTree = require('fs-tree-diff'); var walkSync = require('walk-sync'); @@ -6,6 +8,7 @@ var fs = require('fs'); var md5Hex = require('md5-hex'); var debug = require('debug')('ember-browserify:stub-generator:'); var importsFor = require('./imports-for'); +var versionForModuleName = require('./version-for-module-name'); module.exports = StubGenerator; function StubGenerator(inputTree, _options) { @@ -19,6 +22,7 @@ function StubGenerator(inputTree, _options) { } Plugin.call(this, [inputTree], options); + this._persistentOutput = true; this.basedir = options.basedir; @@ -35,7 +39,7 @@ StubGenerator.prototype.build = function() { var start = Date.now(); var inputPath = this.inputPaths[0]; var outputPath = this.outputPath; - var previous = this._previousTree; + var previous = this._previousTree; // get patchset var input = walkSync.entries(inputPath); @@ -120,13 +124,3 @@ StubGenerator.prototype.writeFileIfContentChanged = function(fullPath, content) this._fileToChecksumMap[fullPath] = next; // update map } }; - -function versionForModuleName(name, basedir) { - var resolve = require('resolve'); - var findUp = require('find-up'); - var path = require('path'); - var fs = require('fs'); - - var cwd = path.dirname(resolve.sync(name, { basedir: basedir })); - return JSON.parse(fs.readFileSync(findUp.sync('package.json', { cwd: cwd }), 'UTF8')).version; -} diff --git a/lib/version-for-module-name.js b/lib/version-for-module-name.js new file mode 100644 index 0000000..dfac37d --- /dev/null +++ b/lib/version-for-module-name.js @@ -0,0 +1,18 @@ +'use strict'; + +var resolve = require('resolve'); +var findUp = require('find-up'); +var path = require('path'); +var fs = require('fs'); + +module.exports = function versionForModuleName(name, basedir) { + var cwd = path.dirname(resolve.sync(name, { + basedir: basedir + })); + + var content = fs.readFileSync(findUp.sync('package.json', { + cwd: cwd + }), 'UTF8'); + + return JSON.parse(content).version; +}; diff --git a/test/caching-browserify-test.js b/test/caching-browserify-test.js index 1985ee6..6ab20e9 100644 --- a/test/caching-browserify-test.js +++ b/test/caching-browserify-test.js @@ -35,9 +35,11 @@ describe('CachingBrowserify', function() { copy(__dirname + '/fixtures/modules', src.inputTree); src.entryTree = src.inputTree + '/src'; readTrees = {}; + fs.readdirSync(src.inputTree + '/node_modules').forEach(function(module){ var parentLink = path.resolve(__dirname + '/../node_modules/' + module); var childLink = src.inputTree + '/node_modules/' + module; + try { fs.lstatSync(parentLink); fs.unlinkSync(parentLink); @@ -49,12 +51,8 @@ describe('CachingBrowserify', function() { afterEach(function() { loader.teardown(); - if (src.tmp) { - quickTemp.remove(src, 'tmp'); - } - if (builder) { - return builder.cleanup(); - } + quickTemp.remove(src, 'tmp'); + return builder.cleanup(); }); function recordReadTrees(tree) { @@ -64,7 +62,9 @@ describe('CachingBrowserify', function() { it('builds successfully', function() { var tree = new CachingBrowserify(src.entryTree); var spy = sinon.spy(tree, 'updateCache'); + builder = new broccoli.Builder(tree); + return builder.build().then(function(result){ loader.load(result.directory + '/browserify/browserify.js'); expect(loader.entries).to.have.keys(['npm:my-module']); @@ -77,7 +77,9 @@ describe('CachingBrowserify', function() { it('builds successfully with non-default output path', function() { var tree = new CachingBrowserify(src.entryTree, { outputFile: './special-browserify/browserify.js'}); + builder = new broccoli.Builder(tree); + return builder.build().then(function(result){ loader.load(result.directory + '/special-browserify/browserify.js'); expect(loader.entries).to.have.keys(['npm:my-module']); @@ -86,22 +88,24 @@ describe('CachingBrowserify', function() { }); it('builds successfully with sourcemaps on', function() { - var tree = new CachingBrowserify(src.entryTree, {enableSourcemap: true}); + var tree = new CachingBrowserify(src.entryTree, { enableSourcemap: true }); var spy = sinon.spy(tree, 'updateCache'); + builder = new broccoli.Builder(tree); - return builder.build().then(function(result){ + + return builder.build().then(function(result) { loader.load(result.directory + '/browserify/browserify.js'); expect(loader.entries).to.have.keys(['npm:my-module']); expect(file(result.directory + '/browserify/browserify.js')).to.match(/sourceMappingURL=data:application\/json;.*base64,/); expect(spy).to.have.callCount(1); return builder.build(); - }).then(function(){ + }).then(function() { expect(spy).to.have.callCount(1); }); }); - it('rebuilds when an npm module changes', function(){ + it('rebuilds when an npm module changes', function() { var module = src.inputTree + '/node_modules/my-module'; var target = module + '/index.js'; @@ -109,7 +113,8 @@ describe('CachingBrowserify', function() { var spy = sinon.spy(tree, 'updateCache'); builder = new broccoli.Builder(tree); - return builder.build(recordReadTrees).then(function(result){ + + return builder.build(recordReadTrees).then(function(result) { loader.load(result.directory + '/browserify/browserify.js'); expect(loader.entries).to.have.keys(['npm:my-module']); @@ -122,12 +127,13 @@ describe('CachingBrowserify', function() { }), 'expected readTrees to contain a path that matched `/node_modules\/my-module/`').to.not.be.empty; var code = fs.readFileSync(target, 'utf-8'); + code = code.replace('other.something()', 'other.something()+1'); fs.unlinkSync(target); fs.writeFileSync(target, code); return builder.build(); - }).then(function(result){ + }).then(function(result) { expect(spy).to.have.callCount(2); loader.reload(result.directory + '/browserify/browserify.js'); @@ -137,31 +143,35 @@ describe('CachingBrowserify', function() { }); }); - it('rebuilds when the entry file changes', function(){ + it('rebuilds when the entry file changes', function() { var tree = new CachingBrowserify(src.entryTree); var spy = sinon.spy(tree, 'updateCache'); builder = new broccoli.Builder(tree); - return builder.build(recordReadTrees).then(function(result){ + + return builder.build(recordReadTrees).then(function(result) { loader.load(result.directory + '/browserify/browserify.js'); expect(loader.entries).to.have.keys(['npm:my-module']); expect(spy).to.have.callCount(1); expect(readTrees[src.entryTree]).to.equal(true, 'should be watching stubs file'); + fs.unlinkSync(src.entryTree + '/browserify_stubs.js'); copy(src.entryTree + '/second_stubs.js', src.entryTree + '/browserify_stubs.js'); + return builder.build(); - }).then(function(result){ + }).then(function(result) { expect(spy).to.have.callCount(2); loader.load(result.directory + '/browserify/browserify.js'); + expect(loader.entries).to.have.keys([ 'npm:my-module' ]); }); }); - it('recovers from failed build', function(){ + it('recovers from failed build', function() { var broken = src.entryTree + '/broken_stubs.js'; var normal = src.entryTree + '/browserify_stubs.js'; var temporary = src.entryTree + '/temporary.js'; @@ -171,15 +181,17 @@ describe('CachingBrowserify', function() { copy(broken, normal); var tree = new CachingBrowserify(src.entryTree); + builder = new broccoli.Builder(tree); - return builder.build().then(function(){ + + return builder.build().then(function() { throw new Error('expected not to get here'); - }, function(err){ + }, function(err) { expect(err.message).to.match(/Cannot find module 'this-is-nonexistent'/); fs.unlinkSync(normal); copy(temporary, normal); return builder.build(); - }).then(function(result){ + }).then(function(result) { loader.load(result.directory + '/browserify/browserify.js'); expect(loader.entries).to.have.keys(['npm:my-module']); }); diff --git a/test/helpers/loader.js b/test/helpers/loader.js index bb607ac..70af5c9 100644 --- a/test/helpers/loader.js +++ b/test/helpers/loader.js @@ -1,5 +1,6 @@ 'use strict'; var fs = require('fs'); + module.exports = Loader; function Loader() { this.entries = {}; From 6548bfa1839f6f3567b78dae7b5a080bc308dd4a Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Wed, 14 Sep 2016 14:39:57 -0700 Subject: [PATCH 16/46] Add in Ember Addon boilerplate. --- .../index.js => addon/.gitkeep | 0 .../broccoli/index.js => app/.gitkeep | 0 bower.json | 7 +++ config/ember-try.js | 60 +++++++++++++++++++ config/environment.js | 6 ++ ember-cli-build.js | 18 ++++++ index.js | 5 +- {test => node-tests}/.gitignore | 0 .../caching-browserify-test.js | 0 .../node_modules/additional-thing}/index.js | 0 .../additional-thing/package.json | 0 .../modules/node_modules/another/index.js | 0 .../modules/node_modules/another/package.json | 0 .../modules/node_modules/broccoli}/index.js | 0 .../node_modules/broccoli/package.json | 0 .../modules/node_modules/my-module/index.js | 0 .../node_modules/other-dependency/index.js | 0 .../other-dependency/package.json | 0 .../node_modules/my-module/package.json | 0 .../modules/node_modules/package.json | 0 .../node_modules/something-new}/index.js | 0 .../node_modules/something-new/package.json | 0 .../fixtures/modules/node_modules/x/index.js | 0 .../modules/node_modules/x/package.json | 0 .../fixtures/modules/node_modules/y/index.js | 0 .../modules/node_modules/y/package.json | 0 .../fixtures/modules/src/broken_stubs.js | 0 .../fixtures/modules/src/browserify_stubs.js | 0 .../fixtures/modules/src/second_stubs.js | 0 .../fixtures/stubs/es5/inner/other.js | 0 .../fixtures/stubs/es5/sample.js | 0 {test => node-tests}/helpers/keys.js | 0 {test => node-tests}/helpers/loader.js | 0 {test => node-tests}/imports-for-test.js | 0 {test => node-tests}/jshint.js | 0 {test => node-tests}/stub-generator-tests.js | 0 {test => node-tests}/stubs-test.js | 0 package.json | 35 +++++++++-- testem.js | 13 ++++ tests/.jshintrc | 52 ++++++++++++++++ tests/dummy/app/app.js | 18 ++++++ tests/dummy/app/components/.gitkeep | 0 tests/dummy/app/controllers/.gitkeep | 0 tests/dummy/app/helpers/.gitkeep | 0 tests/dummy/app/index.html | 25 ++++++++ tests/dummy/app/models/.gitkeep | 0 tests/dummy/app/resolver.js | 3 + tests/dummy/app/router.js | 12 ++++ tests/dummy/app/routes/.gitkeep | 0 tests/dummy/app/styles/app.css | 0 tests/dummy/app/templates/components/.gitkeep | 0 tests/dummy/config/environment.js | 46 ++++++++++++++ tests/dummy/public/crossdomain.xml | 15 +++++ tests/dummy/public/robots.txt | 3 + tests/helpers/destroy-app.js | 5 ++ tests/helpers/module-for-acceptance.js | 23 +++++++ tests/helpers/resolver.js | 11 ++++ tests/helpers/start-app.js | 18 ++++++ tests/index.html | 33 ++++++++++ tests/integration/.gitkeep | 0 tests/test-helper.js | 6 ++ tests/unit/.gitkeep | 0 vendor/.gitkeep | 0 63 files changed, 409 insertions(+), 5 deletions(-) rename test/fixtures/modules/node_modules/additional-thing/index.js => addon/.gitkeep (100%) rename test/fixtures/modules/node_modules/broccoli/index.js => app/.gitkeep (100%) create mode 100644 bower.json create mode 100644 config/ember-try.js create mode 100644 config/environment.js create mode 100644 ember-cli-build.js rename {test => node-tests}/.gitignore (100%) rename {test => node-tests}/caching-browserify-test.js (100%) rename {test/fixtures/modules/node_modules/something-new => node-tests/fixtures/modules/node_modules/additional-thing}/index.js (100%) rename {test => node-tests}/fixtures/modules/node_modules/additional-thing/package.json (100%) rename {test => node-tests}/fixtures/modules/node_modules/another/index.js (100%) rename {test => node-tests}/fixtures/modules/node_modules/another/package.json (100%) rename {test/fixtures/modules/node_modules/x => node-tests/fixtures/modules/node_modules/broccoli}/index.js (100%) rename {test => node-tests}/fixtures/modules/node_modules/broccoli/package.json (100%) rename {test => node-tests}/fixtures/modules/node_modules/my-module/index.js (100%) rename {test => node-tests}/fixtures/modules/node_modules/my-module/node_modules/other-dependency/index.js (100%) rename {test => node-tests}/fixtures/modules/node_modules/my-module/node_modules/other-dependency/package.json (100%) rename {test => node-tests}/fixtures/modules/node_modules/my-module/package.json (100%) rename {test => node-tests}/fixtures/modules/node_modules/package.json (100%) rename {test/fixtures/modules/node_modules/y => node-tests/fixtures/modules/node_modules/something-new}/index.js (100%) rename {test => node-tests}/fixtures/modules/node_modules/something-new/package.json (100%) create mode 100644 node-tests/fixtures/modules/node_modules/x/index.js rename {test => node-tests}/fixtures/modules/node_modules/x/package.json (100%) create mode 100644 node-tests/fixtures/modules/node_modules/y/index.js rename {test => node-tests}/fixtures/modules/node_modules/y/package.json (100%) rename {test => node-tests}/fixtures/modules/src/broken_stubs.js (100%) rename {test => node-tests}/fixtures/modules/src/browserify_stubs.js (100%) rename {test => node-tests}/fixtures/modules/src/second_stubs.js (100%) rename {test => node-tests}/fixtures/stubs/es5/inner/other.js (100%) rename {test => node-tests}/fixtures/stubs/es5/sample.js (100%) rename {test => node-tests}/helpers/keys.js (100%) rename {test => node-tests}/helpers/loader.js (100%) rename {test => node-tests}/imports-for-test.js (100%) rename {test => node-tests}/jshint.js (100%) rename {test => node-tests}/stub-generator-tests.js (100%) rename {test => node-tests}/stubs-test.js (100%) create mode 100644 testem.js create mode 100644 tests/.jshintrc create mode 100644 tests/dummy/app/app.js create mode 100644 tests/dummy/app/components/.gitkeep create mode 100644 tests/dummy/app/controllers/.gitkeep create mode 100644 tests/dummy/app/helpers/.gitkeep create mode 100644 tests/dummy/app/index.html create mode 100644 tests/dummy/app/models/.gitkeep create mode 100644 tests/dummy/app/resolver.js create mode 100644 tests/dummy/app/router.js create mode 100644 tests/dummy/app/routes/.gitkeep create mode 100644 tests/dummy/app/styles/app.css create mode 100644 tests/dummy/app/templates/components/.gitkeep create mode 100644 tests/dummy/config/environment.js create mode 100644 tests/dummy/public/crossdomain.xml create mode 100644 tests/dummy/public/robots.txt create mode 100644 tests/helpers/destroy-app.js create mode 100644 tests/helpers/module-for-acceptance.js create mode 100644 tests/helpers/resolver.js create mode 100644 tests/helpers/start-app.js create mode 100644 tests/index.html create mode 100644 tests/integration/.gitkeep create mode 100644 tests/test-helper.js create mode 100644 tests/unit/.gitkeep create mode 100644 vendor/.gitkeep diff --git a/test/fixtures/modules/node_modules/additional-thing/index.js b/addon/.gitkeep similarity index 100% rename from test/fixtures/modules/node_modules/additional-thing/index.js rename to addon/.gitkeep diff --git a/test/fixtures/modules/node_modules/broccoli/index.js b/app/.gitkeep similarity index 100% rename from test/fixtures/modules/node_modules/broccoli/index.js rename to app/.gitkeep diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..6fbb20d --- /dev/null +++ b/bower.json @@ -0,0 +1,7 @@ +{ + "name": "ember-browserify", + "dependencies": { + "ember": "~2.8.0", + "ember-cli-shims": "0.1.1" + } +} diff --git a/config/ember-try.js b/config/ember-try.js new file mode 100644 index 0000000..0355b5f --- /dev/null +++ b/config/ember-try.js @@ -0,0 +1,60 @@ +/*jshint node:true*/ +module.exports = { + scenarios: [ + { + name: 'ember-1.13', + bower: { + dependencies: { + 'ember': '~1.13.0' + }, + resolutions: { + 'ember': '~1.13.0' + } + } + }, + { + name: 'ember-lts-2.4', + bower: { + dependencies: { + 'ember': 'components/ember#lts-2-4' + }, + resolutions: { + 'ember': 'lts-2-4' + } + } + }, + { + name: 'ember-release', + bower: { + dependencies: { + 'ember': 'components/ember#release' + }, + resolutions: { + 'ember': 'release' + } + } + }, + { + name: 'ember-beta', + bower: { + dependencies: { + 'ember': 'components/ember#beta' + }, + resolutions: { + 'ember': 'beta' + } + } + }, + { + name: 'ember-canary', + bower: { + dependencies: { + 'ember': 'components/ember#canary' + }, + resolutions: { + 'ember': 'canary' + } + } + } + ] +}; diff --git a/config/environment.js b/config/environment.js new file mode 100644 index 0000000..28a787b --- /dev/null +++ b/config/environment.js @@ -0,0 +1,6 @@ +/*jshint node:true*/ +'use strict'; + +module.exports = function(/* environment, appConfig */) { + return { }; +}; diff --git a/ember-cli-build.js b/ember-cli-build.js new file mode 100644 index 0000000..4ac3913 --- /dev/null +++ b/ember-cli-build.js @@ -0,0 +1,18 @@ +/*jshint node:true*/ +/* global require, module */ +var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); + +module.exports = function(defaults) { + var app = new EmberAddon(defaults, { + // Add options here + }); + + /* + This build file specifies the options for the dummy test app of this + addon, located in `/tests/dummy` + This build file does *not* influence how the addon or the app using it + behave. You most likely want to be modifying `./index.js` or app's build file + */ + + return app.toTree(); +}; diff --git a/index.js b/index.js index 486e543..6e692eb 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,6 @@ +/* jshint node: true */ 'use strict'; -module.exports = require('./lib/index'); +module.exports = { + name: 'ember-browserify' +}; diff --git a/test/.gitignore b/node-tests/.gitignore similarity index 100% rename from test/.gitignore rename to node-tests/.gitignore diff --git a/test/caching-browserify-test.js b/node-tests/caching-browserify-test.js similarity index 100% rename from test/caching-browserify-test.js rename to node-tests/caching-browserify-test.js diff --git a/test/fixtures/modules/node_modules/something-new/index.js b/node-tests/fixtures/modules/node_modules/additional-thing/index.js similarity index 100% rename from test/fixtures/modules/node_modules/something-new/index.js rename to node-tests/fixtures/modules/node_modules/additional-thing/index.js diff --git a/test/fixtures/modules/node_modules/additional-thing/package.json b/node-tests/fixtures/modules/node_modules/additional-thing/package.json similarity index 100% rename from test/fixtures/modules/node_modules/additional-thing/package.json rename to node-tests/fixtures/modules/node_modules/additional-thing/package.json diff --git a/test/fixtures/modules/node_modules/another/index.js b/node-tests/fixtures/modules/node_modules/another/index.js similarity index 100% rename from test/fixtures/modules/node_modules/another/index.js rename to node-tests/fixtures/modules/node_modules/another/index.js diff --git a/test/fixtures/modules/node_modules/another/package.json b/node-tests/fixtures/modules/node_modules/another/package.json similarity index 100% rename from test/fixtures/modules/node_modules/another/package.json rename to node-tests/fixtures/modules/node_modules/another/package.json diff --git a/test/fixtures/modules/node_modules/x/index.js b/node-tests/fixtures/modules/node_modules/broccoli/index.js similarity index 100% rename from test/fixtures/modules/node_modules/x/index.js rename to node-tests/fixtures/modules/node_modules/broccoli/index.js diff --git a/test/fixtures/modules/node_modules/broccoli/package.json b/node-tests/fixtures/modules/node_modules/broccoli/package.json similarity index 100% rename from test/fixtures/modules/node_modules/broccoli/package.json rename to node-tests/fixtures/modules/node_modules/broccoli/package.json diff --git a/test/fixtures/modules/node_modules/my-module/index.js b/node-tests/fixtures/modules/node_modules/my-module/index.js similarity index 100% rename from test/fixtures/modules/node_modules/my-module/index.js rename to node-tests/fixtures/modules/node_modules/my-module/index.js diff --git a/test/fixtures/modules/node_modules/my-module/node_modules/other-dependency/index.js b/node-tests/fixtures/modules/node_modules/my-module/node_modules/other-dependency/index.js similarity index 100% rename from test/fixtures/modules/node_modules/my-module/node_modules/other-dependency/index.js rename to node-tests/fixtures/modules/node_modules/my-module/node_modules/other-dependency/index.js diff --git a/test/fixtures/modules/node_modules/my-module/node_modules/other-dependency/package.json b/node-tests/fixtures/modules/node_modules/my-module/node_modules/other-dependency/package.json similarity index 100% rename from test/fixtures/modules/node_modules/my-module/node_modules/other-dependency/package.json rename to node-tests/fixtures/modules/node_modules/my-module/node_modules/other-dependency/package.json diff --git a/test/fixtures/modules/node_modules/my-module/package.json b/node-tests/fixtures/modules/node_modules/my-module/package.json similarity index 100% rename from test/fixtures/modules/node_modules/my-module/package.json rename to node-tests/fixtures/modules/node_modules/my-module/package.json diff --git a/test/fixtures/modules/node_modules/package.json b/node-tests/fixtures/modules/node_modules/package.json similarity index 100% rename from test/fixtures/modules/node_modules/package.json rename to node-tests/fixtures/modules/node_modules/package.json diff --git a/test/fixtures/modules/node_modules/y/index.js b/node-tests/fixtures/modules/node_modules/something-new/index.js similarity index 100% rename from test/fixtures/modules/node_modules/y/index.js rename to node-tests/fixtures/modules/node_modules/something-new/index.js diff --git a/test/fixtures/modules/node_modules/something-new/package.json b/node-tests/fixtures/modules/node_modules/something-new/package.json similarity index 100% rename from test/fixtures/modules/node_modules/something-new/package.json rename to node-tests/fixtures/modules/node_modules/something-new/package.json diff --git a/node-tests/fixtures/modules/node_modules/x/index.js b/node-tests/fixtures/modules/node_modules/x/index.js new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/modules/node_modules/x/package.json b/node-tests/fixtures/modules/node_modules/x/package.json similarity index 100% rename from test/fixtures/modules/node_modules/x/package.json rename to node-tests/fixtures/modules/node_modules/x/package.json diff --git a/node-tests/fixtures/modules/node_modules/y/index.js b/node-tests/fixtures/modules/node_modules/y/index.js new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/modules/node_modules/y/package.json b/node-tests/fixtures/modules/node_modules/y/package.json similarity index 100% rename from test/fixtures/modules/node_modules/y/package.json rename to node-tests/fixtures/modules/node_modules/y/package.json diff --git a/test/fixtures/modules/src/broken_stubs.js b/node-tests/fixtures/modules/src/broken_stubs.js similarity index 100% rename from test/fixtures/modules/src/broken_stubs.js rename to node-tests/fixtures/modules/src/broken_stubs.js diff --git a/test/fixtures/modules/src/browserify_stubs.js b/node-tests/fixtures/modules/src/browserify_stubs.js similarity index 100% rename from test/fixtures/modules/src/browserify_stubs.js rename to node-tests/fixtures/modules/src/browserify_stubs.js diff --git a/test/fixtures/modules/src/second_stubs.js b/node-tests/fixtures/modules/src/second_stubs.js similarity index 100% rename from test/fixtures/modules/src/second_stubs.js rename to node-tests/fixtures/modules/src/second_stubs.js diff --git a/test/fixtures/stubs/es5/inner/other.js b/node-tests/fixtures/stubs/es5/inner/other.js similarity index 100% rename from test/fixtures/stubs/es5/inner/other.js rename to node-tests/fixtures/stubs/es5/inner/other.js diff --git a/test/fixtures/stubs/es5/sample.js b/node-tests/fixtures/stubs/es5/sample.js similarity index 100% rename from test/fixtures/stubs/es5/sample.js rename to node-tests/fixtures/stubs/es5/sample.js diff --git a/test/helpers/keys.js b/node-tests/helpers/keys.js similarity index 100% rename from test/helpers/keys.js rename to node-tests/helpers/keys.js diff --git a/test/helpers/loader.js b/node-tests/helpers/loader.js similarity index 100% rename from test/helpers/loader.js rename to node-tests/helpers/loader.js diff --git a/test/imports-for-test.js b/node-tests/imports-for-test.js similarity index 100% rename from test/imports-for-test.js rename to node-tests/imports-for-test.js diff --git a/test/jshint.js b/node-tests/jshint.js similarity index 100% rename from test/jshint.js rename to node-tests/jshint.js diff --git a/test/stub-generator-tests.js b/node-tests/stub-generator-tests.js similarity index 100% rename from test/stub-generator-tests.js rename to node-tests/stub-generator-tests.js diff --git a/test/stubs-test.js b/node-tests/stubs-test.js similarity index 100% rename from test/stubs-test.js rename to node-tests/stubs-test.js diff --git a/package.json b/package.json index 6785246..3212087 100644 --- a/package.json +++ b/package.json @@ -2,14 +2,17 @@ "name": "ember-browserify", "description": "ember-cli addon for easily loading CommonJS modules from npm via browserify.", "version": "1.1.13", - "main": "index.js", + "main": "lib/index.js", "directories": { "doc": "doc", "test": "tests" }, "scripts": { - "test": "mocha --inline-diffs", - "test:debug": "mocha debug --inline-diffs" + "build": "ember build", + "start": "ember server", + "test": "npm run node-test && ember try:each", + "node-test": "mocha node-tests --inline-diffs", + "node-test:debug": "mocha debug node-tests --inline-diffs" }, "repository": "https://github.com/ef4/ember-browserify", "engines": { @@ -28,9 +31,30 @@ "mocha": "^2.0.1", "mocha-jshint": "2.3.1", "sinon": "^1.12.2", - "sinon-chai": "^2.6.0" + "sinon-chai": "^2.6.0", + "broccoli-asset-rev": "^2.4.2", + "ember-ajax": "^2.0.1", + "ember-cli": "2.8.0", + "ember-cli-app-version": "^1.0.0", + "ember-cli-dependency-checker": "^1.2.0", + "ember-cli-htmlbars": "^1.0.3", + "ember-cli-htmlbars-inline-precompile": "^0.3.1", + "ember-cli-inject-live-reload": "^1.4.0", + "ember-cli-jshint": "^1.0.0", + "ember-cli-qunit": "^2.1.0", + "ember-cli-release": "^0.2.9", + "ember-cli-sri": "^2.1.0", + "ember-cli-test-loader": "^1.1.0", + "ember-cli-uglify": "^1.2.0", + "ember-data": "^2.8.0", + "ember-disable-prototype-extensions": "^1.1.0", + "ember-export-application-global": "^1.0.5", + "ember-load-initializers": "^0.5.1", + "ember-resolver": "^2.0.3", + "loader.js": "^4.0.1" }, "dependencies": { + "ember-cli-babel": "^5.1.6", "acorn": "^2.6.4", "broccoli-caching-writer": "^3.0.3", "broccoli-funnel": "^1.0.6", @@ -56,5 +80,8 @@ "symlink-or-copy": "^1.0.0", "through2": "^2.0.0", "walk-sync": "^0.3.1" + }, + "ember-addon": { + "configPath": "tests/dummy/config" } } diff --git a/testem.js b/testem.js new file mode 100644 index 0000000..26044b2 --- /dev/null +++ b/testem.js @@ -0,0 +1,13 @@ +/*jshint node:true*/ +module.exports = { + "framework": "qunit", + "test_page": "tests/index.html?hidepassed", + "disable_watching": true, + "launch_in_ci": [ + "PhantomJS" + ], + "launch_in_dev": [ + "PhantomJS", + "Chrome" + ] +}; diff --git a/tests/.jshintrc b/tests/.jshintrc new file mode 100644 index 0000000..d2bd113 --- /dev/null +++ b/tests/.jshintrc @@ -0,0 +1,52 @@ +{ + "predef": [ + "document", + "window", + "location", + "setTimeout", + "$", + "-Promise", + "define", + "console", + "visit", + "exists", + "fillIn", + "click", + "keyEvent", + "triggerEvent", + "find", + "findWithAssert", + "wait", + "DS", + "andThen", + "currentURL", + "currentPath", + "currentRouteName" + ], + "node": false, + "browser": false, + "boss": true, + "curly": true, + "debug": false, + "devel": false, + "eqeqeq": true, + "evil": true, + "forin": false, + "immed": false, + "laxbreak": false, + "newcap": true, + "noarg": true, + "noempty": false, + "nonew": false, + "nomen": false, + "onevar": false, + "plusplus": false, + "regexp": false, + "undef": true, + "sub": true, + "strict": false, + "white": false, + "eqnull": true, + "esversion": 6, + "unused": true +} diff --git a/tests/dummy/app/app.js b/tests/dummy/app/app.js new file mode 100644 index 0000000..831ad61 --- /dev/null +++ b/tests/dummy/app/app.js @@ -0,0 +1,18 @@ +import Ember from 'ember'; +import Resolver from './resolver'; +import loadInitializers from 'ember-load-initializers'; +import config from './config/environment'; + +let App; + +Ember.MODEL_FACTORY_INJECTIONS = true; + +App = Ember.Application.extend({ + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix, + Resolver +}); + +loadInitializers(App, config.modulePrefix); + +export default App; diff --git a/tests/dummy/app/components/.gitkeep b/tests/dummy/app/components/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/dummy/app/controllers/.gitkeep b/tests/dummy/app/controllers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/dummy/app/helpers/.gitkeep b/tests/dummy/app/helpers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/dummy/app/index.html b/tests/dummy/app/index.html new file mode 100644 index 0000000..5120bd7 --- /dev/null +++ b/tests/dummy/app/index.html @@ -0,0 +1,25 @@ + + + + + + Dummy + + + + {{content-for "head"}} + + + + + {{content-for "head-footer"}} + + + {{content-for "body"}} + + + + + {{content-for "body-footer"}} + + diff --git a/tests/dummy/app/models/.gitkeep b/tests/dummy/app/models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/dummy/app/resolver.js b/tests/dummy/app/resolver.js new file mode 100644 index 0000000..2fb563d --- /dev/null +++ b/tests/dummy/app/resolver.js @@ -0,0 +1,3 @@ +import Resolver from 'ember-resolver'; + +export default Resolver; diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js new file mode 100644 index 0000000..cdc2578 --- /dev/null +++ b/tests/dummy/app/router.js @@ -0,0 +1,12 @@ +import Ember from 'ember'; +import config from './config/environment'; + +const Router = Ember.Router.extend({ + location: config.locationType, + rootURL: config.rootURL +}); + +Router.map(function() { +}); + +export default Router; diff --git a/tests/dummy/app/routes/.gitkeep b/tests/dummy/app/routes/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/dummy/app/styles/app.css b/tests/dummy/app/styles/app.css new file mode 100644 index 0000000..e69de29 diff --git a/tests/dummy/app/templates/components/.gitkeep b/tests/dummy/app/templates/components/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js new file mode 100644 index 0000000..2529939 --- /dev/null +++ b/tests/dummy/config/environment.js @@ -0,0 +1,46 @@ +/* jshint node: true */ + +module.exports = function(environment) { + var ENV = { + modulePrefix: 'dummy', + environment: environment, + rootURL: '/', + locationType: 'auto', + EmberENV: { + FEATURES: { + // Here you can enable experimental features on an ember canary build + // e.g. 'with-controller': true + } + }, + + APP: { + // Here you can pass flags/options to your application instance + // when it is created + } + }; + + if (environment === 'development') { + // ENV.APP.LOG_RESOLVER = true; + // ENV.APP.LOG_ACTIVE_GENERATION = true; + // ENV.APP.LOG_TRANSITIONS = true; + // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; + // ENV.APP.LOG_VIEW_LOOKUPS = true; + } + + if (environment === 'test') { + // Testem prefers this... + ENV.locationType = 'none'; + + // keep test console output quieter + ENV.APP.LOG_ACTIVE_GENERATION = false; + ENV.APP.LOG_VIEW_LOOKUPS = false; + + ENV.APP.rootElement = '#ember-testing'; + } + + if (environment === 'production') { + + } + + return ENV; +}; diff --git a/tests/dummy/public/crossdomain.xml b/tests/dummy/public/crossdomain.xml new file mode 100644 index 0000000..0c16a7a --- /dev/null +++ b/tests/dummy/public/crossdomain.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/tests/dummy/public/robots.txt b/tests/dummy/public/robots.txt new file mode 100644 index 0000000..f591645 --- /dev/null +++ b/tests/dummy/public/robots.txt @@ -0,0 +1,3 @@ +# http://www.robotstxt.org +User-agent: * +Disallow: diff --git a/tests/helpers/destroy-app.js b/tests/helpers/destroy-app.js new file mode 100644 index 0000000..c3d4d1a --- /dev/null +++ b/tests/helpers/destroy-app.js @@ -0,0 +1,5 @@ +import Ember from 'ember'; + +export default function destroyApp(application) { + Ember.run(application, 'destroy'); +} diff --git a/tests/helpers/module-for-acceptance.js b/tests/helpers/module-for-acceptance.js new file mode 100644 index 0000000..76996fd --- /dev/null +++ b/tests/helpers/module-for-acceptance.js @@ -0,0 +1,23 @@ +import { module } from 'qunit'; +import Ember from 'ember'; +import startApp from '../helpers/start-app'; +import destroyApp from '../helpers/destroy-app'; + +const { RSVP: { Promise } } = Ember; + +export default function(name, options = {}) { + module(name, { + beforeEach() { + this.application = startApp(); + + if (options.beforeEach) { + return options.beforeEach.apply(this, arguments); + } + }, + + afterEach() { + let afterEach = options.afterEach && options.afterEach.apply(this, arguments); + return Promise.resolve(afterEach).then(() => destroyApp(this.application)); + } + }); +} diff --git a/tests/helpers/resolver.js b/tests/helpers/resolver.js new file mode 100644 index 0000000..b208d38 --- /dev/null +++ b/tests/helpers/resolver.js @@ -0,0 +1,11 @@ +import Resolver from '../../resolver'; +import config from '../../config/environment'; + +const resolver = Resolver.create(); + +resolver.namespace = { + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix +}; + +export default resolver; diff --git a/tests/helpers/start-app.js b/tests/helpers/start-app.js new file mode 100644 index 0000000..e098f1d --- /dev/null +++ b/tests/helpers/start-app.js @@ -0,0 +1,18 @@ +import Ember from 'ember'; +import Application from '../../app'; +import config from '../../config/environment'; + +export default function startApp(attrs) { + let application; + + let attributes = Ember.merge({}, config.APP); + attributes = Ember.merge(attributes, attrs); // use defaults, but you can override; + + Ember.run(() => { + application = Application.create(attributes); + application.setupForTesting(); + application.injectTestHelpers(); + }); + + return application; +} diff --git a/tests/index.html b/tests/index.html new file mode 100644 index 0000000..f7ff652 --- /dev/null +++ b/tests/index.html @@ -0,0 +1,33 @@ + + + + + + Dummy Tests + + + + {{content-for "head"}} + {{content-for "test-head"}} + + + + + + {{content-for "head-footer"}} + {{content-for "test-head-footer"}} + + + {{content-for "body"}} + {{content-for "test-body"}} + + + + + + + + {{content-for "body-footer"}} + {{content-for "test-body-footer"}} + + diff --git a/tests/integration/.gitkeep b/tests/integration/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/test-helper.js b/tests/test-helper.js new file mode 100644 index 0000000..e6cfb70 --- /dev/null +++ b/tests/test-helper.js @@ -0,0 +1,6 @@ +import resolver from './helpers/resolver'; +import { + setResolver +} from 'ember-qunit'; + +setResolver(resolver); diff --git a/tests/unit/.gitkeep b/tests/unit/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/vendor/.gitkeep b/vendor/.gitkeep new file mode 100644 index 0000000..e69de29 From 06836338dc28b7aec29763fb9d42e6e5b59176d4 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Wed, 14 Sep 2016 15:09:27 -0700 Subject: [PATCH 17/46] Fix CI. --- .travis.yml | 41 +++++++++++++++++++++++++++++++++++------ appveyor.yml | 2 +- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index eae0e25..221a4b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,39 @@ --- language: node_js sudo: false -before_install: - - npm install -g npm@2 - - npm install -g npm +node_js: + - "0.12" + - node + +cache: + directories: + - node_modules + +env: + # we recommend testing LTS's and latest stable release (bonus points to beta/canary) + - EMBER_TRY_SCENARIO=ember-1.13 + - EMBER_TRY_SCENARIO=ember-lts-2.4 + - EMBER_TRY_SCENARIO=ember-release + - EMBER_TRY_SCENARIO=ember-beta + - EMBER_TRY_SCENARIO=ember-canary + matrix: - include: - - node_js: '0.12' - - node_js: node + fast_finish: true + allow_failures: + - env: EMBER_TRY_SCENARIO=ember-canary + +before_install: + - npm config set spin false + - npm install -g bower + - bower --version + - npm install phantomjs-prebuilt + - node_modules/phantomjs-prebuilt/bin/phantomjs --version + +install: + - npm install + - bower install + +script: + # Usually, it's ok to finish the test scenario without reverting + # to the addon's original dependency state, skipping "cleanup". + - ember try:one $EMBER_TRY_SCENARIO test --skip-cleanup diff --git a/appveyor.yml b/appveyor.yml index 3e2f25d..4b37c71 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -18,7 +18,7 @@ install: test_script: # Output useful info for debugging. - npm version - - cmd: npm test + - cmd: npm run node-test # Don't actually build. build: off From f02b3a515ef3a0c4db80995396cc722e9e3cd486 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Wed, 14 Sep 2016 15:05:36 -0700 Subject: [PATCH 18/46] Add in VS Code debug profile for mocha. --- .vscode/launch.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4469ddd --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Mocha", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", + "stopOnEntry": false, + "args": ["node-tests"], + "cwd": "${workspaceRoot}", + "preLaunchTask": null, + "runtimeExecutable": null, + "runtimeArgs": [ + "--nolazy" + ], + "env": { + "NODE_ENV": "development" + }, + "externalConsole": false, + "sourceMaps": false, + "outDir": null + } + ] +} \ No newline at end of file From 8fa1b0d6d8fb8efc2ddcf64200f31964c6733034 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Wed, 14 Sep 2016 17:14:36 -0700 Subject: [PATCH 19/46] Use string positions to handle replacement. --- lib/imports-for.js | 6 +++--- lib/stub-generator.js | 39 ++++++++++++++++++++++++---------- node-tests/imports-for-test.js | 9 ++++---- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/lib/imports-for.js b/lib/imports-for.js index a0a6cb1..3b1bec5 100644 --- a/lib/imports-for.js +++ b/lib/imports-for.js @@ -14,7 +14,7 @@ function importsFor(src, fullPath) { } function forEachNode(node, visit) { - if (node && typeof node === 'object' && !node._eb_visited) { + if (node && typeof node === 'object' && !(node instanceof acorn.SourceLocation) && !node._eb_visited) { node._eb_visited = true; visit(node); var keys = Object.keys(node); @@ -31,7 +31,7 @@ function head(array) { function parse(src) { var imports = {}; - var ast = acorn.parse(src); + var ast = acorn.parse(src, { locations: true }); forEachNode(ast, function(entry) { if (entry.type === 'CallExpression' && entry.callee.name === 'define') { @@ -40,7 +40,7 @@ function parse(src) { })).elements.filter(function(element) { return element.value.slice(0, 4) === 'npm:'; }).forEach(function(element) { - imports[element.value.slice(4)] = true; + imports[element.value.slice(4)] = element.loc; }); } }); diff --git a/lib/stub-generator.js b/lib/stub-generator.js index 7760781..51c8ed9 100644 --- a/lib/stub-generator.js +++ b/lib/stub-generator.js @@ -73,21 +73,17 @@ StubGenerator.prototype.build = function() { case 'change': if (!/\.js$/.test(path)) { break; } - var content = fs.readFileSync(fullInputPath, 'UTF8'); - var data = {}; var imports = importsFor(content); Object.keys(imports).forEach(function(name) { - data[name] = { - version: versionForModuleName(name, this.basedir) - }; + imports[name].version = versionForModuleName(name, this.basedir); }, this); // TODO: only add files that required rewriting - fs.writeFileSync(fullOutputPath, rewriteImports(content, data)); + fs.writeFileSync(fullOutputPath, rewriteImports(content, imports)); - this.stubs.set(fullInputPath, data); + this.stubs.set(fullInputPath, imports); break; } @@ -101,14 +97,35 @@ StubGenerator.prototype.build = function() { debug('build in %dms', Date.now() - start); }; +// TODO: Extract function rewriteImports(content, data) { - // TODO: real AST printing might be a good plan.. + var lines = content.split('\n'); + var offsets = []; + Object.keys(data).forEach(function(name) { + var line = data[name].start.line - 1; + + if (offsets[line] === undefined) { + offsets[line] = 0; + } + + var start = data[name].start.column + offsets[line]; + var end = data[name].end.column + offsets[line]; var version = data[name].version; - content = content.replace(new RegExp('["]npm:' + name + '["]', 'g'), '"npm:' + name + '@' + version + '"'); - content = content.replace(new RegExp('[\']npm:' + name + '[\']', 'g'), '\'npm:' + name + '@' + version + '\''); + + var pre = lines[line].substring(0, start); + var moduleString = '"npm:' + name + '@' + version + '"'; + var post = lines[line].substring(end); + + lines[line] = [pre, moduleString, post].join(''); + + // Every time we make a replacement we need to adjust the offsets. + // We know that, by rule, these offsets will come in order. + // This means we only need to store the total cumulative offset. + offsets[line] += moduleString.length - (end - start); }); - return content; + + return lines.join('\n'); } StubGenerator.prototype.writeFileIfContentChanged = function(fullPath, content) { diff --git a/node-tests/imports-for-test.js b/node-tests/imports-for-test.js index 5217d7d..c02fed5 100644 --- a/node-tests/imports-for-test.js +++ b/node-tests/imports-for-test.js @@ -3,11 +3,12 @@ var expect = require('chai').expect; var importsFor = require('../lib/imports-for'); +function toPojo(obj) { + return JSON.parse(JSON.stringify(obj)); +} + describe('importsFor', function() { it('parses AMD (ES5)', function() { - expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); - expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); - expect(importsFor('define("asdf", ["npm:asdf"], function() { });')).to.eql({ asdf: true }); - expect(importsFor('define("apple", ["npm:foo"], function() { });')).to.eql({ foo: true }); + expect(toPojo(importsFor('define("apple", ["npm:foo"], function() { });'))).to.eql({ foo: { "end": { "column": 26, "line": 1 }, "start": { "column": 17, "line": 1 } } }); }); }); From 2ef155c7634e9c1afa6a4b635df5ba470617b4b1 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Thu, 15 Sep 2016 09:27:53 -0700 Subject: [PATCH 20/46] Extract rewrite-imports. --- lib/rewrite-imports.js | 29 +++++++++++++++++++++++++++++ lib/stub-generator.js | 32 +------------------------------- 2 files changed, 30 insertions(+), 31 deletions(-) create mode 100644 lib/rewrite-imports.js diff --git a/lib/rewrite-imports.js b/lib/rewrite-imports.js new file mode 100644 index 0000000..3328e0b --- /dev/null +++ b/lib/rewrite-imports.js @@ -0,0 +1,29 @@ +module.exports = function rewriteImports(content, data) { + var lines = content.split('\n'); + var offsets = []; + + Object.keys(data).forEach(function(name) { + var line = data[name].start.line - 1; + + if (offsets[line] === undefined) { + offsets[line] = 0; + } + + var start = data[name].start.column + offsets[line]; + var end = data[name].end.column + offsets[line]; + var version = data[name].version; + + var pre = lines[line].substring(0, start); + var moduleString = '"npm:' + name + '@' + version + '"'; + var post = lines[line].substring(end); + + lines[line] = [pre, moduleString, post].join(''); + + // Every time we make a replacement we need to adjust the offsets. + // We know that, by rule, these offsets will come in order. + // This means we only need to store the total cumulative offset. + offsets[line] += moduleString.length - (end - start); + }); + + return lines.join('\n'); +}; \ No newline at end of file diff --git a/lib/stub-generator.js b/lib/stub-generator.js index 51c8ed9..1144d49 100644 --- a/lib/stub-generator.js +++ b/lib/stub-generator.js @@ -8,6 +8,7 @@ var fs = require('fs'); var md5Hex = require('md5-hex'); var debug = require('debug')('ember-browserify:stub-generator:'); var importsFor = require('./imports-for'); +var rewriteImports = require('./rewrite-imports'); var versionForModuleName = require('./version-for-module-name'); module.exports = StubGenerator; @@ -97,37 +98,6 @@ StubGenerator.prototype.build = function() { debug('build in %dms', Date.now() - start); }; -// TODO: Extract -function rewriteImports(content, data) { - var lines = content.split('\n'); - var offsets = []; - - Object.keys(data).forEach(function(name) { - var line = data[name].start.line - 1; - - if (offsets[line] === undefined) { - offsets[line] = 0; - } - - var start = data[name].start.column + offsets[line]; - var end = data[name].end.column + offsets[line]; - var version = data[name].version; - - var pre = lines[line].substring(0, start); - var moduleString = '"npm:' + name + '@' + version + '"'; - var post = lines[line].substring(end); - - lines[line] = [pre, moduleString, post].join(''); - - // Every time we make a replacement we need to adjust the offsets. - // We know that, by rule, these offsets will come in order. - // This means we only need to store the total cumulative offset. - offsets[line] += moduleString.length - (end - start); - }); - - return lines.join('\n'); -} - StubGenerator.prototype.writeFileIfContentChanged = function(fullPath, content) { var previous = this._fileToChecksumMap[fullPath]; var next = md5Hex(content); From 74ab9851a2476b0409cdfa648cc41bcad468cc50 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Thu, 15 Sep 2016 10:27:51 -0700 Subject: [PATCH 21/46] Alphabetize package.json --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 3212087..eb14a08 100644 --- a/package.json +++ b/package.json @@ -25,14 +25,10 @@ "license": "MIT", "devDependencies": { "broccoli": "^0.16.8", + "broccoli-asset-rev": "^2.4.2", "chai": "^3.5.0", "chai-files": "^1.4.0", "copy-dereference": "^1.0.0", - "mocha": "^2.0.1", - "mocha-jshint": "2.3.1", - "sinon": "^1.12.2", - "sinon-chai": "^2.6.0", - "broccoli-asset-rev": "^2.4.2", "ember-ajax": "^2.0.1", "ember-cli": "2.8.0", "ember-cli-app-version": "^1.0.0", @@ -51,10 +47,13 @@ "ember-export-application-global": "^1.0.5", "ember-load-initializers": "^0.5.1", "ember-resolver": "^2.0.3", - "loader.js": "^4.0.1" + "loader.js": "^4.0.1", + "mocha": "^2.0.1", + "mocha-jshint": "2.3.1", + "sinon": "^1.12.2", + "sinon-chai": "^2.6.0" }, "dependencies": { - "ember-cli-babel": "^5.1.6", "acorn": "^2.6.4", "broccoli-caching-writer": "^3.0.3", "broccoli-funnel": "^1.0.6", @@ -65,6 +64,7 @@ "core-object": "^1.1.0", "debug": "^2.2.0", "derequire": "^2.0.3", + "ember-cli-babel": "^5.1.6", "ember-cli-version-checker": "^1.1.4", "find-up": "^1.1.2", "fs-tree": "^1.0.0", From b65c1625771b9938e20e2b2fe098e1b8f4ba1b6f Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Thu, 15 Sep 2016 11:14:16 -0700 Subject: [PATCH 22/46] npm fixtures --- bin/install-ember-addons.sh | 10 ++++++++++ lib/.jshintrc | 4 ++++ package.json | 9 +++++++-- tests/dummy/app/routes/application.js | 10 ++++++++++ tests/dummy/app/templates/application.hbs | 1 + tests/dummy/lib/.jshintrc | 4 ++++ tests/dummy/lib/flooring/index.js | 1 + tests/dummy/lib/flooring/package.json | 5 +++++ tests/dummy/lib/modern/addon/utils/floor-type.js | 5 +++++ tests/dummy/lib/modern/index.js | 8 ++++++++ tests/dummy/lib/modern/node_modules/flooring/index.js | 1 + .../lib/modern/node_modules/flooring/package.json | 5 +++++ tests/dummy/lib/modern/package.json | 10 ++++++++++ tests/dummy/lib/outdated/addon/utils/floor-type.js | 5 +++++ tests/dummy/lib/outdated/index.js | 8 ++++++++ tests/dummy/lib/outdated/package.json | 10 ++++++++++ tests/unit/routes/application-test.js | 11 +++++++++++ 17 files changed, 105 insertions(+), 2 deletions(-) create mode 100755 bin/install-ember-addons.sh create mode 100644 lib/.jshintrc create mode 100644 tests/dummy/app/routes/application.js create mode 100644 tests/dummy/app/templates/application.hbs create mode 100644 tests/dummy/lib/.jshintrc create mode 100644 tests/dummy/lib/flooring/index.js create mode 100644 tests/dummy/lib/flooring/package.json create mode 100644 tests/dummy/lib/modern/addon/utils/floor-type.js create mode 100644 tests/dummy/lib/modern/index.js create mode 100644 tests/dummy/lib/modern/node_modules/flooring/index.js create mode 100644 tests/dummy/lib/modern/node_modules/flooring/package.json create mode 100644 tests/dummy/lib/modern/package.json create mode 100644 tests/dummy/lib/outdated/addon/utils/floor-type.js create mode 100644 tests/dummy/lib/outdated/index.js create mode 100644 tests/dummy/lib/outdated/package.json create mode 100644 tests/unit/routes/application-test.js diff --git a/bin/install-ember-addons.sh b/bin/install-ember-addons.sh new file mode 100755 index 0000000..6ab88bb --- /dev/null +++ b/bin/install-ember-addons.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env sh + +rm -rf node_modules/flooring +ln -s ../tests/dummy/lib/flooring node_modules/flooring + +rm -rf node_modules/modern +ln -s ../tests/dummy/lib/modern node_modules/modern + +rm -rf node_modules/outdated +ln -s ../tests/dummy/lib/outdated node_modules/outdated diff --git a/lib/.jshintrc b/lib/.jshintrc new file mode 100644 index 0000000..839c191 --- /dev/null +++ b/lib/.jshintrc @@ -0,0 +1,4 @@ +{ + "node": true, + "browser": false +} diff --git a/package.json b/package.json index eb14a08..4ccd61a 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "start": "ember server", "test": "npm run node-test && ember try:each", "node-test": "mocha node-tests --inline-diffs", - "node-test:debug": "mocha debug node-tests --inline-diffs" + "node-test:debug": "mocha debug node-tests --inline-diffs", + "prepublish": "./bin/install-ember-addons.sh" }, "repository": "https://github.com/ef4/ember-browserify", "engines": { @@ -82,6 +83,10 @@ "walk-sync": "^0.3.1" }, "ember-addon": { - "configPath": "tests/dummy/config" + "configPath": "tests/dummy/config", + "paths": [ + "lib/outdated", + "lib/modern" + ] } } diff --git a/tests/dummy/app/routes/application.js b/tests/dummy/app/routes/application.js new file mode 100644 index 0000000..7f9f582 --- /dev/null +++ b/tests/dummy/app/routes/application.js @@ -0,0 +1,10 @@ +import Ember from 'ember'; + +// Should be version 1970.0.0 +import flooring from 'npm:flooring'; + +export default Ember.Route.extend({ + model() { + return flooring(); + } +}); diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs new file mode 100644 index 0000000..c24cd68 --- /dev/null +++ b/tests/dummy/app/templates/application.hbs @@ -0,0 +1 @@ +{{outlet}} diff --git a/tests/dummy/lib/.jshintrc b/tests/dummy/lib/.jshintrc new file mode 100644 index 0000000..839c191 --- /dev/null +++ b/tests/dummy/lib/.jshintrc @@ -0,0 +1,4 @@ +{ + "node": true, + "browser": false +} diff --git a/tests/dummy/lib/flooring/index.js b/tests/dummy/lib/flooring/index.js new file mode 100644 index 0000000..fd59a48 --- /dev/null +++ b/tests/dummy/lib/flooring/index.js @@ -0,0 +1 @@ +module.exports = function() { return 'shag carpet'; }; diff --git a/tests/dummy/lib/flooring/package.json b/tests/dummy/lib/flooring/package.json new file mode 100644 index 0000000..5450566 --- /dev/null +++ b/tests/dummy/lib/flooring/package.json @@ -0,0 +1,5 @@ +{ + "name": "flooring", + "version": "1970.0.0", + "main": "index.js" +} diff --git a/tests/dummy/lib/modern/addon/utils/floor-type.js b/tests/dummy/lib/modern/addon/utils/floor-type.js new file mode 100644 index 0000000..5327a34 --- /dev/null +++ b/tests/dummy/lib/modern/addon/utils/floor-type.js @@ -0,0 +1,5 @@ +import flooring from 'npm:flooring'; + +export default function() { + return flooring(); +} diff --git a/tests/dummy/lib/modern/index.js b/tests/dummy/lib/modern/index.js new file mode 100644 index 0000000..f36adc5 --- /dev/null +++ b/tests/dummy/lib/modern/index.js @@ -0,0 +1,8 @@ +/*jshint node:true*/ +module.exports = { + name: 'modern', + + isDevelopingAddon: function() { + return true; + } +}; diff --git a/tests/dummy/lib/modern/node_modules/flooring/index.js b/tests/dummy/lib/modern/node_modules/flooring/index.js new file mode 100644 index 0000000..af9b26e --- /dev/null +++ b/tests/dummy/lib/modern/node_modules/flooring/index.js @@ -0,0 +1 @@ +module.exports = function() { return 'hardwood'; }; diff --git a/tests/dummy/lib/modern/node_modules/flooring/package.json b/tests/dummy/lib/modern/node_modules/flooring/package.json new file mode 100644 index 0000000..f791fcf --- /dev/null +++ b/tests/dummy/lib/modern/node_modules/flooring/package.json @@ -0,0 +1,5 @@ +{ + "name": "flooring", + "version": "2010.0.0", + "main": "index.js" +} diff --git a/tests/dummy/lib/modern/package.json b/tests/dummy/lib/modern/package.json new file mode 100644 index 0000000..2d3eb95 --- /dev/null +++ b/tests/dummy/lib/modern/package.json @@ -0,0 +1,10 @@ +{ + "name": "modern", + "version": "1.0.0", + "keywords": [ + "ember-addon" + ], + "dependencies": { + "flooring": "2010" + } +} diff --git a/tests/dummy/lib/outdated/addon/utils/floor-type.js b/tests/dummy/lib/outdated/addon/utils/floor-type.js new file mode 100644 index 0000000..5327a34 --- /dev/null +++ b/tests/dummy/lib/outdated/addon/utils/floor-type.js @@ -0,0 +1,5 @@ +import flooring from 'npm:flooring'; + +export default function() { + return flooring(); +} diff --git a/tests/dummy/lib/outdated/index.js b/tests/dummy/lib/outdated/index.js new file mode 100644 index 0000000..18bd621 --- /dev/null +++ b/tests/dummy/lib/outdated/index.js @@ -0,0 +1,8 @@ +/*jshint node:true*/ +module.exports = { + name: 'outdated', + + isDevelopingAddon: function() { + return true; + } +}; diff --git a/tests/dummy/lib/outdated/package.json b/tests/dummy/lib/outdated/package.json new file mode 100644 index 0000000..6505ab6 --- /dev/null +++ b/tests/dummy/lib/outdated/package.json @@ -0,0 +1,10 @@ +{ + "name": "outdated", + "version": "1.0.0", + "keywords": [ + "ember-addon" + ], + "dependencies": { + "flooring": "1970" + } +} diff --git a/tests/unit/routes/application-test.js b/tests/unit/routes/application-test.js new file mode 100644 index 0000000..bec00b8 --- /dev/null +++ b/tests/unit/routes/application-test.js @@ -0,0 +1,11 @@ +import { moduleFor, test } from 'ember-qunit'; + +moduleFor('route:application', 'Unit | Route | application', { + // Specify the other units that are required for this test. + // needs: ['controller:foo'] +}); + +test('it properly resolves npm modules', function(assert) { + let route = this.subject(); + assert.equal(route.model(), 'shag carpet'); +}); From a7f4b5da3eda37a9e81fe9ca0cca35b9dbbd0cac Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Thu, 15 Sep 2016 15:40:56 -0700 Subject: [PATCH 23/46] Set up top-level addon fixtures. --- package.json | 4 +-- tests/dummy/app/routes/application.js | 26 +++++++++++++++++++ .../lib/modern/app/utils/floor-modern.js | 5 ++++ .../lib/outdated/app/utils/floor-outdated.js | 5 ++++ tests/unit/routes/application-test.js | 11 ++++++++ 5 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 tests/dummy/lib/modern/app/utils/floor-modern.js create mode 100644 tests/dummy/lib/outdated/app/utils/floor-outdated.js diff --git a/package.json b/package.json index 4ccd61a..b12f021 100644 --- a/package.json +++ b/package.json @@ -85,8 +85,8 @@ "ember-addon": { "configPath": "tests/dummy/config", "paths": [ - "lib/outdated", - "lib/modern" + "node_modules/modern", + "node_modules/outdated" ] } } diff --git a/tests/dummy/app/routes/application.js b/tests/dummy/app/routes/application.js index 7f9f582..19af810 100644 --- a/tests/dummy/app/routes/application.js +++ b/tests/dummy/app/routes/application.js @@ -3,8 +3,34 @@ import Ember from 'ember'; // Should be version 1970.0.0 import flooring from 'npm:flooring'; +// Should be 1970.0.0, which the host app includes +import modernApp from '../utils/floor-modern'; +import outdatedApp from '../utils/floor-outdated'; + +// Should be version 1970.0.0 +import outdated from 'outdated/utils/floor-type'; + +// Should be version 2010.0.0 +import modern from 'modern/utils/floor-type'; + export default Ember.Route.extend({ model() { return flooring(); + }, + + modern() { + return modern(); + }, + + modernApp() { + return modernApp(); + }, + + outdated() { + return outdated(); + }, + + outdatedApp() { + return outdatedApp(); } }); diff --git a/tests/dummy/lib/modern/app/utils/floor-modern.js b/tests/dummy/lib/modern/app/utils/floor-modern.js new file mode 100644 index 0000000..5327a34 --- /dev/null +++ b/tests/dummy/lib/modern/app/utils/floor-modern.js @@ -0,0 +1,5 @@ +import flooring from 'npm:flooring'; + +export default function() { + return flooring(); +} diff --git a/tests/dummy/lib/outdated/app/utils/floor-outdated.js b/tests/dummy/lib/outdated/app/utils/floor-outdated.js new file mode 100644 index 0000000..5327a34 --- /dev/null +++ b/tests/dummy/lib/outdated/app/utils/floor-outdated.js @@ -0,0 +1,5 @@ +import flooring from 'npm:flooring'; + +export default function() { + return flooring(); +} diff --git a/tests/unit/routes/application-test.js b/tests/unit/routes/application-test.js index bec00b8..653ad30 100644 --- a/tests/unit/routes/application-test.js +++ b/tests/unit/routes/application-test.js @@ -7,5 +7,16 @@ moduleFor('route:application', 'Unit | Route | application', { test('it properly resolves npm modules', function(assert) { let route = this.subject(); + + // Host application which depends on flooring@1970 + // Set by virtue of folder structure. assert.equal(route.model(), 'shag carpet'); + assert.equal(route.modernApp(), 'shag carpet'); + assert.equal(route.outdatedApp(), 'shag carpet'); + + // Addon which depends on flooring@2010 + assert.equal(route.modern(), 'hardwood'); + + // Addon which depends on flooring@1970 + assert.equal(route.outdated(), 'shag carpet'); }); From 0850b99921da8e49b523fe3b3d82b9db1f31940a Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 09:15:57 -0700 Subject: [PATCH 24/46] Make sure caching-browserify (a legacy plugin) toStrings helpfully, so default broccoli errors name it correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather then `The Broccoli Plugin: [Object object] failed with: …` we get `The Broccoli Plugin: [CachingBrowserify] failed with: …` --- lib/caching-browserify.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/caching-browserify.js b/lib/caching-browserify.js index 212660f..c51a5bc 100644 --- a/lib/caching-browserify.js +++ b/lib/caching-browserify.js @@ -35,7 +35,7 @@ module.exports = CoreObject.extend({ quickTemp.makeOrRemake(this, '_destDir'); }, - description: 'ember-browserify', + description: 'CachingBrowserify', cleanup: function() { if (this._destDir) { @@ -49,6 +49,10 @@ module.exports = CoreObject.extend({ } }, + toString: function() { + return '[' + this.description + ']'; + }, + read: function (readTree) { var self = this; From d25ff3666102cd4fb143a16c797655f6aaac6862 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 09:17:07 -0700 Subject: [PATCH 25/46] add a very simple/basic scenario (that works) --- tests/dummy/app/app.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/dummy/app/app.js b/tests/dummy/app/app.js index 831ad61..3386bf7 100644 --- a/tests/dummy/app/app.js +++ b/tests/dummy/app/app.js @@ -2,7 +2,7 @@ import Ember from 'ember'; import Resolver from './resolver'; import loadInitializers from 'ember-load-initializers'; import config from './config/environment'; - +import acorn from 'npm:acorn'; let App; Ember.MODEL_FACTORY_INJECTIONS = true; @@ -10,7 +10,8 @@ Ember.MODEL_FACTORY_INJECTIONS = true; App = Ember.Application.extend({ modulePrefix: config.modulePrefix, podModulePrefix: config.podModulePrefix, - Resolver + Resolver, + acorn // just add this here, so hinting says happy }); loadInitializers(App, config.modulePrefix); From a60d9f9e0266b347bf159a9be94ce57f92d7af1c Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 10:53:06 -0700 Subject: [PATCH 26/46] remove unused file --- index.js | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 index.js diff --git a/index.js b/index.js deleted file mode 100644 index 6e692eb..0000000 --- a/index.js +++ /dev/null @@ -1,6 +0,0 @@ -/* jshint node: true */ -'use strict'; - -module.exports = { - name: 'ember-browserify' -}; From e5f3e89bb848902a2470d9acb21cbd2a1fa85cea Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 10:53:31 -0700 Subject: [PATCH 27/46] lazily require browserify, only injuring its load cost when used. --- lib/caching-browserify.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/caching-browserify.js b/lib/caching-browserify.js index c51a5bc..ffcfd44 100644 --- a/lib/caching-browserify.js +++ b/lib/caching-browserify.js @@ -2,7 +2,6 @@ var fs = require('fs'); var path = require('path'); -var browserify = require('browserify'); var helpers = require('broccoli-kitchen-sink-helpers'); var RSVP = require('rsvp'); var CoreObject = require('core-object'); @@ -109,7 +108,7 @@ module.exports = CoreObject.extend({ debug: this.enableSourcemap }, this.browserifyOptions); - var b = browserify(opts); + var b = require('browserify')(opts); ['transforms', 'externals', 'ignores', 'includes'].forEach(function(thing) { if (!opts[thing]) { return; } opts[thing].forEach(function(args) { From 1f4412787537a5e21397ad2a441d1ac6fec3011b Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 10:54:07 -0700 Subject: [PATCH 28/46] only include the part of lodash we use. --- lib/caching-browserify.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/caching-browserify.js b/lib/caching-browserify.js index ffcfd44..0908214 100644 --- a/lib/caching-browserify.js +++ b/lib/caching-browserify.js @@ -6,7 +6,7 @@ var helpers = require('broccoli-kitchen-sink-helpers'); var RSVP = require('rsvp'); var CoreObject = require('core-object'); var mapSeries = require('promise-map-series'); -var merge = require('lodash').merge; +var merge = require('lodash.merge').merge; var rimraf = require('rimraf'); var symlinkOrCopy = require('symlink-or-copy'); var quickTemp = require('quick-temp'); diff --git a/package.json b/package.json index b12f021..76374a3 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "find-up": "^1.1.2", "fs-tree": "^1.0.0", "fs-tree-diff": "^0.5.0", - "lodash": "^4.5.1", + "lodash.merge": "^4.6.0", "md5-hex": "^1.3.0", "mkdirp": "^0.5.1", "promise-map-series": "^0.2.0", From 47055a5d5f32852c99b4896bacdc029c9f27f802 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 10:54:17 -0700 Subject: [PATCH 29/46] update dependency to be more accurate --- tests/dummy/lib/outdated/app/utils/floor-outdated.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/dummy/lib/outdated/app/utils/floor-outdated.js b/tests/dummy/lib/outdated/app/utils/floor-outdated.js index 5327a34..aa73913 100644 --- a/tests/dummy/lib/outdated/app/utils/floor-outdated.js +++ b/tests/dummy/lib/outdated/app/utils/floor-outdated.js @@ -1,5 +1 @@ -import flooring from 'npm:flooring'; - -export default function() { - return flooring(); -} +export { default } from 'outdated/utils/floor-type'; From 8f250bbdcf87a2c526c197773a7925e76224d8f8 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 10:55:15 -0700 Subject: [PATCH 30/46] fix lodash usage --- lib/caching-browserify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/caching-browserify.js b/lib/caching-browserify.js index 0908214..80b25c3 100644 --- a/lib/caching-browserify.js +++ b/lib/caching-browserify.js @@ -6,7 +6,7 @@ var helpers = require('broccoli-kitchen-sink-helpers'); var RSVP = require('rsvp'); var CoreObject = require('core-object'); var mapSeries = require('promise-map-series'); -var merge = require('lodash.merge').merge; +var merge = require('lodash.merge'); var rimraf = require('rimraf'); var symlinkOrCopy = require('symlink-or-copy'); var quickTemp = require('quick-temp'); From 555d137f2646cad7b99eb141aa401d6b45037265 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 14:15:07 -0700 Subject: [PATCH 31/46] update example to more closely match what works --- tests/dummy/lib/flooring/index.js | 2 +- tests/dummy/lib/flooring/package.json | 2 +- tests/dummy/lib/modern/node_modules/flooring/index.js | 2 +- tests/dummy/lib/modern/node_modules/flooring/package.json | 2 +- tests/dummy/lib/modern/package.json | 3 ++- tests/dummy/lib/outdated/node_modules/flooring/index.js | 1 + tests/dummy/lib/outdated/node_modules/flooring/package.json | 5 +++++ tests/dummy/lib/outdated/package.json | 3 ++- 8 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 tests/dummy/lib/outdated/node_modules/flooring/index.js create mode 100644 tests/dummy/lib/outdated/node_modules/flooring/package.json diff --git a/tests/dummy/lib/flooring/index.js b/tests/dummy/lib/flooring/index.js index fd59a48..38e71c8 100644 --- a/tests/dummy/lib/flooring/index.js +++ b/tests/dummy/lib/flooring/index.js @@ -1 +1 @@ -module.exports = function() { return 'shag carpet'; }; +module.exports = function() { return 'something modern very modern'; }; diff --git a/tests/dummy/lib/flooring/package.json b/tests/dummy/lib/flooring/package.json index 5450566..b3cb42d 100644 --- a/tests/dummy/lib/flooring/package.json +++ b/tests/dummy/lib/flooring/package.json @@ -1,5 +1,5 @@ { "name": "flooring", - "version": "1970.0.0", + "version": "2016.0.0", "main": "index.js" } diff --git a/tests/dummy/lib/modern/node_modules/flooring/index.js b/tests/dummy/lib/modern/node_modules/flooring/index.js index af9b26e..fd59a48 100644 --- a/tests/dummy/lib/modern/node_modules/flooring/index.js +++ b/tests/dummy/lib/modern/node_modules/flooring/index.js @@ -1 +1 @@ -module.exports = function() { return 'hardwood'; }; +module.exports = function() { return 'shag carpet'; }; diff --git a/tests/dummy/lib/modern/node_modules/flooring/package.json b/tests/dummy/lib/modern/node_modules/flooring/package.json index f791fcf..5450566 100644 --- a/tests/dummy/lib/modern/node_modules/flooring/package.json +++ b/tests/dummy/lib/modern/node_modules/flooring/package.json @@ -1,5 +1,5 @@ { "name": "flooring", - "version": "2010.0.0", + "version": "1970.0.0", "main": "index.js" } diff --git a/tests/dummy/lib/modern/package.json b/tests/dummy/lib/modern/package.json index 2d3eb95..f9ae94c 100644 --- a/tests/dummy/lib/modern/package.json +++ b/tests/dummy/lib/modern/package.json @@ -5,6 +5,7 @@ "ember-addon" ], "dependencies": { - "flooring": "2010" + "flooring": "2010", + "ember-browserify": "*" } } diff --git a/tests/dummy/lib/outdated/node_modules/flooring/index.js b/tests/dummy/lib/outdated/node_modules/flooring/index.js new file mode 100644 index 0000000..fd59a48 --- /dev/null +++ b/tests/dummy/lib/outdated/node_modules/flooring/index.js @@ -0,0 +1 @@ +module.exports = function() { return 'shag carpet'; }; diff --git a/tests/dummy/lib/outdated/node_modules/flooring/package.json b/tests/dummy/lib/outdated/node_modules/flooring/package.json new file mode 100644 index 0000000..5450566 --- /dev/null +++ b/tests/dummy/lib/outdated/node_modules/flooring/package.json @@ -0,0 +1,5 @@ +{ + "name": "flooring", + "version": "1970.0.0", + "main": "index.js" +} diff --git a/tests/dummy/lib/outdated/package.json b/tests/dummy/lib/outdated/package.json index 6505ab6..5e0e678 100644 --- a/tests/dummy/lib/outdated/package.json +++ b/tests/dummy/lib/outdated/package.json @@ -5,6 +5,7 @@ "ember-addon" ], "dependencies": { - "flooring": "1970" + "flooring": "1970", + "ember-browserify": "*" } } From f605a3b3e71481cd7f653025006c18c73a7a798d Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 14:41:15 -0700 Subject: [PATCH 32/46] cross platform setup script --- bin/install-ember-addons.js | 18 ++++++++++++++++++ bin/install-ember-addons.sh | 10 ---------- package.json | 3 ++- 3 files changed, 20 insertions(+), 11 deletions(-) create mode 100755 bin/install-ember-addons.js delete mode 100755 bin/install-ember-addons.sh diff --git a/bin/install-ember-addons.js b/bin/install-ember-addons.js new file mode 100755 index 0000000..ea61004 --- /dev/null +++ b/bin/install-ember-addons.js @@ -0,0 +1,18 @@ +#!/usr/bin/env node + +var symlinkOrCopy = require('symlink-or-copy'); +var path = require('path'); +var rimraf = require('rimraf'); +var fs = require('fs'); + +['modern', 'outdated'].forEach(function(inRepoAddon) { + + var source = path.resolve(__dirname, '..', 'lib/index.js'); + var directory = path.resolve(__dirname, '..', 'tests/dummy/lib', inRepoAddon, 'node_modules/ember-browserify/lib/'); + var target = path.join(directory, 'index.js'); + console.log('rimraf', target); + + rimraf.sync(target); + console.log('symlink', source, target) + symlinkOrCopy.sync(source, target); +}); diff --git a/bin/install-ember-addons.sh b/bin/install-ember-addons.sh deleted file mode 100755 index 6ab88bb..0000000 --- a/bin/install-ember-addons.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env sh - -rm -rf node_modules/flooring -ln -s ../tests/dummy/lib/flooring node_modules/flooring - -rm -rf node_modules/modern -ln -s ../tests/dummy/lib/modern node_modules/modern - -rm -rf node_modules/outdated -ln -s ../tests/dummy/lib/outdated node_modules/outdated diff --git a/package.json b/package.json index 76374a3..5d3e8b0 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,8 @@ "mocha": "^2.0.1", "mocha-jshint": "2.3.1", "sinon": "^1.12.2", - "sinon-chai": "^2.6.0" + "sinon-chai": "^2.6.0", + "symlink-or-copy": "^1.1.6" }, "dependencies": { "acorn": "^2.6.4", From 062f674578e34a8bc497cae05f94dd530a08fb4a Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 14:41:28 -0700 Subject: [PATCH 33/46] remove trailing whitespace --- lib/rewrite-imports.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rewrite-imports.js b/lib/rewrite-imports.js index 3328e0b..cfcc0e8 100644 --- a/lib/rewrite-imports.js +++ b/lib/rewrite-imports.js @@ -21,8 +21,8 @@ module.exports = function rewriteImports(content, data) { // Every time we make a replacement we need to adjust the offsets. // We know that, by rule, these offsets will come in order. - // This means we only need to store the total cumulative offset. - offsets[line] += moduleString.length - (end - start); + // This means we only need to store the total cumulative offset. + offsets[line] += moduleString.length - (end - start); }); return lines.join('\n'); From e3c8b59abb602b6b30e21e4ab4bbc83a58814a09 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 14:43:18 -0700 Subject: [PATCH 34/46] update example to work with in-repo addons --- .gitignore | 4 ++++ .../lib/modern/node_modules/ember-browserify/lib/.gitkeep | 0 .../lib/modern/node_modules/ember-browserify/package.json | 8 ++++++++ tests/dummy/lib/modern/node_modules/flooring/index.js | 2 +- tests/dummy/lib/modern/node_modules/flooring/package.json | 2 +- .../outdated/node_modules/ember-browserify/lib/.gitkeep | 0 .../outdated/node_modules/ember-browserify/package.json | 8 ++++++++ 7 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/dummy/lib/modern/node_modules/ember-browserify/lib/.gitkeep create mode 100644 tests/dummy/lib/modern/node_modules/ember-browserify/package.json create mode 100644 tests/dummy/lib/outdated/node_modules/ember-browserify/lib/.gitkeep create mode 100644 tests/dummy/lib/outdated/node_modules/ember-browserify/package.json diff --git a/.gitignore b/.gitignore index 86fceae..6e74c6d 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,7 @@ /libpeerconnection.log npm-debug.log testem.log + +# specific to fancy symlinks we require +tests/dummy/lib/modern/node_modules/ember-browserify/lib/index.js +tests/dummy/lib/outdated/node_modules/ember-browserify/lib/index.js diff --git a/tests/dummy/lib/modern/node_modules/ember-browserify/lib/.gitkeep b/tests/dummy/lib/modern/node_modules/ember-browserify/lib/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/dummy/lib/modern/node_modules/ember-browserify/package.json b/tests/dummy/lib/modern/node_modules/ember-browserify/package.json new file mode 100644 index 0000000..bdd7fd3 --- /dev/null +++ b/tests/dummy/lib/modern/node_modules/ember-browserify/package.json @@ -0,0 +1,8 @@ +{ + "name": "ember-browserify", + "version": "*", + "main": "lib/index.js", + "keywords": [ + "ember-addon" + ] +} diff --git a/tests/dummy/lib/modern/node_modules/flooring/index.js b/tests/dummy/lib/modern/node_modules/flooring/index.js index fd59a48..d1c9bf6 100644 --- a/tests/dummy/lib/modern/node_modules/flooring/index.js +++ b/tests/dummy/lib/modern/node_modules/flooring/index.js @@ -1 +1 @@ -module.exports = function() { return 'shag carpet'; }; +module.exports = function() { return 'something more or less modern'; }; diff --git a/tests/dummy/lib/modern/node_modules/flooring/package.json b/tests/dummy/lib/modern/node_modules/flooring/package.json index 5450566..f791fcf 100644 --- a/tests/dummy/lib/modern/node_modules/flooring/package.json +++ b/tests/dummy/lib/modern/node_modules/flooring/package.json @@ -1,5 +1,5 @@ { "name": "flooring", - "version": "1970.0.0", + "version": "2010.0.0", "main": "index.js" } diff --git a/tests/dummy/lib/outdated/node_modules/ember-browserify/lib/.gitkeep b/tests/dummy/lib/outdated/node_modules/ember-browserify/lib/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/dummy/lib/outdated/node_modules/ember-browserify/package.json b/tests/dummy/lib/outdated/node_modules/ember-browserify/package.json new file mode 100644 index 0000000..bdd7fd3 --- /dev/null +++ b/tests/dummy/lib/outdated/node_modules/ember-browserify/package.json @@ -0,0 +1,8 @@ +{ + "name": "ember-browserify", + "version": "*", + "main": "lib/index.js", + "keywords": [ + "ember-addon" + ] +} From 2c686a02e491007a067916f7c7f153e135020cae Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Fri, 16 Sep 2016 14:56:39 -0700 Subject: [PATCH 35/46] update symlink/junction hack to work in more cases --- .gitignore | 16 +++++++++++++--- bin/install-ember-addons.js | 7 +++---- lib/index.js | 2 ++ .../node_modules/ember-browserify/lib/.gitkeep | 0 .../node_modules/ember-browserify/lib/.gitkeep | 0 5 files changed, 18 insertions(+), 7 deletions(-) delete mode 100644 tests/dummy/lib/modern/node_modules/ember-browserify/lib/.gitkeep delete mode 100644 tests/dummy/lib/outdated/node_modules/ember-browserify/lib/.gitkeep diff --git a/.gitignore b/.gitignore index 6e74c6d..bcf4db6 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,16 @@ npm-debug.log testem.log -# specific to fancy symlinks we require -tests/dummy/lib/modern/node_modules/ember-browserify/lib/index.js -tests/dummy/lib/outdated/node_modules/ember-browserify/lib/index.js +# linking ember-browserify here, so addon-discovery bug is worked-around. +# linking the dir, so as: +# * not to create a cycyle +# * use the correct version of ember-browserify +# * use symlinks when possible, but correctly fallback to junctions on windows +# (if no symlinks are used) +# * symlinked files turn out to be realpathSync'd before being loaded into +# node, which means this should nicely trick node. Atleast in posix, although +# in windows this may also be true with junctions... Ultimately this is just +# for testing, and its working around a potential addon-discovery bug which +# will hopefully soon be addressed. +tests/dummy/lib/modern/node_modules/ember-browserify/lib +tests/dummy/lib/outdated/node_modules/ember-browserify/lib diff --git a/bin/install-ember-addons.js b/bin/install-ember-addons.js index ea61004..737691d 100755 --- a/bin/install-ember-addons.js +++ b/bin/install-ember-addons.js @@ -6,13 +6,12 @@ var rimraf = require('rimraf'); var fs = require('fs'); ['modern', 'outdated'].forEach(function(inRepoAddon) { + var source = path.resolve(__dirname, '..', 'lib/'); + var target = path.resolve(__dirname, '..', 'tests/dummy/lib', inRepoAddon, 'node_modules/ember-browserify/lib/'); - var source = path.resolve(__dirname, '..', 'lib/index.js'); - var directory = path.resolve(__dirname, '..', 'tests/dummy/lib', inRepoAddon, 'node_modules/ember-browserify/lib/'); - var target = path.join(directory, 'index.js'); console.log('rimraf', target); - rimraf.sync(target); + console.log('symlink', source, target) symlinkOrCopy.sync(source, target); }); diff --git a/lib/index.js b/lib/index.js index f78629b..8f99503 100644 --- a/lib/index.js +++ b/lib/index.js @@ -29,6 +29,7 @@ module.exports = { if (emberCliVersion.satisfies('< 2.0.0')) { throw new TypeError('ember-browserify@^2.0.0 no longer supports ember-cli versions less then 2.0.0.'); } + this.that = app; app = findHost(this); @@ -58,6 +59,7 @@ module.exports = { }, postprocessTree: function(type, tree) { + console.log('OMG', type, this.name, this.app.name, this.that.name); var outputFile, options; if (type === 'js'){ diff --git a/tests/dummy/lib/modern/node_modules/ember-browserify/lib/.gitkeep b/tests/dummy/lib/modern/node_modules/ember-browserify/lib/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tests/dummy/lib/outdated/node_modules/ember-browserify/lib/.gitkeep b/tests/dummy/lib/outdated/node_modules/ember-browserify/lib/.gitkeep deleted file mode 100644 index e69de29..0000000 From f3e0231b5db563c4301e25bda98b763687c3ef7f Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Fri, 16 Sep 2016 15:33:02 -0700 Subject: [PATCH 36/46] Rework tests, add reexports scenario. --- tests/dummy/app/routes/application.js | 29 +++++++------------ tests/dummy/lib/flooring/index.js | 2 +- tests/dummy/lib/flooring/package.json | 2 +- .../lib/modern/app/utils/reexports-modern.js | 1 + .../lib/modern/node_modules/flooring/index.js | 2 +- tests/dummy/lib/modern/package.json | 2 +- .../lib/outdated/app/utils/floor-outdated.js | 6 +++- .../outdated/app/utils/reexports-outdated.js | 1 + tests/dummy/lib/outdated/package.json | 2 +- tests/unit/routes/application-test.js | 18 +++++++----- 10 files changed, 34 insertions(+), 31 deletions(-) create mode 100644 tests/dummy/lib/modern/app/utils/reexports-modern.js create mode 100644 tests/dummy/lib/outdated/app/utils/reexports-outdated.js diff --git a/tests/dummy/app/routes/application.js b/tests/dummy/app/routes/application.js index 19af810..8447fb2 100644 --- a/tests/dummy/app/routes/application.js +++ b/tests/dummy/app/routes/application.js @@ -1,36 +1,29 @@ import Ember from 'ember'; -// Should be version 1970.0.0 +// Should be version 2030.0.0 import flooring from 'npm:flooring'; -// Should be 1970.0.0, which the host app includes +// Should be 2030.0.0, which the host app includes import modernApp from '../utils/floor-modern'; import outdatedApp from '../utils/floor-outdated'; // Should be version 1970.0.0 import outdated from 'outdated/utils/floor-type'; +import outdatedReexports from '../utils/reexports-outdated'; // Should be version 2010.0.0 import modern from 'modern/utils/floor-type'; +import modernReexports from '../utils/reexports-modern'; export default Ember.Route.extend({ - model() { - return flooring(); - }, - - modern() { - return modern(); - }, + flooring, - modernApp() { - return modernApp(); - }, + modernApp, + outdatedApp, - outdated() { - return outdated(); - }, + outdated, + outdatedReexports, - outdatedApp() { - return outdatedApp(); - } + modern, + modernReexports }); diff --git a/tests/dummy/lib/flooring/index.js b/tests/dummy/lib/flooring/index.js index 38e71c8..e5de798 100644 --- a/tests/dummy/lib/flooring/index.js +++ b/tests/dummy/lib/flooring/index.js @@ -1 +1 @@ -module.exports = function() { return 'something modern very modern'; }; +module.exports = function() { return 'space cloud'; }; diff --git a/tests/dummy/lib/flooring/package.json b/tests/dummy/lib/flooring/package.json index b3cb42d..6b9fd63 100644 --- a/tests/dummy/lib/flooring/package.json +++ b/tests/dummy/lib/flooring/package.json @@ -1,5 +1,5 @@ { "name": "flooring", - "version": "2016.0.0", + "version": "2030.0.0", "main": "index.js" } diff --git a/tests/dummy/lib/modern/app/utils/reexports-modern.js b/tests/dummy/lib/modern/app/utils/reexports-modern.js new file mode 100644 index 0000000..29e3011 --- /dev/null +++ b/tests/dummy/lib/modern/app/utils/reexports-modern.js @@ -0,0 +1 @@ +export { default } from 'modern/utils/floor-type'; diff --git a/tests/dummy/lib/modern/node_modules/flooring/index.js b/tests/dummy/lib/modern/node_modules/flooring/index.js index d1c9bf6..af9b26e 100644 --- a/tests/dummy/lib/modern/node_modules/flooring/index.js +++ b/tests/dummy/lib/modern/node_modules/flooring/index.js @@ -1 +1 @@ -module.exports = function() { return 'something more or less modern'; }; +module.exports = function() { return 'hardwood'; }; diff --git a/tests/dummy/lib/modern/package.json b/tests/dummy/lib/modern/package.json index f9ae94c..0348c1d 100644 --- a/tests/dummy/lib/modern/package.json +++ b/tests/dummy/lib/modern/package.json @@ -5,7 +5,7 @@ "ember-addon" ], "dependencies": { - "flooring": "2010", + "flooring": "2010.0.0", "ember-browserify": "*" } } diff --git a/tests/dummy/lib/outdated/app/utils/floor-outdated.js b/tests/dummy/lib/outdated/app/utils/floor-outdated.js index aa73913..5327a34 100644 --- a/tests/dummy/lib/outdated/app/utils/floor-outdated.js +++ b/tests/dummy/lib/outdated/app/utils/floor-outdated.js @@ -1 +1,5 @@ -export { default } from 'outdated/utils/floor-type'; +import flooring from 'npm:flooring'; + +export default function() { + return flooring(); +} diff --git a/tests/dummy/lib/outdated/app/utils/reexports-outdated.js b/tests/dummy/lib/outdated/app/utils/reexports-outdated.js new file mode 100644 index 0000000..aa73913 --- /dev/null +++ b/tests/dummy/lib/outdated/app/utils/reexports-outdated.js @@ -0,0 +1 @@ +export { default } from 'outdated/utils/floor-type'; diff --git a/tests/dummy/lib/outdated/package.json b/tests/dummy/lib/outdated/package.json index 5e0e678..a2839d1 100644 --- a/tests/dummy/lib/outdated/package.json +++ b/tests/dummy/lib/outdated/package.json @@ -5,7 +5,7 @@ "ember-addon" ], "dependencies": { - "flooring": "1970", + "flooring": "1970.0.0", "ember-browserify": "*" } } diff --git a/tests/unit/routes/application-test.js b/tests/unit/routes/application-test.js index 653ad30..863b98d 100644 --- a/tests/unit/routes/application-test.js +++ b/tests/unit/routes/application-test.js @@ -8,15 +8,19 @@ moduleFor('route:application', 'Unit | Route | application', { test('it properly resolves npm modules', function(assert) { let route = this.subject(); - // Host application which depends on flooring@1970 + // Host application which depends on flooring@2030.0.0 // Set by virtue of folder structure. - assert.equal(route.model(), 'shag carpet'); - assert.equal(route.modernApp(), 'shag carpet'); - assert.equal(route.outdatedApp(), 'shag carpet'); + assert.equal(route.flooring(), 'space cloud'); - // Addon which depends on flooring@2010 - assert.equal(route.modern(), 'hardwood'); + // Moved into the app folder via the addons. + assert.equal(route.modernApp(), 'space cloud'); + assert.equal(route.outdatedApp(), 'space cloud'); - // Addon which depends on flooring@1970 + // Addon which depends on flooring@1970.0.0 assert.equal(route.outdated(), 'shag carpet'); + assert.equal(route.outdatedReexports(), 'shag carpet'); + + // Addon which depends on flooring@2010.0.0 + assert.equal(route.modern(), 'hardwood'); + assert.equal(route.modernReexports(), 'hardwood'); }); From 59004b2d38e1a461019cda8ecf75417b6aed086a Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Fri, 16 Sep 2016 15:37:18 -0700 Subject: [PATCH 37/46] Properly set on prepublish. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5d3e8b0..5997e16 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test": "npm run node-test && ember try:each", "node-test": "mocha node-tests --inline-diffs", "node-test:debug": "mocha debug node-tests --inline-diffs", - "prepublish": "./bin/install-ember-addons.sh" + "prepublish": "./bin/install-ember-addons.js" }, "repository": "https://github.com/ef4/ember-browserify", "engines": { From 69cc443022e7875daed57671363a3faf24e73924 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Sat, 17 Sep 2016 22:48:20 -0700 Subject: [PATCH 38/46] Revert "add a very simple/basic scenario (that works)" Exists in tests/dummy/app/routes/application.js This reverts commit d25ff3666102cd4fb143a16c797655f6aaac6862. --- tests/dummy/app/app.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/dummy/app/app.js b/tests/dummy/app/app.js index 3386bf7..831ad61 100644 --- a/tests/dummy/app/app.js +++ b/tests/dummy/app/app.js @@ -2,7 +2,7 @@ import Ember from 'ember'; import Resolver from './resolver'; import loadInitializers from 'ember-load-initializers'; import config from './config/environment'; -import acorn from 'npm:acorn'; + let App; Ember.MODEL_FACTORY_INJECTIONS = true; @@ -10,8 +10,7 @@ Ember.MODEL_FACTORY_INJECTIONS = true; App = Ember.Application.extend({ modulePrefix: config.modulePrefix, podModulePrefix: config.podModulePrefix, - Resolver, - acorn // just add this here, so hinting says happy + Resolver }); loadInitializers(App, config.modulePrefix); From 772c859af949a55d67a466d6a77a614743f016b4 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Sat, 17 Sep 2016 23:48:42 -0700 Subject: [PATCH 39/46] Structure for doing the right thing in the vendor hook. --- lib/index.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/index.js b/lib/index.js index 8f99503..dd716c8 100644 --- a/lib/index.js +++ b/lib/index.js @@ -29,7 +29,6 @@ module.exports = { if (emberCliVersion.satisfies('< 2.0.0')) { throw new TypeError('ember-browserify@^2.0.0 no longer supports ember-cli versions less then 2.0.0.'); } - this.that = app; app = findHost(this); @@ -58,8 +57,22 @@ module.exports = { } }, + treeForVendor: function(tree) { + tree = this._super.included(...arguments); + + var isRootChild = !this.parent.parent; + var isHostChild = findHost(this) === this.parent || isRootChild; + + if (isHostChild) { + if (isRootChild) { + } + } else { + } + + return tree; + }, + postprocessTree: function(type, tree) { - console.log('OMG', type, this.name, this.app.name, this.that.name); var outputFile, options; if (type === 'js'){ From 0ef7aa4aec64f52f0094ed8fcdd2e3d3704ed7f4 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Mon, 19 Sep 2016 10:43:09 -0700 Subject: [PATCH 40/46] Partial rewrite of preprocessor approach. --- lib/index.js | 83 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/lib/index.js b/lib/index.js index dd716c8..5a12579 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,6 +1,7 @@ 'use strict'; // Support old versions of Ember CLI. +// Nearest thing which provides `.import`` function findHost(current) { var app; @@ -15,12 +16,51 @@ function findHost(current) { return app; } +// The root host. +function findRoot(current) { + var app; + + // Keep iterating upward until we don't have a grandparent. + // Has to do this grandparent check because at some point we hit the project. + // Stop at lazy engine boundaries. + do { + app = current.app || app; + } while (current.parent && current.parent.parent && (current = current.parent)); + + return app; +} + +// The thing which browserify should run on. +function findTarget(current) { + // If we are the project, or the project's child. + if (!current.parent || !current.parent.parent) { + return current.app; + } else { + return current.parent; + } +} + var Funnel = require('broccoli-funnel'); +function getPreprocessor(instance) { + return { + name: 'ember-browserify', + ext: 'js', + toTree: function(tree) { console.log('thingamabob'); return tree; } + }; +} + module.exports = { name: 'ember-browserify', - included: function(app) { + included: function() { + var host = findHost(this); + var root = findRoot(this); + var target = findTarget(this); + var project = root.project; + + target.registry.add('js', getPreprocessor(this), ['js']); + var VersionChecker = require('ember-cli-version-checker'); var checker = new VersionChecker(this); @@ -30,49 +70,32 @@ module.exports = { throw new TypeError('ember-browserify@^2.0.0 no longer supports ember-cli versions less then 2.0.0.'); } - app = findHost(this); - - var enableSourcemaps = app.options.sourcemaps && app.options.sourcemaps.enabled && app.options.sourcemaps.extensions.indexOf('js') > -1; - - this.app = app; + var enableSourcemaps = root.options.sourcemaps && root.options.sourcemaps.enabled && root.options.sourcemaps.extensions.indexOf('js') > -1; this.options = { - root: this.app.project.root, - browserifyOptions: app.project.config(app.env).browserify || {}, + root: project.root, + browserifyOptions: project.config(root.env).browserify || {}, enableSourcemap: enableSourcemaps, - fullPaths: app.env !== 'production' + fullPaths: root.env !== 'production' }; - app.import('browserify/browserify.js'); - if (app.tests && (process.env.BROWSERIFY_TESTS || this.options.browserifyOptions.tests)) { - app.import('browserify-tests/browserify.js', { + host.import('browserify/browserify.js'); + if (host.tests && (process.env.BROWSERIFY_TESTS || this.options.browserifyOptions.tests)) { + host.import('browserify-tests/browserify.js', { type: 'test' }); } - if (app.importWhitelistFilters) { - app.importWhitelistFilters.push(function(moduleName) { + if (host.importWhitelistFilters) { + host.importWhitelistFilters.push(function(moduleName) { return moduleName.slice(0,4) === 'npm:'; }); } }, - treeForVendor: function(tree) { - tree = this._super.included(...arguments); - - var isRootChild = !this.parent.parent; - var isHostChild = findHost(this) === this.parent || isRootChild; - - if (isHostChild) { - if (isRootChild) { - } - } else { - } - - return tree; - }, - postprocessTree: function(type, tree) { + var root = findRoot(this); + var outputFile, options; if (type === 'js'){ @@ -88,7 +111,7 @@ module.exports = { options = Object.create(this.options); options.outputFile = outputFile; - options.basedir = this.app.root; + options.basedir = root.root; // produces: // - browserify_stubs.js (for CachingBrowserify, to build a bundle); From b6f11dc6181abbbb9c1ce7166b5e4e9db45c3c58 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Mon, 19 Sep 2016 11:25:07 -0700 Subject: [PATCH 41/46] Move away from postprocessTree. --- lib/imports-for.js | 49 ++++++++++++++++++++++++-- lib/index.js | 82 +++++++++++++++++++++---------------------- lib/stub-generator.js | 3 +- package.json | 2 +- 4 files changed, 91 insertions(+), 45 deletions(-) diff --git a/lib/imports-for.js b/lib/imports-for.js index 3b1bec5..5f1699b 100644 --- a/lib/imports-for.js +++ b/lib/imports-for.js @@ -3,9 +3,20 @@ var acorn = require('acorn'); module.exports = importsFor; + function importsFor(src, fullPath) { - var result = parse(src); + // In host applications the source is already ES5 code. + // In addons the source is ES6 code. + + // First, try to parse as es5 code. Es6 code will return an error. + var result = tryCatch(parseEs5, src); + + // If a syntax error is thrown, we assume this is because src is es6 code. + if (result instanceof Error) { + result = tryCatch(parseEs6, src); + } + // If result is still an error, there must have been a parse error. if (result instanceof Error) { throw new Error('Error parsing code while looking for "npm:" imports: ' + result.stack || result + ' in file: ' + fullPath); } @@ -28,7 +39,7 @@ function head(array) { return array[0]; } -function parse(src) { +function parseEs5(src) { var imports = {}; var ast = acorn.parse(src, { locations: true }); @@ -44,5 +55,39 @@ function parse(src) { }); } }); + return imports; } + +function parseEs6(src) { + var imports = {}; + + var ast = acorn.parse(src, { + ecmaVersion: 6, + sourceType: 'module', + locations: true + }); + + forEachNode(ast, function(entry) { + if (entry.type === 'ImportDeclaration') { + var source = entry.source.value; + if (source.slice(0,4) === 'npm:') { + if (entry.kind === 'named') { + throw new Error("ember-browserify doesn't support named imports (you tried to import " + entry.specifiers[0].id.name + " from " + source); + } + imports[source.slice(4)] = entry.source.loc; + } + } + }); + + return imports; +} + +function tryCatch(func, arg) { + try { + return func.call(null, arg); + } + catch(e) { + return e; + } +} diff --git a/lib/index.js b/lib/index.js index 5a12579..f1ea57c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -46,7 +46,47 @@ function getPreprocessor(instance) { return { name: 'ember-browserify', ext: 'js', - toTree: function(tree) { console.log('thingamabob'); return tree; } + toTree: function(tree) { + var type = 'js'; + var root = findRoot(instance); + + var outputFile, options; + + // TODO: Sort out tests. + if (type === 'js'){ + outputFile = 'browserify/browserify.js'; + } else if (type === 'test'){ + outputFile = 'browserify-tests/browserify.js'; + } + + if (outputFile) { + var StubGenerator = require('./stub-generator'); + var CachingBrowserify = require('./caching-browserify'); + var MergeTrees = require('broccoli-merge-trees'); + + options = Object.create(instance.options); + options.outputFile = outputFile; + options.basedir = root.root; + + // produces: + // - browserify_stubs.js (for CachingBrowserify, to build a bundle); + // - any inputFiles that had npm imports + var stubs = new StubGenerator(tree, options); + + tree = new MergeTrees([ + // original files + tree, + + // copies rewritten inputFiles over (overwriting original files) + new Funnel(stubs, { exclude: ['browserify_stubs.js'] }), + + // produces browserify bundle, named options.outputFile (defaulting to browserify/browserify.js) + new CachingBrowserify(stubs, options) + ], { overwrite: true }); + } + + return tree; + } }; } @@ -91,45 +131,5 @@ module.exports = { return moduleName.slice(0,4) === 'npm:'; }); } - }, - - postprocessTree: function(type, tree) { - var root = findRoot(this); - - var outputFile, options; - - if (type === 'js'){ - outputFile = 'browserify/browserify.js'; - } else if (type === 'test'){ - outputFile = 'browserify-tests/browserify.js'; - } - - if (outputFile) { - var StubGenerator = require('./stub-generator'); - var CachingBrowserify = require('./caching-browserify'); - var MergeTrees = require('broccoli-merge-trees'); - - options = Object.create(this.options); - options.outputFile = outputFile; - options.basedir = root.root; - - // produces: - // - browserify_stubs.js (for CachingBrowserify, to build a bundle); - // - any inputFiles that had npm imports - var stubs = new StubGenerator(tree, options); - - tree = new MergeTrees([ - // original files - tree, - - // copies rewritten inputFiles over (overwriting original files) - new Funnel(stubs, { exclude: ['browserify_stubs.js'] }), - - // produces browserify bundle, named options.outputFile (defaulting to browserify/browserify.js) - new CachingBrowserify(stubs, options) - ], { overwrite: true }); - } - - return tree; } }; diff --git a/lib/stub-generator.js b/lib/stub-generator.js index 1144d49..553a5a5 100644 --- a/lib/stub-generator.js +++ b/lib/stub-generator.js @@ -75,9 +75,10 @@ StubGenerator.prototype.build = function() { if (!/\.js$/.test(path)) { break; } var content = fs.readFileSync(fullInputPath, 'UTF8'); - var imports = importsFor(content); + var imports = importsFor(content, fullInputPath); Object.keys(imports).forEach(function(name) { + // FIXME: This returns the wrong value for nested addons. imports[name].version = versionForModuleName(name, this.basedir); }, this); diff --git a/package.json b/package.json index 5997e16..6407338 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "symlink-or-copy": "^1.1.6" }, "dependencies": { - "acorn": "^2.6.4", + "acorn": "^4.0.0", "broccoli-caching-writer": "^3.0.3", "broccoli-funnel": "^1.0.6", "broccoli-kitchen-sink-helpers": "^0.3.1", From 80597f7b136afe955ce6935848b0b73bbc8919e2 Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Mon, 19 Sep 2016 12:49:48 -0700 Subject: [PATCH 42/46] Properly set basedir per target. --- lib/index.js | 3 ++- lib/stub-generator.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/index.js b/lib/index.js index f1ea57c..fe7a742 100644 --- a/lib/index.js +++ b/lib/index.js @@ -49,6 +49,7 @@ function getPreprocessor(instance) { toTree: function(tree) { var type = 'js'; var root = findRoot(instance); + var target = findTarget(instance); var outputFile, options; @@ -66,7 +67,7 @@ function getPreprocessor(instance) { options = Object.create(instance.options); options.outputFile = outputFile; - options.basedir = root.root; + options.basedir = target.root; // produces: // - browserify_stubs.js (for CachingBrowserify, to build a bundle); diff --git a/lib/stub-generator.js b/lib/stub-generator.js index 553a5a5..4f53fd0 100644 --- a/lib/stub-generator.js +++ b/lib/stub-generator.js @@ -78,7 +78,6 @@ StubGenerator.prototype.build = function() { var imports = importsFor(content, fullInputPath); Object.keys(imports).forEach(function(name) { - // FIXME: This returns the wrong value for nested addons. imports[name].version = versionForModuleName(name, this.basedir); }, this); From 03c9c9577e64742e9ffbbe9c22c13971f6e58a60 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Tue, 20 Sep 2016 08:41:08 -0700 Subject: [PATCH 43/46] add comments, making it easier to understand where stuff is actually coming from. --- tests/dummy/app/routes/application.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/dummy/app/routes/application.js b/tests/dummy/app/routes/application.js index 8447fb2..8a54b75 100644 --- a/tests/dummy/app/routes/application.js +++ b/tests/dummy/app/routes/application.js @@ -4,16 +4,16 @@ import Ember from 'ember'; import flooring from 'npm:flooring'; // Should be 2030.0.0, which the host app includes -import modernApp from '../utils/floor-modern'; -import outdatedApp from '../utils/floor-outdated'; +import modernApp from '../utils/floor-modern'; // source: tests/dummy/lib/modern/app/utils/floor-modern +import outdatedApp from '../utils/floor-outdated'; // source: tests/dummy/lib/outdated/app/utils/floor-outdated // Should be version 1970.0.0 import outdated from 'outdated/utils/floor-type'; -import outdatedReexports from '../utils/reexports-outdated'; +import outdatedReexports from '../utils/reexports-outdated'; // source: tests/dummy/lib/outdated/app/utils/reexports-outdated // Should be version 2010.0.0 import modern from 'modern/utils/floor-type'; -import modernReexports from '../utils/reexports-modern'; +import modernReexports from '../utils/reexports-modern'; // source: tests/dummy/lib/modern/app/utils/reexports-modern export default Ember.Route.extend({ flooring, From f5908b90548e9cc64208c6a37bcd22a773d942f6 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Tue, 20 Sep 2016 08:45:45 -0700 Subject: [PATCH 44/46] only rewrite if rewriting is required --- lib/stub-generator.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/stub-generator.js b/lib/stub-generator.js index 4f53fd0..3c062cc 100644 --- a/lib/stub-generator.js +++ b/lib/stub-generator.js @@ -76,13 +76,18 @@ StubGenerator.prototype.build = function() { var content = fs.readFileSync(fullInputPath, 'UTF8'); var imports = importsFor(content, fullInputPath); + var needsImportsReWritten = false; Object.keys(imports).forEach(function(name) { + needsImportsReWritten = true; imports[name].version = versionForModuleName(name, this.basedir); }, this); - // TODO: only add files that required rewriting - fs.writeFileSync(fullOutputPath, rewriteImports(content, imports)); + if (needsImportsReWritten) { + fs.writeFileSync(fullOutputPath, rewriteImports(content, imports)); + } else { + fs.writeFileSync(fullOutputPath, content); + } this.stubs.set(fullInputPath, imports); From a70c0060f37922e5ae8c767d548063666a5f7486 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Tue, 20 Sep 2016 11:04:21 -0700 Subject: [PATCH 45/46] remove optimization for now. Bring back with tests. --- lib/stub-generator.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/stub-generator.js b/lib/stub-generator.js index 3c062cc..6f8fba2 100644 --- a/lib/stub-generator.js +++ b/lib/stub-generator.js @@ -79,20 +79,15 @@ StubGenerator.prototype.build = function() { var needsImportsReWritten = false; Object.keys(imports).forEach(function(name) { - needsImportsReWritten = true; imports[name].version = versionForModuleName(name, this.basedir); }, this); - if (needsImportsReWritten) { - fs.writeFileSync(fullOutputPath, rewriteImports(content, imports)); - } else { - fs.writeFileSync(fullOutputPath, content); - } - + fs.writeFileSync(fullOutputPath, rewriteImports(content, imports)); this.stubs.set(fullInputPath, imports); break; } + }, this); debug('patched applied in: %dms', Date.now() - applyPatch); From e3141193f97b36a87547a86546ec38d33decd5fc Mon Sep 17 00:00:00 2001 From: Nathan Hammond Date: Thu, 22 Sep 2016 08:59:47 -0700 Subject: [PATCH 46/46] Use the proper hook for setting up the registry. --- lib/index.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/index.js b/lib/index.js index fe7a742..0aea83a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -48,7 +48,6 @@ function getPreprocessor(instance) { ext: 'js', toTree: function(tree) { var type = 'js'; - var root = findRoot(instance); var target = findTarget(instance); var outputFile, options; @@ -94,14 +93,11 @@ function getPreprocessor(instance) { module.exports = { name: 'ember-browserify', - included: function() { + included: function(target) { var host = findHost(this); var root = findRoot(this); - var target = findTarget(this); var project = root.project; - target.registry.add('js', getPreprocessor(this), ['js']); - var VersionChecker = require('ember-cli-version-checker'); var checker = new VersionChecker(this); @@ -132,5 +128,11 @@ module.exports = { return moduleName.slice(0,4) === 'npm:'; }); } + }, + + setupPreprocessorRegistry: function(type, registry) { + if (type === 'self') { return; } + + registry.add('js', getPreprocessor(this), ['js']); } };