From f51bf21ae999bea885daa808fc5f204c3002b992 Mon Sep 17 00:00:00 2001 From: Chris Garrett Date: Fri, 12 Jul 2019 16:56:28 -0700 Subject: [PATCH 1/2] [BUGFIX lts] Compile Ember dynamically in consuming applications This PR sets up Ember to do a two phase build: * **Phase 1, prepublish:** Run Typescript and Rollup on the main Ember packages, and strip out canary-features. Publish these packages, along with the dependencies for Ember, in the `dist/` folder. * **Phase 2, in addon:** Run Babel transpilation using the consumer's `ember-cli-babel` and Babel configuration on the dist packages and dependencies, and bundle up the final `ember.js` file to serve to apps. This also includes `debug` flags and, in theory, svelting. Two major changes that will occur because of this: 1. We will no longer be distributing `ember.prod.js`, `ember.debug.js`, `ember.min.js`, or `ember-testing.js`. These files existing may be something that people rely on, and the packages that _are_ distributed aren't quite ready to build in a "normal" way, using webpack or another bundler. 2. We will no longer be _building_ `ember.prod.js`, `ember.min.js`, or `ember.debug.js` at all, only a single `ember.js` file. We no longer need separate builds, because the environment settings of the build will handle the differences for us. We _are_ continuing to distribute a pre-built version of the `ember.js` and `ember-testing.js` files. These are used only in the case where the build targets match the default development build targets for Ember apps, providing a small optimization for users' dev workflow. Unfortunately, until we disentangle `ember-cli` from the implementation details of `ember-source` we cannot convert Ember to _build_ like a normal addon locally. Using the `EmberAddon` class blows up in many small ways. --- .travis.yml | 30 +- CONTRIBUTING.md | 4 +- bin/run-tests.js | 33 +- broccoli/bootstrap-modules.js | 37 -- broccoli/canary-features.js | 33 ++ broccoli/concat-bundle.js | 32 -- broccoli/debug-macros.js | 35 +- broccoli/packages.js | 71 +-- broccoli/rollup-package.js | 46 ++ broccoli/strip-for-prod.js | 11 - broccoli/to-es5.js | 3 + broccoli/to-named-amd.js | 7 - broccoli/transforms/transform-define.js | 29 -- ember-cli-build.js | 410 ++++++------------ lib/build-debug-macro-plugin.js | 16 + lib/build-strip-class-callcheck-plugin.js | 6 + lib/concat-bundle.js | 19 + lib/index.js | 141 ++++-- lib/run-in-sequence.js | 13 - package.json | 30 +- .../glimmer/lib/protocol-for-url.ts | 4 +- packages/@ember/-internals/views/index.js | 2 +- .../views/lib/mixins/view_support.js | 2 +- .../views/lib/system/event_dispatcher.js | 2 +- .../-internals/views/lib/system/jquery.js | 5 +- packages/loader/lib/index.js | 22 +- testem.browserstack.js | 2 +- tests/index.html | 47 +- tests/node/helpers/setup-app.js | 2 +- tests/node/helpers/setup-component.js | 2 +- tests/node/instrumentation-test.js | 2 +- tests/node/sourcemap-test.js | 16 +- tests/node/template-compiler-test.js | 82 ++-- yarn.lock | 12 +- 34 files changed, 528 insertions(+), 680 deletions(-) delete mode 100644 broccoli/bootstrap-modules.js create mode 100644 broccoli/canary-features.js delete mode 100644 broccoli/concat-bundle.js create mode 100644 broccoli/rollup-package.js delete mode 100644 broccoli/strip-for-prod.js delete mode 100644 broccoli/transforms/transform-define.js create mode 100644 lib/build-debug-macro-plugin.js create mode 100644 lib/build-strip-class-callcheck-plugin.js create mode 100644 lib/concat-bundle.js delete mode 100644 lib/run-in-sequence.js diff --git a/.travis.yml b/.travis.yml index 155958ceaa0..712cc6b2a3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -60,26 +60,42 @@ install: jobs: include: - stage: basic test - env: TEST_SUITE=each-package-tests + env: TEST_SUITE=each-package + script: + - yarn ember build + - yarn test - name: Linting script: - yarn lint - - stage: additional tests + - stage: Additional Tests name: Browserstack Tests (Safari, Edge, IE11) + env: SHOULD_TRANSPILE=true script: - - yarn ember build -prod + - yarn ember build - yarn test:browserstack - - env: - - TEST_SUITE=built-tests - - EMBER_ENV=production + - name: Development (All Tests + Canary Features) + script: + - yarn ember build + - yarn test - - env: TEST_SUITE=old-jquery-and-extend-prototypes + - name: Production (All Tests + Canary Features) + env: SHOULD_TRANSPILE=true + script: + - yarn ember build -prod + - yarn test + + - name: Old Jquery and Extend Prototypes + env: TEST_SUITE=old-jquery-and-extend-prototypes + script: + - yarn ember build + - yarn test - name: Node.js Tests node_js: "8" + env: SHOULD_TRANSPILE=true script: - yarn ember build -prod - yarn test:node diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c7e854fb8a3..9861c85cac1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -259,7 +259,7 @@ When you submit your PR (or later change that code), a Travis build will automat Within the Travis build, you can see that we (currently) run six different test suites. -* The `each-package-tests` test suite is closest to what you normally run locally on your machine. +* The `each-package` test suite is closest to what you normally run locally on your machine. * The `build-tests EMBER_ENV=production...` test suite runs tests against a production build. * The `browserstack` test suite runs tests against various supported browsers. @@ -267,7 +267,7 @@ Within the Travis build, you can see that we (currently) run six different test ### Production Build Failures -If your build is failing on the 'production' suite, you may be relying on a debug-only function that does not even exist in a production build (`Ember.warn`, `Ember.deprecate`, `Ember.assert`, etc.). These will pass on the 'each-package-tests' suite (and locally) because those functions are present in development builds. +If your build is failing on the 'production' suite, you may be relying on a debug-only function that does not even exist in a production build (`Ember.warn`, `Ember.deprecate`, `Ember.assert`, etc.). These will pass on the 'each-package' suite (and locally) because those functions are present in development builds. There are helpers for many of these functions, which will resolve this for you: `expectDeprecation`, `expectAssertion`, etc. Please use these helpers when dealing with these functions. diff --git a/bin/run-tests.js b/bin/run-tests.js index b3114feee35..2e78726e0be 100755 --- a/bin/run-tests.js +++ b/bin/run-tests.js @@ -2,7 +2,7 @@ 'use strict'; const chalk = require('chalk'); -const runInSequence = require('../lib/run-in-sequence'); +const RSVP = require('rsvp'); const path = require('path'); const finalhandler = require('finalhandler'); @@ -79,15 +79,9 @@ function generateEachPackageTests() { .forEach(generateTestsFor); } -function generateBuiltTests() { +function generateStandardTests() { testFunctions.push(() => run('')); - testFunctions.push(() => run('dist=min&prod=true')); - testFunctions.push(() => run('dist=prod&prod=true')); - testFunctions.push(() => run('enableoptionalfeatures=true&dist=prod&prod=true')); - testFunctions.push(() => run('legacy=true')); - testFunctions.push(() => run('legacy=true&dist=min&prod=true')); - testFunctions.push(() => run('legacy=true&dist=prod&prod=true')); - testFunctions.push(() => run('legacy=true&enableoptionalfeatures=true&dist=prod&prod=true')); + testFunctions.push(() => run('enableoptionalfeatures=true')); } function generateOldJQueryTests() { @@ -101,6 +95,18 @@ function generateExtendPrototypeTests() { testFunctions.push(() => run('extendprototypes=true&enableoptionalfeatures=true')); } +function runInSequence(tasks) { + var length = tasks.length; + var current = RSVP.Promise.resolve(); + var results = new Array(length); + + for (var i = 0; i < length; ++i) { + current = results[i] = current.then(tasks[i]); + } + + return RSVP.Promise.all(results); +} + function runAndExit() { runInSequence(testFunctions) .then(function() { @@ -121,9 +127,9 @@ switch (process.env.TEST_SUITE) { generateTestsFor(p); runAndExit(); break; - case 'built-tests': - console.log('suite: built-tests'); - generateBuiltTests(); + case 'each-package': + console.log('suite: optional-features'); + generateEachPackageTests(); runAndExit(); break; case 'old-jquery-and-extend-prototypes': @@ -134,7 +140,6 @@ switch (process.env.TEST_SUITE) { break; case 'all': console.log('suite: all'); - generateBuiltTests(); generateOldJQueryTests(); generateExtendPrototypeTests(); generateEachPackageTests(); @@ -142,6 +147,6 @@ switch (process.env.TEST_SUITE) { break; default: console.log('suite: default (generate each package)'); - generateEachPackageTests(); + generateStandardTests(); runAndExit(); } diff --git a/broccoli/bootstrap-modules.js b/broccoli/bootstrap-modules.js deleted file mode 100644 index 5baee1e18cd..00000000000 --- a/broccoli/bootstrap-modules.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; - -const WriteFile = require('broccoli-file-creator'); -const { stripIndent } = require('common-tags'); - -function sideeffects(moduleExport) { - return `requireModule('${moduleExport}')`; -} - -function umd(moduleExport) { - return `(function (m) { if (typeof module === "object" && module.exports) { module.exports = m } }(requireModule('${moduleExport}')));\n`; -} - -function testing() { - return stripIndent` - var testing = requireModule('ember-testing'); - Ember.Test = testing.Test; - Ember.Test.Adapter = testing.Adapter; - Ember.Test.QUnitAdapter = testing.QUnitAdapter; - Ember.setupForTesting = testing.setupForTesting; - `; -} - -function empty() { - return ''; -} - -module.exports = function bootstrapModule(type, moduleExport) { - let moduleType = { - empty, - sideeffects, - testing, - umd, - }; - - return new WriteFile('bootstrap', moduleType[type](moduleExport)); -}; diff --git a/broccoli/canary-features.js b/broccoli/canary-features.js new file mode 100644 index 00000000000..3f58bef6de8 --- /dev/null +++ b/broccoli/canary-features.js @@ -0,0 +1,33 @@ +'use strict'; + +const Babel = require('broccoli-babel-transpiler'); +const FEATURES = require('./features'); + +module.exports = function canaryFeatures(tree) { + let plugins = [ + [ + 'debug-macros', + { + flags: [ + { + source: '@ember/canary-features', + flags: Object.assign( + // explicit list of additional exports within @ember/canary-features + // without adding this (with a null value) an error is thrown during + // the feature replacement process (e.g. XYZ is not a supported flag) + { + FEATURES: null, + DEFAULT_FEATURES: null, + isEnabled: null, + }, + FEATURES + ), + }, + ], + }, + 'debug-macros:canary-flags', + ], + ]; + + return new Babel(tree, { plugins }); +}; diff --git a/broccoli/concat-bundle.js b/broccoli/concat-bundle.js deleted file mode 100644 index 688719b1509..00000000000 --- a/broccoli/concat-bundle.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -const concat = require('broccoli-concat'); - -module.exports = function(tree, options) { - let { outputFile, hasBootstrap, footer } = options; - - if (typeof hasBootstrap !== 'boolean') { - hasBootstrap = true; - } - - let footerFiles = []; - - if (hasBootstrap) { - footerFiles = ['bootstrap']; - } - - if (!footer) { - footer = ''; - } - - return concat(tree, { - header: '(function() {', - outputFile: outputFile, - headerFiles: ['license.js', 'loader.js'], - sourceMapConfig: { enabled: true }, - footerFiles: footerFiles, - inputFiles: ['**/*.js'], - annotation: outputFile, - footer: footer + '\n}());', - }); -}; diff --git a/broccoli/debug-macros.js b/broccoli/debug-macros.js index 6b250d26cdd..8c8cc9cc4e4 100644 --- a/broccoli/debug-macros.js +++ b/broccoli/debug-macros.js @@ -1,43 +1,12 @@ 'use strict'; const Babel = require('broccoli-babel-transpiler'); -const FEATURES = require('./features'); +const buildDebugMacroPlugin = require('../lib/build-debug-macro-plugin'); module.exports = function debugMacros(tree, environment) { let isDebug = environment !== 'production'; - let plugins = [ - [ - 'debug-macros', - { - debugTools: { - source: '@ember/debug', - assertPredicateIndex: 1, - isDebug, - }, - externalizeHelpers: { - module: true, - }, - flags: [ - { source: '@glimmer/env', flags: { DEBUG: isDebug } }, - { - source: '@ember/canary-features', - flags: Object.assign( - // explicit list of additional exports within @ember/canary-features - // without adding this (with a null value) an error is thrown during - // the feature replacement process (e.g. XYZ is not a supported flag) - { - FEATURES: null, - DEFAULT_FEATURES: null, - isEnabled: null, - }, - FEATURES - ), - }, - ], - }, - ], - ]; + let plugins = [buildDebugMacroPlugin(isDebug)]; return new Babel(tree, { plugins }); }; diff --git a/broccoli/packages.js b/broccoli/packages.js index b7534345d39..b6b36bada27 100644 --- a/broccoli/packages.js +++ b/broccoli/packages.js @@ -5,6 +5,7 @@ const path = require('path'); const Rollup = require('broccoli-rollup'); const Funnel = require('broccoli-funnel'); const MergeTrees = require('broccoli-merge-trees'); +const Babel = require('broccoli-babel-transpiler'); const typescript = require('broccoli-typescript-compiler').default; const BroccoliDebug = require('broccoli-debug'); const findLib = require('./find-lib'); @@ -17,6 +18,8 @@ const StringReplace = require('broccoli-string-replace'); const GlimmerTemplatePrecompiler = require('./glimmer-template-compiler'); const VERSION_PLACEHOLDER = /VERSION_STRING_PLACEHOLDER/g; const transfromBabelPlugins = require('./transforms/transform-babel-plugins'); +const canaryFeatures = require('./canary-features'); +const injectNodeGlobals = require('./transforms/inject-node-globals'); const debugTree = BroccoliDebug.buildDebugCallback('ember-source'); @@ -34,14 +37,6 @@ module.exports.routerES = function _routerES() { }); }; -module.exports.jquery = function _jquery() { - return new Funnel(findLib('jquery'), { - files: ['jquery.js'], - destDir: 'jquery', - annotation: 'jquery', - }); -}; - module.exports.internalLoader = function _internalLoader() { return new Funnel('packages/loader/lib', { files: ['index.js'], @@ -112,7 +107,9 @@ module.exports.getPackagesES = function getPackagesES() { `get-packages-es:package-json` ); - mergedFinalOutput = new MergeTrees([mergedFinalOutput, packageJSON], { overwrite: true }); + mergedFinalOutput = canaryFeatures( + new MergeTrees([mergedFinalOutput, packageJSON], { overwrite: true }) + ); return debugTree(mergedFinalOutput, `get-packages-es:output`); }; @@ -216,11 +213,11 @@ module.exports.simpleHTMLTokenizerES = function _simpleHTMLTokenizerES() { }); }; -const glimmerTrees = new Map(); +const _glimmerTrees = new Map(); function rollupGlimmerPackage(pkg) { let name = pkg.name; - let tree = glimmerTrees.get(name); + let tree = _glimmerTrees.get(name); if (tree === undefined) { tree = new Rollup(pkg.module.dir, { rollup: { @@ -233,12 +230,12 @@ function rollupGlimmerPackage(pkg) { }, annotation: name, }); - glimmerTrees.set(name, tree); + _glimmerTrees.set(name, tree); } return tree; } -module.exports.glimmerTrees = function glimmerTrees(entries) { +function glimmerTrees(entries) { let seen = new Set(); // glimmer runtime has dependency on this even though it is only in tests @@ -269,7 +266,36 @@ module.exports.glimmerTrees = function glimmerTrees(entries) { queue.push(...dependencies); } } - return trees; + return new Babel(new MergeTrees(trees), { + sourceMaps: true, + plugins: [ + // ensures `@glimmer/compiler` requiring `crypto` works properly + // in both browser and node-land + injectNodeGlobals, + ], + }); +} + +module.exports.glimmerCompilerES = () => { + return glimmerTrees(['@glimmer/compiler']); +}; + +module.exports.glimmerES = function glimmerES(environment) { + let glimmerEntries = ['@glimmer/node', '@glimmer/opcode-compiler', '@glimmer/runtime']; + + if (environment === 'development') { + let hasGlimmerDebug = true; + try { + require.resolve('@glimmer/debug'); + } catch (e) { + hasGlimmerDebug = false; + } + if (hasGlimmerDebug) { + glimmerEntries.push('@glimmer/debug', '@glimmer/local-debug-flags'); + } + } + + return glimmerTrees(glimmerEntries); }; module.exports.emberVersionES = function _emberVersionES() { @@ -279,17 +305,6 @@ module.exports.emberVersionES = function _emberVersionES() { }); }; -module.exports.buildEmberEnvFlagsES = function(flags) { - let content = ''; - for (let key in flags) { - content += `\nexport const ${key} = ${flags[key]};`; - } - - return new WriteFile('@glimmer/env.js', content, { - annotation: '@glimmer/env', - }); -}; - module.exports.emberLicense = function _emberLicense() { let license = new Funnel('generators', { files: ['license.js'], @@ -307,9 +322,3 @@ module.exports.emberLicense = function _emberLicense() { annotation: 'license', }); }; - -module.exports.nodeTests = function _nodeTests() { - return new Funnel('tests', { - include: ['**/*/*.js'], - }); -}; diff --git a/broccoli/rollup-package.js b/broccoli/rollup-package.js new file mode 100644 index 00000000000..5daf409b926 --- /dev/null +++ b/broccoli/rollup-package.js @@ -0,0 +1,46 @@ +const Rollup = require('broccoli-rollup'); +const BroccoliDebug = require('broccoli-debug'); +const Funnel = require('broccoli-funnel'); +const path = require('path'); + +const debugTree = BroccoliDebug.buildDebugCallback('ember-source'); + +module.exports = function rollupPackage(packagesES, name) { + // this prevents broccoli-rollup from "seeing" changes in + // its input that are unrelated to what we are building + // and therefore noop on rebuilds... + let rollupRestrictedInput = new Funnel(packagesES, { + srcDir: name, + destDir: name, + }); + + rollupRestrictedInput = debugTree(rollupRestrictedInput, `rollup-package:${name}:input`); + + let output = new Rollup(rollupRestrictedInput, { + annotation: `rollup ${name}`, + rollup: { + input: `${name}/index.js`, + external(importee, importer) { + // importer of null/undefined means entry module + if (!importer) { + return false; + } + + // import is relative initially, then expanded to absolute + // when resolveId is called. this checks for either... + if (importee[0] === '.' || path.isAbsolute(importee)) { + return false; + } + + return true; + }, + output: { + file: `${name}/index.js`, + format: 'es', + exports: 'named', + }, + }, + }); + + return debugTree(output, `rollup-package:${name}:output`); +}; diff --git a/broccoli/strip-for-prod.js b/broccoli/strip-for-prod.js deleted file mode 100644 index 8e5f16214c2..00000000000 --- a/broccoli/strip-for-prod.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -const Babel = require('broccoli-babel-transpiler'); - -module.exports = function stripForProd(tree) { - let options = { - plugins: [['filter-imports', { imports: { 'ember-babel': ['_classCallCheck'] } }]], - }; - - return new Babel(tree, options); -}; diff --git a/broccoli/to-es5.js b/broccoli/to-es5.js index fcf9cc418f2..e853ed041da 100644 --- a/broccoli/to-es5.js +++ b/broccoli/to-es5.js @@ -2,6 +2,7 @@ const Babel = require('broccoli-babel-transpiler'); const injectBabelHelpers = require('./transforms/inject-babel-helpers'); +const buildStripClassCallcheckPlugin = require('../lib/build-strip-class-callcheck-plugin'); module.exports = function toES5(tree, _options) { let options = Object.assign({}, _options); @@ -9,6 +10,7 @@ module.exports = function toES5(tree, _options) { options.sourceMaps = true; options.plugins = [ injectBabelHelpers, + ['@babel/transform-template-literals', { loose: true }], ['@babel/transform-literals'], ['@babel/transform-arrow-functions'], ['@babel/transform-destructuring', { loose: true }], @@ -19,6 +21,7 @@ module.exports = function toES5(tree, _options) { ['@babel/transform-block-scoping', { throwIfClosureRequired: true }], ['@babel/transform-classes', { loose: true }], ['@babel/transform-object-assign'], + buildStripClassCallcheckPlugin(), ]; if (options.inlineHelpers) { diff --git a/broccoli/to-named-amd.js b/broccoli/to-named-amd.js index d8264b1aaff..d15a717d0fa 100644 --- a/broccoli/to-named-amd.js +++ b/broccoli/to-named-amd.js @@ -3,8 +3,6 @@ const { resolveRelativeModulePath, getRelativeModulePath, } = require('ember-cli-babel/lib/relative-module-paths'); -const enifed = require('./transforms/transform-define'); -const injectNodeGlobals = require('./transforms/inject-node-globals'); module.exports = function processModulesOnly(tree, strict = false) { let transformOptions = { noInterop: true }; @@ -20,13 +18,8 @@ module.exports = function processModulesOnly(tree, strict = false) { let options = { sourceMaps: true, plugins: [ - // ensures `@glimmer/compiler` requiring `crypto` works properly - // in both browser and node-land - injectNodeGlobals, - ['@babel/transform-template-literals', { loose: true }], ['module-resolver', { resolvePath: resolveRelativeModulePath }], ['@babel/transform-modules-amd', transformOptions], - enifed, ], moduleIds: true, getModuleId: getRelativeModulePath, diff --git a/broccoli/transforms/transform-define.js b/broccoli/transforms/transform-define.js deleted file mode 100644 index 166218837b0..00000000000 --- a/broccoli/transforms/transform-define.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -function transformDefine(babel) { - let { types: t } = babel; - return { - name: 'transform define', - visitor: { - Program: { - exit(path) { - let [expressionStatement] = path.node.body; - - if ( - t.isExpressionStatement(expressionStatement) && - t.isCallExpression(expressionStatement.expression) && - expressionStatement.expression.callee.name === 'define' - ) { - expressionStatement.expression.callee.name = 'enifed'; - } - }, - }, - }, - }; -} - -transformDefine.baseDir = function() { - return 'babel-plugin-transform-es2015-modules-amd'; -}; - -module.exports = transformDefine; diff --git a/ember-cli-build.js b/ember-cli-build.js index 29bbcb6996d..56812c7e1e8 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -1,25 +1,22 @@ 'use strict'; -const path = require('path'); +const EmberSourceAddon = require('./lib/index'); + const MergeTrees = require('broccoli-merge-trees'); const Funnel = require('broccoli-funnel'); -const Rollup = require('broccoli-rollup'); const babelHelpers = require('./broccoli/babel-helpers'); -const bootstrapModule = require('./broccoli/bootstrap-modules'); -const concatBundle = require('./broccoli/concat-bundle'); -const concat = require('broccoli-concat'); +const concatBundle = require('./lib/concat-bundle'); const testIndexHTML = require('./broccoli/test-index-html'); const testPolyfills = require('./broccoli/test-polyfills'); -const toES5 = require('./broccoli/to-es5'); const toNamedAMD = require('./broccoli/to-named-amd'); -const stripForProd = require('./broccoli/strip-for-prod'); +const rollupPackage = require('./broccoli/rollup-package'); +const toES5 = require('./broccoli/to-es5'); const debugMacros = require('./broccoli/debug-macros'); const minify = require('./broccoli/minify'); -const rename = require('./broccoli/rename'); const testBabelPluginsTransform = require('./broccoli/transforms/test-babel-plugins'); + const { routerES, - jquery, internalLoader, qunit, handlebarsES, @@ -28,39 +25,32 @@ const { backburnerES, dagES, routeRecognizerES, - glimmerTrees, + glimmerES, + glimmerCompilerES, emberVersionES, emberLicense, - nodeTests, - buildEmberEnvFlagsES, getPackagesES, } = require('./broccoli/packages'); -const BroccoliDebug = require('broccoli-debug'); -const ENV = process.env.EMBER_ENV || 'development'; -let debugTree = BroccoliDebug.buildDebugCallback('ember-source:ember-cli-build'); +const ENV = process.env.EMBER_ENV || 'development'; +const SHOULD_ROLLUP = process.env.SHOULD_ROLLUP !== 'false'; +const SHOULD_TRANSPILE = Boolean(process.env.SHOULD_TRANSPILE); +const SHOULD_MINIFY = Boolean(process.env.SHOULD_MINIFY); -module.exports = function() { - let loader = internalLoader(); +function transpileTree(tree, env, shouldTranspile = false) { + let transpiled = debugMacros(tree, env); - // generate "loose" ES modules... - let dependenciesES = new MergeTrees([ - backburnerES(), - rsvpES(), - dagES(), - routerES(), - routeRecognizerES(), + if (shouldTranspile || SHOULD_TRANSPILE) { + transpiled = toES5(transpiled); + } - ...glimmerDependenciesES(), - ]); + return toNamedAMD(transpiled); +} - let templateCompilerDependenciesES = new MergeTrees([ - simpleHTMLTokenizerES(), - handlebarsES(), - ...glimmerTrees(['@glimmer/compiler']), - ]); +EmberSourceAddon.transpileTree = tree => transpileTree(tree, ENV); - let packagesES = new MergeTrees([ +module.exports = function() { + let packages = new MergeTrees([ // dynamically generated packages emberVersionES(), @@ -71,283 +61,169 @@ module.exports = function() { babelHelpers(), ]); - let es = new MergeTrees([packagesES, dependenciesES, templateCompilerDependenciesES], { - overwrite: true, - }); - let pkgAndTestESInAMD = toNamedAMD(es); - let emberEnvFlagsDebug = toNamedAMD(buildEmberEnvFlagsES({ DEBUG: true })); - - let pkgAndTestESBundleDebug = concat( - new MergeTrees([pkgAndTestESInAMD, loader, emberEnvFlagsDebug]), - { - headerFiles: ['loader.js'], - inputFiles: ['**/*.js'], - outputFile: 'ember-all.debug.js', - } - ); - // Rollup - let packagesRollupES = new MergeTrees([ - new Funnel(packagesES, { + if (SHOULD_ROLLUP) { + packages = new MergeTrees([ + new Funnel(packages, { + exclude: [ + '@ember/-internals/browser-environment/index.js', + '@ember/-internals/browser-environment/lib/**', + '@ember/-internals/container/index.js', + '@ember/-internals/container/lib/**', + '@ember/-internals/environment/index.js', + '@ember/-internals/environment/lib/**', + '@ember/-internals/glimmer/index.js', + '@ember/-internals/glimmer/lib/**', + '@ember/-internals/metal/index.js', + '@ember/-internals/metal/lib/**', + '@ember/-internals/utils/index.js', + '@ember/-internals/utils/lib/**', + ], + }), + rollupPackage(packages, '@ember/-internals/browser-environment'), + rollupPackage(packages, '@ember/-internals/environment'), + rollupPackage(packages, '@ember/-internals/glimmer'), + rollupPackage(packages, '@ember/-internals/metal'), + rollupPackage(packages, '@ember/-internals/utils'), + rollupPackage(packages, '@ember/-internals/container'), + ]); + } + + let dist = new MergeTrees([ + new Funnel(packages, { + destDir: 'packages', exclude: [ - '@ember/-internals/browser-environment/index.js', - '@ember/-internals/browser-environment/lib/**', - '@ember/-internals/container/index.js', - '@ember/-internals/container/lib/**', - '@ember/-internals/environment/index.js', - '@ember/-internals/environment/lib/**', - '@ember/-internals/glimmer/index.js', - '@ember/-internals/glimmer/lib/**', - '@ember/-internals/metal/index.js', - '@ember/-internals/metal/lib/**', - '@ember/-internals/utils/index.js', - '@ember/-internals/utils/lib/**', + '**/package.json', + '@ember/-internals/*/tests/**' /* internal packages */, + '*/*/tests/**' /* scoped packages */, + '*/tests/**' /* packages */, + 'ember-template-compiler/**', + 'internal-test-helpers/**', ], }), - rollupPackage(packagesES, '@ember/-internals/browser-environment'), - rollupPackage(packagesES, '@ember/-internals/environment'), - rollupPackage(packagesES, '@ember/-internals/glimmer'), - rollupPackage(packagesES, '@ember/-internals/metal'), - rollupPackage(packagesES, '@ember/-internals/utils'), - rollupPackage(packagesES, '@ember/-internals/container'), + new Funnel(emberHeaderFiles(), { destDir: 'header' }), + new Funnel(emberDependencies(ENV), { destDir: 'dependencies' }), ]); - // Bundling - let bundleTrees = [ - buildBundles(packagesRollupES, dependenciesES, templateCompilerDependenciesES), - ]; - - if (ENV === 'production') { - let bundlesES5 = buildBundles( - toES5(packagesRollupES), - toES5(dependenciesES), - toES5(templateCompilerDependenciesES) - ); + let preBuilt = new Funnel(EmberSourceAddon.treeForVendor(dist), { + srcDir: 'ember', + }); - bundleTrees.push(new Funnel(bundlesES5, { destDir: 'legacy' })); + if (SHOULD_MINIFY) { + preBuilt = minify(preBuilt); } - let emberTestsEmptyTestem = new Funnel('tests', { - files: ['testem.js'], - destDir: '', - annotation: 'tests/testem.js', - }); - - return new MergeTrees([ - new Funnel(es, { destDir: 'es' }), - ...bundleTrees, - pkgAndTestESBundleDebug, - emberTestsEmptyTestem, - nodeTests(), + return new MergeTrees( + [ + // Distributed files + dist, + templateCompilerBundle(packages, ENV), - // test harness - testPolyfills(), - testIndexHTML(), - jquery(), - qunit(), - ]); -}; + // Test builds + preBuilt, -function buildBundles(packagesES, dependenciesES, templateCompilerDependenciesES) { - let packagesDevES = debugMacros(packagesES, 'development'); - let dependenciesDevES = debugMacros(dependenciesES, 'development'); - let templateCompilerDependenciesDevES = debugMacros( - templateCompilerDependenciesES, - 'development' + // Tests and test harness + testsBundle(packages, ENV), + testHarness(), + ], + { + overwrite: true, + } ); +}; - let emberDebugFiles = new MergeTrees([ - new Funnel(packagesDevES, { - exclude: [ - '@ember/-internals/*/tests/**' /* internal packages */, - '*/*/tests/**' /* scoped packages */, - '*/tests/**' /* packages */, - 'ember-template-compiler/**', - 'internal-test-helpers/**', - ], - }), - dependenciesDevES, - bootstrapModule('sideeffects', 'ember'), +function emberDependencies(environment) { + // generate "loose" ES modules... + return new MergeTrees([ + backburnerES(), + rsvpES(), + dagES(), + routerES(), + routeRecognizerES(), + glimmerES(environment), ]); +} + +function testsBundle(emberPackages, env) { + let exclude = env === 'production' ? ['@ember/debug/tests/**', 'ember-testing/tests/**'] : []; let emberTestsFiles = new MergeTrees([ - new Funnel(packagesDevES, { + new Funnel(emberPackages, { include: [ 'internal-test-helpers/**', '@ember/-internals/*/tests/**' /* internal packages */, '*/*/tests/**' /* scoped packages */, '*/tests/**' /* packages */, - 'license.js', - ], - }), - bootstrapModule('empty'), - ]); - - let emberTestingFiles = new MergeTrees([ - new Funnel(packagesDevES, { - include: [ - '@ember/debug/lib/**', - '@ember/debug/index.js', - 'ember-testing/index.js', - 'ember-testing/lib/**', - 'license.js', - ], - }), - bootstrapModule('testing'), - ]); - - let templateCompilerFiles = new MergeTrees([ - new Funnel(packagesDevES, { - include: [ - '@ember/-internals/utils.js', - '@ember/-internals/environment.js', - '@ember/-internals/browser-environment.js', - '@ember/canary-features/**', - '@ember/debug/index.js', - '@ember/debug/lib/**', - '@ember/deprecated-features/**', - '@ember/error/index.js', - '@ember/polyfills/index.js', - '@ember/polyfills/lib/**', - 'ember/version.js', - 'ember-babel.js', 'ember-template-compiler/**', - 'node-module/**', ], + exclude, }), - templateCompilerDependenciesDevES, - bootstrapModule('umd', 'ember-template-compiler'), ]); - let emberProdFiles, emberTestsProdFiles; + if (SHOULD_TRANSPILE || env === 'production') { + emberTestsFiles = testBabelPluginsTransform(emberTestsFiles); + } - if (ENV === 'production') { - let packagesProdES = stripForProd(debugMacros(packagesES, 'production')); - let dependenciesProdES = stripForProd(debugMacros(dependenciesES, 'production')); + return concatBundle(new MergeTrees([transpileTree(emberTestsFiles, env), emberHeaderFiles()]), { + outputFile: 'ember-tests.js', + headerFiles: ['license.js', 'loader.js'], + }); +} - emberProdFiles = new MergeTrees([ - new Funnel(packagesProdES, { +function templateCompilerBundle(emberPackages, env) { + let templateCompilerFiles = transpileTree( + new MergeTrees([ + new Funnel(emberPackages, { + include: [ + '@ember/-internals/utils/**', + '@ember/-internals/environment/**', + '@ember/-internals/browser-environment/**', + '@ember/canary-features/**', + '@ember/debug/**', + '@ember/deprecated-features/**', + '@ember/error/**', + '@ember/polyfills/**', + 'ember/version.js', + 'ember-babel.js', + 'ember-template-compiler/**', + 'node-module/**', + ], exclude: [ '@ember/-internals/*/tests/**' /* internal packages */, '*/*/tests/**' /* scoped packages */, '*/tests/**' /* packages */, - 'ember-template-compiler/**', - 'ember-testing/**', - 'internal-test-helpers/**', ], }), - dependenciesProdES, - bootstrapModule('sideeffects', 'ember'), - ]); - - emberTestsProdFiles = testBabelPluginsTransform( - MergeTrees([ - new Funnel(packagesProdES, { - include: [ - '@ember/-internals/*/tests/**' /* internal packages */, - 'internal-test-helpers/**', - '*/*/tests/**' /* scoped packages */, - '*/tests/**' /* packages */, - 'license.js', - ], - exclude: ['@ember/debug/tests/**', 'ember-testing/tests/**'], - }), - bootstrapModule('empty'), - ]) - ); - - // apply the babel transforms for legacy tests - emberTestsFiles = testBabelPluginsTransform(emberTestsFiles); - - // Note: - // We have to build custom production template compiler - // because we strip babel helpers in the prod build - templateCompilerFiles = stripForProd(templateCompilerFiles); - } - - // Files that are prebuilt and should not be AMD transformed - let vendor = [internalLoader(), emberLicense()]; - - let emberProdBundle = emberProdFiles && buildBundle('ember.prod.js', emberProdFiles, vendor); - let emberMinBundle = - emberProdBundle && minify(rename(emberProdBundle, { 'ember.prod.js': 'ember.min.js' })); - let emberProdTestsBundle = - emberTestsProdFiles && buildBundle('ember-tests.prod.js', emberTestsProdFiles, vendor); - - return new MergeTrees( - [ - emberProdBundle, - process.env.DISABLE_MINIFICATION !== '1' && emberMinBundle, - emberProdTestsBundle, - buildBundle('ember.debug.js', emberDebugFiles, vendor), - buildBundle('ember-tests.js', emberTestsFiles, vendor), - buildBundle('ember-testing.js', emberTestingFiles, vendor), - buildBundle('ember-template-compiler.js', templateCompilerFiles, vendor), - ].filter(Boolean) + templateCompilerDependencies(), + ]), + env, + true ); -} - -function buildBundle(name, tree, extras) { - let bundleWithExtras = new MergeTrees([toNamedAMD(tree, true), ...extras]); - return concatBundle(bundleWithExtras, { - outputFile: name, + return concatBundle(new MergeTrees([templateCompilerFiles, emberHeaderFiles()]), { + outputFile: 'ember-template-compiler.js', + headerFiles: ['license.js', 'loader.js'], + footer: + '(function (m) { if (typeof module === "object" && module.exports) { module.exports = m } }(require("ember-template-compiler")));', }); } -function glimmerDependenciesES() { - let glimmerEntries = ['@glimmer/node', '@glimmer/opcode-compiler', '@glimmer/runtime']; - - if (ENV === 'development') { - let hasGlimmerDebug = true; - try { - require.resolve('@glimmer/debug'); - } catch (e) { - hasGlimmerDebug = false; - } - if (hasGlimmerDebug) { - glimmerEntries.push('@glimmer/debug', '@glimmer/local-debug-flags'); - } - } - return glimmerTrees(glimmerEntries); +function testHarness() { + return new MergeTrees([emptyTestem(), testPolyfills(), testIndexHTML(), qunit()]); } -function rollupPackage(packagesES, name) { - // this prevents broccoli-rollup from "seeing" changes in - // its input that are unrelated to what we are building - // and therefore noop on rebuilds... - let rollupRestrictedInput = new Funnel(packagesES, { - srcDir: name, - destDir: name, +function emptyTestem() { + return new Funnel('tests', { + files: ['testem.js'], + destDir: '', + annotation: 'tests/testem.js', }); +} - rollupRestrictedInput = debugTree(rollupRestrictedInput, `rollup-package:${name}:input`); - - let output = new Rollup(rollupRestrictedInput, { - annotation: `rollup ${name}`, - rollup: { - input: `${name}/index.js`, - external(importee, importer) { - // importer of null/undefined means entry module - if (!importer) { - return false; - } - - // import is relative initially, then expanded to absolute - // when resolveId is called. this checks for either... - if (importee[0] === '.' || path.isAbsolute(importee)) { - return false; - } - - return true; - }, - output: { - file: `${name}.js`, - format: 'es', - exports: 'named', - }, - }, - }); +function templateCompilerDependencies() { + return new MergeTrees([simpleHTMLTokenizerES(), handlebarsES(), glimmerCompilerES()]); +} - return debugTree(output, `rollup-package:${name}:output`); +function emberHeaderFiles() { + return new MergeTrees([emberLicense(), internalLoader()]); } diff --git a/lib/build-debug-macro-plugin.js b/lib/build-debug-macro-plugin.js new file mode 100644 index 00000000000..0b7b9363ea2 --- /dev/null +++ b/lib/build-debug-macro-plugin.js @@ -0,0 +1,16 @@ +module.exports = function buildDebugMacrosPlugin(isDebug) { + return [ + require.resolve('babel-plugin-debug-macros'), + { + debugTools: { + source: '@ember/debug', + assertPredicateIndex: 1, + isDebug, + }, + externalizeHelpers: { + module: true, + }, + flags: [{ source: '@glimmer/env', flags: { DEBUG: isDebug } }], + }, + ]; +}; diff --git a/lib/build-strip-class-callcheck-plugin.js b/lib/build-strip-class-callcheck-plugin.js new file mode 100644 index 00000000000..90b1e1f8bc2 --- /dev/null +++ b/lib/build-strip-class-callcheck-plugin.js @@ -0,0 +1,6 @@ +module.exports = () => { + return [ + require.resolve('babel-plugin-filter-imports'), + { imports: { 'ember-babel': ['_classCallCheck'] } }, + ]; +}; diff --git a/lib/concat-bundle.js b/lib/concat-bundle.js new file mode 100644 index 00000000000..bedb025a805 --- /dev/null +++ b/lib/concat-bundle.js @@ -0,0 +1,19 @@ +'use strict'; + +const concat = require('broccoli-concat'); + +module.exports = function( + tree, + { outputFile, header = '', footer = '', headerFiles = [], footerFiles = [] } +) { + return concat(tree, { + header: '(function() {' + header, + outputFile, + headerFiles, + sourceMapConfig: { enabled: true }, + footerFiles, + inputFiles: ['**/*.js'], + annotation: outputFile, + footer: footer + '\n}());', + }); +}; diff --git a/lib/index.js b/lib/index.js index ced4529b18c..8bba34d4d69 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,8 +1,20 @@ 'use strict'; -const fs = require('fs'); +const MergeTrees = require('broccoli-merge-trees'); +const Funnel = require('broccoli-funnel'); const path = require('path'); const resolve = require('resolve'); +const concatBundle = require('./concat-bundle'); +const buildDebugMacroPlugin = require('./build-debug-macro-plugin'); +const buildStripClassCallcheckPlugin = require('./build-strip-class-callcheck-plugin'); + +const isProduction = process.env.EMBER_ENV === 'production'; + +const PRE_BUILT_TARGETS = [ + 'last 1 Chrome versions', + 'last 1 Firefox versions', + 'last 1 Safari versions', +]; const paths = {}; const absolutePaths = {}; @@ -16,8 +28,8 @@ function add(paths, name, path) { }); } -add(paths, 'prod', 'vendor/ember/ember.prod.js'); -add(paths, 'debug', 'vendor/ember/ember.debug.js'); +add(paths, 'prod', 'vendor/ember/ember.js'); +add(paths, 'debug', 'vendor/ember/ember.js'); add(paths, 'testing', 'vendor/ember/ember-testing.js'); add(paths, 'jquery', 'vendor/ember/jquery/jquery.js'); @@ -28,7 +40,7 @@ add( ); module.exports = { - init: function() { + init() { this._super.init && this._super.init.apply(this, arguments); if ('ember' in this.project.bowerDependencies()) { @@ -42,17 +54,38 @@ module.exports = { // considers `__dirname` here to be the root, but since our main entry // point is within a subfolder we need to correct that this.root = path.join(__dirname, '..'); + + // Updates the vendor tree to point to dist, so we get the correct tree in + // treeForVendor + this.treePaths.vendor = 'dist'; }, name: 'ember-source', - paths: paths, - absolutePaths: absolutePaths, + paths, + absolutePaths, + + transpileTree(tree) { + let emberCliBabel = this.addons.find(a => a.name === 'ember-cli-babel'); + let options = emberCliBabel.buildBabelOptions(); + + options['ember-cli-babel'] = options['ember-cli-babel'] || {}; + options['ember-cli-babel'].disableDebugTooling = true; + options['ember-cli-babel'].disableEmberModulesAPIPolyfill = true; + + options.babel = options.babel || {}; + options.babel.plugins = options.babel.plugins || []; + options.babel.plugins.push(buildDebugMacroPlugin(!isProduction)); + options.babel.plugins.push(buildStripClassCallcheckPlugin()); + + return emberCliBabel.transpileTree(tree, options); + }, - treeForVendor: function() { + treeForVendor(tree) { let Funnel = require('broccoli-funnel'); let MergeTrees = require('broccoli-merge-trees'); let jqueryPath; + try { jqueryPath = path.dirname( resolve.sync('jquery/package.json', { basedir: this.project.root }) @@ -66,49 +99,63 @@ module.exports = { files: ['jquery.js'], }); - let emberSourceDistPath = path.join(__dirname, '..', 'dist'); + let ember; + let targets = (this.project && this.project.targets && this.project.targets.browsers) || []; - let emberCliBabel = this.addons.find(a => a.name === 'ember-cli-babel'); - let needsLegacyBuild = [ - 'transform-literals', - 'transform-arrow-functions', - 'transform-destructuring', - 'transform-spread', - 'transform-parameters', - 'transform-computed-properties', - 'transform-shorthand-properties', - 'transform-block-scoping', - 'transform-classes', - ].some(p => emberCliBabel.isPluginRequired(p)); - - if (needsLegacyBuild) { - emberSourceDistPath = path.join(emberSourceDistPath, 'legacy'); - } - - let emberFiles = [ - 'ember-template-compiler.js', - 'ember-testing.js', - 'ember.debug.js', - 'ember.min.js', - 'ember.prod.js', - ] - .map(function(file) { - return [file, file.replace('.js', '.map')]; - }) - .reduce(function(flat, jsAndMap) { - return flat.concat(jsAndMap); - }, []) - .filter(function(file) { - let fullPath = path.join(emberSourceDistPath, file); - - return fs.existsSync(fullPath); + if (!isProduction && PRE_BUILT_TARGETS.every(target => targets.includes(target))) { + ember = new Funnel(tree, { + destDir: 'ember', + include: ['ember.js', 'ember.map', 'ember-testing.js', 'ember-testing.map'], }); - - let ember = new Funnel(emberSourceDistPath, { - destDir: 'ember', - files: emberFiles, - }); + } else { + // Bundling + let packages = this.transpileTree(new Funnel(tree, { srcDir: 'packages' })); + let dependencies = this.transpileTree(new Funnel(tree, { srcDir: 'dependencies' })); + let headerFiles = new Funnel(tree, { srcDir: 'header' }); + + ember = new Funnel(buildBundles(packages, dependencies, headerFiles), { + destDir: 'ember', + }); + } return new MergeTrees([ember, jquery]); }, }; + +function buildBundles(packages, dependencies, headerFiles) { + let exclude = isProduction ? ['ember-testing/**'] : []; + + let emberFiles = new MergeTrees([new Funnel(packages, { exclude }), dependencies, headerFiles]); + + let emberTestingFiles = new MergeTrees([ + new Funnel(packages, { + include: [ + '@ember/debug/lib/**', + '@ember/debug/index.js', + 'ember-testing/index.js', + 'ember-testing/lib/**', + ], + }), + headerFiles, + ]); + + return new MergeTrees([ + concatBundle(emberFiles, { + outputFile: 'ember.js', + headerFiles: ['license.js', 'loader.js'], + footer: "require('ember');", + }), + + concatBundle(emberTestingFiles, { + outputFile: 'ember-testing.js', + headerFiles: ['license.js', 'loader.js'], + footer: ` + var testing = require('ember-testing'); + Ember.Test = testing.Test; + Ember.Test.Adapter = testing.Adapter; + Ember.Test.QUnitAdapter = testing.QUnitAdapter; + Ember.setupForTesting = testing.setupForTesting; + `, + }), + ]); +} diff --git a/lib/run-in-sequence.js b/lib/run-in-sequence.js deleted file mode 100644 index b38dd68fe81..00000000000 --- a/lib/run-in-sequence.js +++ /dev/null @@ -1,13 +0,0 @@ -var RSVP = require('rsvp'); - -module.exports = function runInSequence(tasks) { - var length = tasks.length; - var current = RSVP.Promise.resolve(); - var results = new Array(length); - - for (var i = 0; i < length; ++i) { - current = results[i] = current.then(tasks[i]); - } - - return RSVP.Promise.all(results); -}; diff --git a/package.json b/package.json index 4b250e6a968..a94281f9c4c 100644 --- a/package.json +++ b/package.json @@ -16,27 +16,15 @@ "blueprints", "dist/ember-template-compiler.js", "dist/ember-template-compiler.map", + "dist/packages/*", + "dist/dependencies/*", + "dist/header/*", + "dist/ember.js", + "dist/ember.map", "dist/ember-testing.js", "dist/ember-testing.map", - "dist/ember.debug.js", - "dist/ember.debug.map", - "dist/ember.min.js", - "dist/ember.min.map", - "dist/ember.prod.js", - "dist/ember.prod.map", - "dist/legacy/ember-template-compiler.js", - "dist/legacy/ember-template-compiler.map", - "dist/legacy/ember-testing.js", - "dist/legacy/ember-testing.map", - "dist/legacy/ember.debug.js", - "dist/legacy/ember.debug.map", - "dist/legacy/ember.min.js", - "dist/legacy/ember.min.map", - "dist/legacy/ember.prod.js", - "dist/legacy/ember.prod.map", "docs/data.json", - "lib/index.js", - "vendor/ember" + "lib/*" ], "repository": { "type": "git", @@ -60,6 +48,9 @@ "test:browserstack": "node bin/run-browserstack-tests.js" }, "dependencies": { + "babel-plugin-filter-imports": "^3.0.0", + "babel-plugin-debug-macros": "^0.3.2", + "broccoli-concat": "^3.7.3", "broccoli-funnel": "^2.0.2", "broccoli-merge-trees": "^3.0.2", "chalk": "^2.4.2", @@ -107,13 +98,10 @@ "auto-dist-tag": "^1.0.0", "aws-sdk": "^2.493.0", "babel-eslint": "^10.0.2", - "babel-plugin-debug-macros": "^0.3.2", - "babel-plugin-filter-imports": "^2.0.4", "babel-plugin-module-resolver": "^3.2.0", "babel-template": "^6.26.0", "backburner.js": "^2.6.0", "broccoli-babel-transpiler": "^7.2.0", - "broccoli-concat": "^3.7.3", "broccoli-debug": "^0.6.4", "broccoli-file-creator": "^2.1.1", "broccoli-persistent-filter": "^2.3.1", diff --git a/packages/@ember/-internals/glimmer/lib/protocol-for-url.ts b/packages/@ember/-internals/glimmer/lib/protocol-for-url.ts index f05989aef91..8374413368b 100644 --- a/packages/@ember/-internals/glimmer/lib/protocol-for-url.ts +++ b/packages/@ember/-internals/glimmer/lib/protocol-for-url.ts @@ -23,13 +23,13 @@ export default function installProtocolForURL(environment: Environment) { // URL globally provided, likely from FastBoot's sandbox nodeURL = URL; environment.protocolForURL = nodeProtocolForURL; - } else if (typeof require === 'function') { + } else if (typeof module !== undefined && typeof module.require === 'function') { // Otherwise, we need to fall back to our own URL parsing. // Global `require` is shadowed by Ember's loader so we have to use the fully // qualified `module.require`. // tslint:disable-next-line:no-require-imports - nodeURL = require('url'); + nodeURL = module.require('url'); environment.protocolForURL = nodeProtocolForURL; } else { throw new Error('Could not find valid URL parsing mechanism for URL Sanitization'); diff --git a/packages/@ember/-internals/views/index.js b/packages/@ember/-internals/views/index.js index 7a2890e4eb2..7b14200d9be 100644 --- a/packages/@ember/-internals/views/index.js +++ b/packages/@ember/-internals/views/index.js @@ -1,4 +1,4 @@ -export { default as jQuery, jQueryDisabled } from './lib/system/jquery'; +export { jQuery, jQueryDisabled } from './lib/system/jquery'; export { addChildView, isSimpleClick, diff --git a/packages/@ember/-internals/views/lib/mixins/view_support.js b/packages/@ember/-internals/views/lib/mixins/view_support.js index bb3e8d0b76a..ae981cf929e 100644 --- a/packages/@ember/-internals/views/lib/mixins/view_support.js +++ b/packages/@ember/-internals/views/lib/mixins/view_support.js @@ -3,7 +3,7 @@ import { descriptorForProperty, Mixin, nativeDescDecorator } from '@ember/-inter import { assert } from '@ember/debug'; import { hasDOM } from '@ember/-internals/browser-environment'; import { matches } from '../system/utils'; -import { default as jQuery, jQueryDisabled } from '../system/jquery'; +import { jQuery, jQueryDisabled } from '../system/jquery'; import { deprecate } from '@ember/debug'; import { JQUERY_INTEGRATION } from '@ember/deprecated-features'; diff --git a/packages/@ember/-internals/views/lib/system/event_dispatcher.js b/packages/@ember/-internals/views/lib/system/event_dispatcher.js index 23418e6bd59..8af29de116a 100644 --- a/packages/@ember/-internals/views/lib/system/event_dispatcher.js +++ b/packages/@ember/-internals/views/lib/system/event_dispatcher.js @@ -4,7 +4,7 @@ import { assert } from '@ember/debug'; import { get, set } from '@ember/-internals/metal'; import { Object as EmberObject } from '@ember/-internals/runtime'; import { getElementView } from '@ember/-internals/views'; -import jQuery, { jQueryDisabled } from './jquery'; +import { jQuery, jQueryDisabled } from './jquery'; import ActionManager from './action_manager'; import addJQueryEventDeprecation from './jquery_event_deprecation'; import { contains } from './utils'; diff --git a/packages/@ember/-internals/views/lib/system/jquery.js b/packages/@ember/-internals/views/lib/system/jquery.js index 3ec655321fc..89dca88e8ec 100644 --- a/packages/@ember/-internals/views/lib/system/jquery.js +++ b/packages/@ember/-internals/views/lib/system/jquery.js @@ -3,7 +3,7 @@ import { hasDOM } from '@ember/-internals/browser-environment'; import { ENV } from '@ember/-internals/environment'; import { JQUERY_INTEGRATION } from '@ember/deprecated-features'; -let jQuery; +export let jQuery; export let jQueryDisabled = !JQUERY_INTEGRATION || ENV._JQUERY_INTEGRATION === false; if (JQUERY_INTEGRATION && hasDOM) { @@ -23,8 +23,7 @@ if (JQUERY_INTEGRATION && hasDOM) { ); } } else { + jQuery = undefined; jQueryDisabled = true; } } - -export default jQueryDisabled ? undefined : jQuery; diff --git a/packages/loader/lib/index.js b/packages/loader/lib/index.js index 9096bf4b555..9139ebc1b4a 100644 --- a/packages/loader/lib/index.js +++ b/packages/loader/lib/index.js @@ -1,5 +1,5 @@ /*globals process */ -var enifed, requireModule, Ember; +var define, require, Ember; // Used in @ember/-internals/environment/lib/global.js mainContext = this; // eslint-disable-line no-undef @@ -42,7 +42,7 @@ mainContext = this; // eslint-disable-line no-undef if (deps[i] === 'exports') { reified[i] = exports; } else if (deps[i] === 'require') { - reified[i] = requireModule; + reified[i] = require; } else { reified[i] = internalRequire(deps[i], name); } @@ -70,7 +70,7 @@ mainContext = this; // eslint-disable-line no-undef var registry = Object.create(null); var seen = Object.create(null); - enifed = function(name, deps, callback) { + define = function(name, deps, callback) { var value = {}; if (!callback) { @@ -84,26 +84,26 @@ mainContext = this; // eslint-disable-line no-undef registry[name] = value; }; - requireModule = function(name) { + require = function(name) { return internalRequire(name, null); }; // setup `require` module - requireModule['default'] = requireModule; + require['default'] = require; - requireModule.has = function registryHas(moduleName) { + require.has = function registryHas(moduleName) { return Boolean(registry[moduleName]) || Boolean(registry[moduleName + '/index']); }; - requireModule._eak_seen = registry; + require._eak_seen = registry; Ember.__loader = { - define: enifed, - require: requireModule, + define: define, + require: require, registry: registry, }; } else { - enifed = Ember.__loader.define; - requireModule = Ember.__loader.require; + define = Ember.__loader.define; + require = Ember.__loader.require; } })(); diff --git a/testem.browserstack.js b/testem.browserstack.js index e9a122f885c..cd0451cb684 100644 --- a/testem.browserstack.js +++ b/testem.browserstack.js @@ -134,7 +134,7 @@ module.exports = { '-t', '1500', '--u', - '&legacy=true', + '', ], protocol: 'browser', }, diff --git a/tests/index.html b/tests/index.html index 97ac42e1b6a..d297981200e 100644 --- a/tests/index.html +++ b/tests/index.html @@ -62,23 +62,8 @@ - - - + + @@ -62,8 +62,12 @@