Skip to content

Commit

Permalink
Refactor the internal Ember loader to use the standard Ember CLI loader
Browse files Browse the repository at this point in the history
This PR refactors the internal Ember loader so that it uses the standard
Ember CLI loader instead for modules. This means that modules will be
defined in the main namespace, and importable from there, instead of in
a hidden namespace that only Ember can use.

Notes:

- Code is still loaded and built via `treeForVendor` and included as a
  vendor file. This needs to be the case for the time being for
  bootstrapping.
- Loader code is still included for Node support. If `define` and
  `require` are not already defined, then a backup shim is used instead.
- Modules are now exposed from Ember, but `ember-cli-babel` still
  transpiles them to global references. This unblocks us from being able
  to make all modules work normally, however.
- `require` shim module is no longer defined, we reference `define` and
  `require` as globals instead (which is more accurate). In the future
  we should update this to use Embroider's conventions.
- `__loader` is still exposed on the Ember object, referencing the same
  values as before.
  • Loading branch information
NullVoxPopuli authored and Chris Garrett committed Feb 9, 2021
1 parent df22118 commit b059b42
Show file tree
Hide file tree
Showing 20 changed files with 159 additions and 196 deletions.
4 changes: 3 additions & 1 deletion .eslintrc.js
Expand Up @@ -50,7 +50,7 @@ module.exports = {
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-this-alias': 'off',
'@typescript-eslint/no-var-requires': 'warn',
'@typescript-eslint/no-var-requires': 'off',

// TODO: Enable and fix these rules
// Typescript provides better types with these rules enabled
Expand Down Expand Up @@ -81,6 +81,8 @@ module.exports = {
Set: true,
Symbol: true,
WeakMap: true,
require: true,
define: true,
},

rules: {
Expand Down
15 changes: 4 additions & 11 deletions broccoli/packages.js
Expand Up @@ -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');
Expand All @@ -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');

Expand All @@ -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() {
Expand Down Expand Up @@ -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;
Expand All @@ -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 = () => {
Expand Down
52 changes: 0 additions & 52 deletions broccoli/transforms/inject-node-globals.js

This file was deleted.

13 changes: 10 additions & 3 deletions ember-cli-build.js
Expand Up @@ -15,7 +15,7 @@ Error.stackTraceLimit = Infinity;
const {
routerES,
jquery,
internalLoader,
loader,
qunit,
handlebarsES,
rsvpES,
Expand Down Expand Up @@ -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() {
Expand All @@ -262,5 +269,5 @@ function templateCompilerDependencies() {
}

function emberHeaderFiles() {
return new MergeTrees([emberLicense(), internalLoader()]);
return new MergeTrees([emberLicense(), loader()]);
}
9 changes: 1 addition & 8 deletions lib/index.js
Expand Up @@ -237,18 +237,11 @@ 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;
`,
}),
]);
},
Expand Down
30 changes: 30 additions & 0 deletions packages/@ember/-internals/bootstrap/index.js
@@ -0,0 +1,30 @@
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;
}
})();
2 changes: 1 addition & 1 deletion 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
Expand Down
33 changes: 18 additions & 15 deletions packages/ember-template-compiler/index.ts
@@ -1,24 +1,27 @@
import { context, ENV } from '@ember/-internals/environment';
import { ENV } from '@ember/-internals/environment';
import { FEATURES } from '@ember/canary-features';
import VERSION from 'ember/version';

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';
Expand Down
3 changes: 1 addition & 2 deletions packages/ember-template-compiler/lib/system/compile.ts
@@ -1,7 +1,6 @@
/**
@module ember
*/
import require, { has } from 'require';
import { EmberPrecompileOptions } from '../types';
import precompile from './precompile';

Expand All @@ -23,7 +22,7 @@ export default function compile(
templateString: string,
options: Partial<EmberPrecompileOptions> = {}
): Factory {
if (!template && has('@ember/-internals/glimmer')) {
if (!template && require.has('@ember/-internals/glimmer')) {
// tslint:disable-next-line:no-require-imports
template = require('@ember/-internals/glimmer').template;
}
Expand Down
7 changes: 3 additions & 4 deletions packages/ember-template-compiler/lib/system/initializer.ts
@@ -1,11 +1,10 @@
import require, { has } from 'require';
import bootstrap from './bootstrap';

// Globals mode template compiler
if (
has('@ember/application') &&
has('@ember/-internals/browser-environment') &&
has('@ember/-internals/glimmer')
require.has('@ember/application') &&
require.has('@ember/-internals/browser-environment') &&
require.has('@ember/-internals/glimmer')
) {
// tslint:disable:no-require-imports
let emberEnv = require('@ember/-internals/browser-environment');
Expand Down
5 changes: 5 additions & 0 deletions packages/ember/index.d.ts
@@ -0,0 +1,5 @@
declare module 'ember' {
declare const Ember: any;

export default Ember;
}
39 changes: 25 additions & 14 deletions packages/ember/index.js
@@ -1,7 +1,4 @@
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';
Expand Down Expand Up @@ -168,7 +165,7 @@ import {

// ****@ember/-internals/environment****

const Ember = (typeof context.imports.Ember === 'object' && context.imports.Ember) || {};
const Ember = {};

import { isIE } from '@ember/-internals/browser-environment';

Expand Down Expand Up @@ -782,13 +779,27 @@ runLoadHooks('Ember.Application', Application);
Ember.DataAdapter = extensionSupport.DataAdapter;
Ember.ContainerDebugAdapter = extensionSupport.ContainerDebugAdapter;

if (has('ember-template-compiler')) {
require('ember-template-compiler');
if (require.has('ember-template-compiler')) {
let templateCompiler = require('ember-template-compiler');

let EmberHandlebars = Ember.Handlebars;
if (!EmberHandlebars) {
Ember.Handlebars = EmberHandlebars = {};
}

let EmberHTMLBars = Ember.HTMLBars;
if (!EmberHTMLBars) {
Ember.HTMLBars = EmberHTMLBars = {};
}

EmberHTMLBars.precompile = EmberHandlebars.precompile = templateCompiler.precompile;
EmberHTMLBars.compile = EmberHandlebars.compile = templateCompiler.compile;
EmberHTMLBars.registerPlugin = templateCompiler.registerPlugin;
}

// do this to ensure that Ember.Test is defined properly on the global
// if it is present.
if (has('ember-testing')) {
if (require.has('ember-testing')) {
let testing = require('ember-testing');

Ember.Test = testing.Test;
Expand All @@ -799,13 +810,13 @@ if (has('ember-testing')) {

runLoadHooks('Ember');

export default Ember;
Ember.__loader = {
require,
define,
registry: require._eak_seen,
};

if (IS_NODE) {
module.exports = Ember;
} else {
context.exports.Ember = context.exports.Em = Ember;
}
export default Ember;

/**
@module jquery
Expand Down
1 change: 0 additions & 1 deletion packages/ember/tests/reexports_test.js
@@ -1,5 +1,4 @@
import Ember from '../index';
import require from 'require';
import {
FEATURES,
EMBER_GLIMMER_HELPER_MANAGER,
Expand Down
2 changes: 0 additions & 2 deletions packages/internal-test-helpers/lib/confirm-export.js
@@ -1,5 +1,3 @@
import require from 'require';

function getDescriptor(obj, path) {
let parts = path.split('.');
let value = obj;
Expand Down
2 changes: 2 additions & 0 deletions 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';

Expand Down

0 comments on commit b059b42

Please sign in to comment.