diff --git a/broccoli/packages.js b/broccoli/packages.js
index db25d4d7712..ab8f37c035f 100644
--- a/broccoli/packages.js
+++ b/broccoli/packages.js
@@ -5,7 +5,6 @@ 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');
@@ -18,7 +17,6 @@ const StringReplace = require('broccoli-string-replace');
const GlimmerTemplatePrecompiler = require('./glimmer-template-compiler');
const VERSION_PLACEHOLDER = /VERSION_STRING_PLACEHOLDER/g;
const canaryFeatures = require('./canary-features');
-const injectNodeGlobals = require('./transforms/inject-node-globals');
const debugTree = BroccoliDebug.buildDebugCallback('ember-source');
@@ -44,7 +42,7 @@ module.exports.jquery = function _jquery() {
});
};
-module.exports.internalLoader = function _internalLoader() {
+module.exports.loader = function _loader() {
return new Funnel('packages/loader/lib', {
files: ['index.js'],
getDestinationPath() {
@@ -234,6 +232,7 @@ function glimmerTrees(entries) {
let trees = [];
let queue = Array.isArray(entries) ? entries.slice() : [entries];
let name;
+
while ((name = queue.pop()) !== undefined) {
if (seen.has(name)) {
continue;
@@ -255,14 +254,8 @@ function glimmerTrees(entries) {
queue.push(...dependencies);
}
}
- return new Babel(new MergeTrees(trees), {
- sourceMaps: true,
- plugins: [
- // ensures `@glimmer/compiler` requiring `crypto` works properly
- // in both browser and node-land
- injectNodeGlobals,
- ],
- });
+
+ return new MergeTrees(trees);
}
module.exports.glimmerCompilerES = () => {
diff --git a/broccoli/transforms/inject-node-globals.js b/broccoli/transforms/inject-node-globals.js
deleted file mode 100644
index b5bba89fc1e..00000000000
--- a/broccoli/transforms/inject-node-globals.js
+++ /dev/null
@@ -1,52 +0,0 @@
-function injectNodeGlobals({ types: t }) {
- let requireId;
- let importDecl;
- let moduleId;
- return {
- name: 'inject require',
- visitor: {
- Program: {
- enter(path, state) {
- if (state.file.opts.filename.match(/node-module\/index.js/)) return;
-
- requireId = path.scope.globals.require;
- moduleId = path.scope.globals.module;
-
- if (requireId || moduleId) {
- let specifiers = [];
- let source = t.stringLiteral('node-module');
-
- if (requireId) {
- delete path.scope.globals.require;
- specifiers.push(t.importSpecifier(requireId, t.identifier('require')));
- }
-
- if (moduleId) {
- delete path.scope.globals.module;
- specifiers.push(t.importSpecifier(moduleId, t.identifier('module')));
- }
-
- importDecl = t.importDeclaration(specifiers, source);
- path.unshiftContainer('body', importDecl);
- }
- },
- exit(path) {
- if (requireId) {
- path.scope.rename('require');
- }
- },
- },
- ImportDeclaration(path) {
- if (path.node === importDecl) {
- path.scope.registerDeclaration(path);
- }
- },
- },
- };
-}
-
-injectNodeGlobals.baseDir = function () {
- return 'babel-plugin-transform-es2015-modules-amd';
-};
-
-module.exports = injectNodeGlobals;
diff --git a/ember-cli-build.js b/ember-cli-build.js
index 8c0254be9bc..77b3aa5c9e3 100644
--- a/ember-cli-build.js
+++ b/ember-cli-build.js
@@ -15,7 +15,7 @@ Error.stackTraceLimit = Infinity;
const {
routerES,
jquery,
- internalLoader,
+ loader,
qunit,
handlebarsES,
rsvpES,
@@ -246,7 +246,14 @@ function templateCompilerBundle(emberPackages, transpileTree) {
}
function testHarness() {
- return new MergeTrees([emptyTestem(), testPolyfills(), testIndexHTML(), qunit(), jquery()]);
+ return new MergeTrees([
+ emptyTestem(),
+ testPolyfills(),
+ testIndexHTML(),
+ loader(),
+ qunit(),
+ jquery(),
+ ]);
}
function emptyTestem() {
@@ -262,5 +269,5 @@ function templateCompilerDependencies() {
}
function emberHeaderFiles() {
- return new MergeTrees([emberLicense(), internalLoader()]);
+ return new MergeTrees([emberLicense(), loader()]);
}
diff --git a/lib/index.js b/lib/index.js
index 3af916860e7..2205c530bda 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -237,18 +237,12 @@ module.exports = {
return new MergeTrees([
concatBundle(emberFiles, {
outputFile: 'ember.js',
- footer: "require('ember');",
+ footer: "require('@ember/-internals/bootstrap');",
}),
concatBundle(emberTestingFiles, {
outputFile: 'ember-testing.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;
- `,
+ footer: "require('ember-testing');",
}),
]);
},
diff --git a/packages/@ember/-internals/bootstrap/index.js b/packages/@ember/-internals/bootstrap/index.js
new file mode 100644
index 00000000000..d74aee1c358
--- /dev/null
+++ b/packages/@ember/-internals/bootstrap/index.js
@@ -0,0 +1,31 @@
+import require from 'require';
+import { context } from '@ember/-internals/environment';
+
+(function () {
+ let Ember;
+
+ function defineEmber(key) {
+ Object.defineProperty(context.exports, key, {
+ enumerable: true,
+ configurable: true,
+ get() {
+ if (!Ember) {
+ Ember = require('ember').default;
+ }
+
+ return Ember;
+ },
+ });
+ }
+
+ // Bootstrap the global
+ defineEmber('Ember');
+ defineEmber('Em');
+
+ // Bootstrap Node module
+ // eslint-disable-next-line no-undef
+ if (typeof module === 'object' && typeof module.require === 'function') {
+ // eslint-disable-next-line no-undef
+ module.exports = Ember = require('ember').default;
+ }
+})();
diff --git a/packages/@ember/-internals/environment/lib/global.ts b/packages/@ember/-internals/environment/lib/global.ts
index ceaff0c112c..99cbbd76dc0 100644
--- a/packages/@ember/-internals/environment/lib/global.ts
+++ b/packages/@ember/-internals/environment/lib/global.ts
@@ -1,4 +1,4 @@
-/* globals global, window, self, mainContext */
+/* globals global, window, self */
declare const mainContext: object | undefined;
// from lodash to catch fake globals
diff --git a/packages/ember-template-compiler/index.ts b/packages/ember-template-compiler/index.ts
index 3cdea8978d9..007f45f27fe 100644
--- a/packages/ember-template-compiler/index.ts
+++ b/packages/ember-template-compiler/index.ts
@@ -1,24 +1,28 @@
-import { context, ENV } from '@ember/-internals/environment';
+import { ENV } from '@ember/-internals/environment';
import { FEATURES } from '@ember/canary-features';
import VERSION from 'ember/version';
+import require from 'require';
-export const _Ember =
- (typeof (context.imports as any).Ember === 'object' && (context.imports as any).Ember) || {};
+declare global {
+ interface NodeRequire {
+ has(name: string): boolean;
+ }
-// private API used by ember-cli-htmlbars to setup ENV and FEATURES
-if (!_Ember.ENV) {
- _Ember.ENV = ENV;
-}
-if (!_Ember.FEATURES) {
- _Ember.FEATURES = FEATURES;
-}
-if (!_Ember.VERSION) {
- _Ember.VERSION = VERSION;
+ function define(path: string, deps: string[], module: () => void): void;
}
-// used for adding Ember.Handlebars.compile for backwards compat
-import setupGlobal from './lib/compat';
-setupGlobal(_Ember);
+export let _Ember: unknown;
+
+try {
+ // tslint:disable-next-line: no-require-imports
+ _Ember = require('ember');
+} catch (e) {
+ _Ember = {
+ ENV,
+ FEATURES,
+ VERSION,
+ };
+}
export { default as precompile } from './lib/system/precompile';
export { default as compile } from './lib/system/compile';
diff --git a/packages/ember-template-compiler/lib/compat.ts b/packages/ember-template-compiler/lib/compat.ts
deleted file mode 100644
index bee025ac1cc..00000000000
--- a/packages/ember-template-compiler/lib/compat.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import compile from './system/compile';
-import { registerPlugin } from './system/compile-options';
-import precompile from './system/precompile';
-
-export default function setupGlobal(Ember: any) {
- let EmberHandlebars = Ember.Handlebars;
- if (!EmberHandlebars) {
- Ember.Handlebars = EmberHandlebars = {};
- }
-
- let EmberHTMLBars = Ember.HTMLBars;
- if (!EmberHTMLBars) {
- Ember.HTMLBars = EmberHTMLBars = {};
- }
-
- EmberHTMLBars.precompile = EmberHandlebars.precompile = precompile;
- EmberHTMLBars.compile = EmberHandlebars.compile = compile;
- EmberHTMLBars.registerPlugin = registerPlugin;
-}
diff --git a/packages/node-module/require.d.ts b/packages/ember/index.d.ts
similarity index 61%
rename from packages/node-module/require.d.ts
rename to packages/ember/index.d.ts
index 58443c7f54c..46c2fa636e0 100644
--- a/packages/node-module/require.d.ts
+++ b/packages/ember/index.d.ts
@@ -1,3 +1,9 @@
+declare module 'ember' {
+ declare const Ember: any;
+
+ export default Ember;
+}
+
declare module 'require' {
export function has(path: string): boolean;
export default function require(path: string): any;
diff --git a/packages/ember/index.js b/packages/ember/index.js
index 4c7ff4c1262..74a8f145b3b 100644
--- a/packages/ember/index.js
+++ b/packages/ember/index.js
@@ -1,7 +1,6 @@
import require, { has } from 'require';
-import { getENV, getLookup, setLookup, ENV, context } from '@ember/-internals/environment';
-import { IS_NODE, module } from 'node-module';
+import { getENV, getLookup, setLookup, ENV } from '@ember/-internals/environment';
import * as utils from '@ember/-internals/utils';
import { Registry, Container } from '@ember/-internals/container';
import * as instrumentation from '@ember/instrumentation';
@@ -168,7 +167,7 @@ import {
// ****@ember/-internals/environment****
-const Ember = (typeof context.imports.Ember === 'object' && context.imports.Ember) || {};
+const Ember = {};
import { isIE } from '@ember/-internals/browser-environment';
@@ -652,15 +651,6 @@ if (EMBER_GLIMMER_INVOKE_HELPER) {
Ember._invokeHelper = invokeHelper;
}
Ember._captureRenderTree = captureRenderTree;
-Ember.Handlebars = {
- template,
- Utils: {
- escapeExpression,
- },
-};
-Ember.HTMLBars = {
- template,
-};
if (ENV.EXTEND_PROTOTYPES.String) {
String.prototype.htmlSafe = function () {
@@ -782,30 +772,99 @@ runLoadHooks('Ember.Application', Application);
Ember.DataAdapter = extensionSupport.DataAdapter;
Ember.ContainerDebugAdapter = extensionSupport.ContainerDebugAdapter;
-if (has('ember-template-compiler')) {
- require('ember-template-compiler');
+let EmberHandlebars = {
+ template,
+ Utils: {
+ escapeExpression,
+ },
+};
+
+let EmberHTMLBars = {
+ template,
+};
+
+function defineEmberTemplateCompilerLazyLoad(key) {
+ Object.defineProperty(Ember, key, {
+ configurable: true,
+ enumerable: true,
+ get() {
+ if (require.has('ember-template-compiler')) {
+ let templateCompiler = require('ember-template-compiler');
+
+ EmberHTMLBars.precompile = EmberHandlebars.precompile = templateCompiler.precompile;
+ EmberHTMLBars.compile = EmberHandlebars.compile = templateCompiler.compile;
+ EmberHTMLBars.registerPlugin = templateCompiler.registerPlugin;
+
+ Object.defineProperty(Ember, 'HTMLBars', {
+ configurable: true,
+ writable: true,
+ enumerable: true,
+ value: EmberHTMLBars,
+ });
+ Object.defineProperty(Ember, 'Handlebars', {
+ configurable: true,
+ writable: true,
+ enumerable: true,
+ value: EmberHandlebars,
+ });
+ }
+
+ return key === 'Handlebars' ? EmberHandlebars : EmberHTMLBars;
+ },
+ });
}
+defineEmberTemplateCompilerLazyLoad('HTMLBars');
+defineEmberTemplateCompilerLazyLoad('Handlebars');
+
// do this to ensure that Ember.Test is defined properly on the global
// if it is present.
-if (has('ember-testing')) {
- let testing = require('ember-testing');
+function defineEmberTestingLazyLoad(key) {
+ Object.defineProperty(Ember, key, {
+ configurable: true,
+ enumerable: true,
+ get() {
+ if (has('ember-testing')) {
+ let testing = require('ember-testing');
+
+ let { Test, Adapter, QUnitAdapter, setupForTesting } = testing;
+ Test.Adapter = Adapter;
+ Test.QUnitAdapter = QUnitAdapter;
+
+ Object.defineProperty(Ember, 'Test', {
+ configurable: true,
+ writable: true,
+ enumerable: true,
+ value: Test,
+ });
+ Object.defineProperty(Ember, 'setupForTesting', {
+ configurable: true,
+ writable: true,
+ enumerable: true,
+ value: setupForTesting,
+ });
+
+ return key === 'Test' ? Test : setupForTesting;
+ }
- Ember.Test = testing.Test;
- Ember.Test.Adapter = testing.Adapter;
- Ember.Test.QUnitAdapter = testing.QUnitAdapter;
- Ember.setupForTesting = testing.setupForTesting;
+ return undefined;
+ },
+ });
}
+defineEmberTestingLazyLoad('Test');
+defineEmberTestingLazyLoad('setupForTesting');
+
runLoadHooks('Ember');
-export default Ember;
+Ember.__loader = {
+ require,
+ // eslint-disable-next-line no-undef
+ define,
+ registry: require.entries,
+};
-if (IS_NODE) {
- module.exports = Ember;
-} else {
- context.exports.Ember = context.exports.Em = Ember;
-}
+export default Ember;
/**
@module jquery
diff --git a/packages/internal-test-helpers/lib/confirm-export.js b/packages/internal-test-helpers/lib/confirm-export.js
index 2f0be668fd4..7e5eb68e2cb 100644
--- a/packages/internal-test-helpers/lib/confirm-export.js
+++ b/packages/internal-test-helpers/lib/confirm-export.js
@@ -21,7 +21,8 @@ export default function confirmExport(Ember, assert, path, moduleId, exportName)
if (typeof exportName === 'string') {
let mod = require(moduleId);
- assert.equal(desc.value, mod[exportName], `Ember.${path} is exported correctly`);
+ let value = 'value' in desc ? desc.value : desc.get.call(Ember);
+ assert.equal(value, mod[exportName], `Ember.${path} is exported correctly`);
assert.notEqual(mod[exportName], undefined, `Ember.${path} is not \`undefined\``);
} else if ('value' in desc) {
assert.equal(desc.value, exportName.value, `Ember.${path} is exported correctly`);
diff --git a/packages/internal-test-helpers/lib/ember-dev/setup-qunit.ts b/packages/internal-test-helpers/lib/ember-dev/setup-qunit.ts
index bcc6c785ab7..5142e42d09d 100644
--- a/packages/internal-test-helpers/lib/ember-dev/setup-qunit.ts
+++ b/packages/internal-test-helpers/lib/ember-dev/setup-qunit.ts
@@ -1,3 +1,5 @@
+import Ember from 'ember';
+
import { getDebugFunction, setDebugFunction } from '@ember/debug';
import { DEBUG } from '@glimmer/env';
diff --git a/packages/loader/lib/index.js b/packages/loader/lib/index.js
index dcb6c7c4594..3c125722870 100644
--- a/packages/loader/lib/index.js
+++ b/packages/loader/lib/index.js
@@ -1,12 +1,32 @@
-/*globals process */
-let define, require, Ember;
-
-// Used in @ember/-internals/environment/lib/global.js
-mainContext = this; // eslint-disable-line no-undef
+/* eslint-disable no-var */
+/* globals global globalThis self */
+var define, require;
(function () {
- let registry;
- let seen;
+ var globalObj =
+ typeof globalThis !== 'undefined'
+ ? globalThis
+ : typeof self !== 'undefined'
+ ? self
+ : typeof window !== 'undefined'
+ ? window
+ : typeof global !== 'undefined'
+ ? global
+ : null;
+
+ if (globalObj === null) {
+ throw new Error('unable to locate global object');
+ }
+
+ if (typeof globalObj.define === 'function' && typeof globalObj.require === 'function') {
+ define = globalObj.define;
+ require = globalObj.require;
+
+ return;
+ }
+
+ var registry = Object.create(null);
+ var seen = Object.create(null);
function missingModule(name, referrerName) {
if (referrerName) {
@@ -17,15 +37,15 @@ mainContext = this; // eslint-disable-line no-undef
}
function internalRequire(_name, referrerName) {
- let name = _name;
- let mod = registry[name];
+ var name = _name;
+ var mod = registry[name];
if (!mod) {
name = name + '/index';
mod = registry[name];
}
- let exports = seen[name];
+ var exports = seen[name];
if (exports !== undefined) {
return exports;
@@ -37,17 +57,17 @@ mainContext = this; // eslint-disable-line no-undef
missingModule(_name, referrerName);
}
- let deps = mod.deps;
- let callback = mod.callback;
- let reified = new Array(deps.length);
+ var deps = mod.deps;
+ var callback = mod.callback;
+ var reified = new Array(deps.length);
- for (let i = 0; i < deps.length; i++) {
+ for (var i = 0; i < deps.length; i++) {
if (deps[i] === 'exports') {
reified[i] = exports;
} else if (deps[i] === 'require') {
reified[i] = require;
} else {
- reified[i] = internalRequire(deps[i], name);
+ reified[i] = require(deps[i], name);
}
}
@@ -56,57 +76,21 @@ mainContext = this; // eslint-disable-line no-undef
return exports;
}
- let isNode =
- typeof window === 'undefined' &&
- typeof process !== 'undefined' &&
- {}.toString.call(process) === '[object process]';
-
- if (!isNode) {
- Ember = this.Ember = this.Ember || {};
- }
-
- if (typeof Ember === 'undefined') {
- Ember = {};
- }
-
- if (typeof Ember.__loader === 'undefined') {
- registry = Object.create(null);
- seen = Object.create(null);
-
- define = function (name, deps, callback) {
- let value = {};
+ require = function (name) {
+ return internalRequire(name, null);
+ };
- if (!callback) {
- value.deps = [];
- value.callback = deps;
- } else {
- value.deps = deps;
- value.callback = callback;
- }
+ // eslint-disable-next-line no-unused-vars
+ define = function (name, deps, callback) {
+ registry[name] = { deps: deps, callback: callback };
+ };
- registry[name] = value;
- };
+ // setup `require` module
+ require['default'] = require;
- require = function (name) {
- return internalRequire(name, null);
- };
+ require.has = function registryHas(moduleName) {
+ return Boolean(registry[moduleName]) || Boolean(registry[moduleName + '/index']);
+ };
- // setup `require` module
- require['default'] = require;
-
- require.has = function registryHas(moduleName) {
- return Boolean(registry[moduleName]) || Boolean(registry[moduleName + '/index']);
- };
-
- require._eak_seen = registry;
-
- Ember.__loader = {
- define: define,
- require: require,
- registry: registry,
- };
- } else {
- define = Ember.__loader.define;
- require = Ember.__loader.require;
- }
+ require._eak_seen = registry;
})();
diff --git a/packages/node-module/index.d.ts b/packages/node-module/index.d.ts
deleted file mode 100644
index 249e58d812f..00000000000
--- a/packages/node-module/index.d.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export const IS_NODE: boolean;
-
-export function require(url: string): string;
diff --git a/packages/node-module/index.js b/packages/node-module/index.js
deleted file mode 100644
index cad5138a421..00000000000
--- a/packages/node-module/index.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/*global module */
-
-const IS_NODE = typeof module === 'object' && typeof module.require === 'function';
-
-let exportModule;
-let exportRequire;
-
-if (IS_NODE) {
- exportModule = module;
- exportRequire = module.require;
-} else {
- exportModule = null;
- exportRequire = null;
-}
-
-export { IS_NODE, exportModule as module, exportRequire as require };
diff --git a/tests/index.html b/tests/index.html
index 57bf6b6b84d..9046533ef85 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -10,6 +10,7 @@
}
+
@@ -90,7 +91,7 @@
@@ -114,7 +115,7 @@
}
}
- var setupQUnit = window.Ember.__loader.require('internal-test-helpers/lib/ember-dev/setup-qunit')['default'];
+ var setupQUnit = require('internal-test-helpers/lib/ember-dev/setup-qunit')['default'];
setupQUnit();
// Tests should time out after 15 seconds
@@ -180,11 +181,11 @@
skipPackages = (skipPackages && skipPackages.split(',')) || [];
var skipPackageRegexp = new RegExp('^('+skipPackages.join('|')+')/');
- for (var moduleName in Ember.__loader.registry) {
+ for (var moduleName in require._eak_seen) {
if (!moduleName.match(packageRegexp)) { continue; }
if (moduleName.match(skipPackageRegexp)) { continue; }
- if (moduleName.match(/[_-]test$/)) { Ember.__loader.require(moduleName); }
+ if (moduleName.match(/[_-]test$/)) { require(moduleName); }
}