Skip to content

Commit 45bdb10

Browse files
author
Chris Garrett
committed
Disable the modules API polyfill on latest Ember
Disables the modules API polyfill on the latest versions of Ember.
1 parent e3818be commit 45bdb10

10 files changed

Lines changed: 1109 additions & 290 deletions

lib/colocated-babel-plugin.js

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
module.exports = function (babel) {
44
let t = babel.types;
55

6-
function makeSetComponentTemplateMemberExpression() {
6+
function makeSetComponentTemplateExpression(state) {
7+
if (!state.opts.requiresModuleApiPolyfill) {
8+
return state._colocationEnsureImport('setComponentTemplate', '@ember/component');
9+
}
10+
711
return t.memberExpression(t.identifier('Ember'), t.identifier('_setComponentTemplate'));
812
}
913

@@ -15,6 +19,53 @@ module.exports = function (babel) {
1519
name: 'ember-cli-htmlbars-colocation-template',
1620

1721
visitor: {
22+
Program(path, state) {
23+
let allAddedImports = {};
24+
25+
state._colocationEnsureImport = (exportName, moduleName) => {
26+
let addedImports = (allAddedImports[moduleName] = allAddedImports[moduleName] || {});
27+
28+
if (addedImports[exportName]) return addedImports[exportName];
29+
30+
let importDeclarations = path.get('body').filter((n) => n.type === 'ImportDeclaration');
31+
32+
let preexistingImportDeclaration = importDeclarations.find(
33+
(n) => n.get('source').get('value').node === moduleName
34+
);
35+
36+
if (preexistingImportDeclaration) {
37+
let importSpecifier = preexistingImportDeclaration
38+
.get('specifiers')
39+
.find(({ node }) => {
40+
return exportName === 'default'
41+
? t.isImportDefaultSpecifier(node)
42+
: node.imported.name === exportName;
43+
});
44+
45+
if (importSpecifier) {
46+
addedImports[exportName] = importSpecifier.node.local;
47+
}
48+
}
49+
50+
if (!addedImports[exportName]) {
51+
let uid = path.scope.generateUidIdentifier(
52+
exportName === 'default' ? moduleName : exportName
53+
);
54+
addedImports[exportName] = uid;
55+
56+
let newImportSpecifier =
57+
exportName === 'default'
58+
? t.importDefaultSpecifier(uid)
59+
: t.importSpecifier(uid, t.identifier(exportName));
60+
61+
let newImport = t.importDeclaration([newImportSpecifier], t.stringLiteral(moduleName));
62+
path.unshiftContainer('body', newImport);
63+
}
64+
65+
return addedImports[exportName];
66+
};
67+
},
68+
1869
VariableDeclarator(path, state) {
1970
if (path.node.id.name === '__COLOCATED_TEMPLATE__') {
2071
state.colocatedTemplateFound = true;
@@ -38,7 +89,7 @@ module.exports = function (babel) {
3889

3990
state.setComponentTemplateInjected = true;
4091
let defaultExportDeclaration = path.node.declaration;
41-
let setComponentTemplateMemberExpression = makeSetComponentTemplateMemberExpression();
92+
let setComponentTemplateMemberExpression = makeSetComponentTemplateExpression(state);
4293
let colocatedTemplateIdentifier = makeColocatedTemplateIdentifier();
4394

4495
if (defaultExportDeclaration.type === 'ClassDeclaration') {
@@ -85,7 +136,7 @@ module.exports = function (babel) {
85136
state.setComponentTemplateInjected = true;
86137
path.parent.body.push(
87138
t.expressionStatement(
88-
t.callExpression(makeSetComponentTemplateMemberExpression(), [
139+
t.callExpression(makeSetComponentTemplateExpression(state), [
89140
makeColocatedTemplateIdentifier(),
90141
defaultSpecifier.local,
91142
])

lib/ember-addon-main.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const path = require('path');
44
const SilentError = require('silent-error');
55
const utils = require('./utils');
6+
const VersionChecker = require('ember-cli-version-checker');
67

78
let registryInvocationCounter = 0;
89

@@ -62,7 +63,7 @@ module.exports = {
6263
transpileTree(inputTree, htmlbarsOptions) {
6364
const TemplateCompiler = require('./template-compiler-plugin');
6465

65-
return new TemplateCompiler(inputTree, htmlbarsOptions);
66+
return new TemplateCompiler(inputTree, htmlbarsOptions, this._requiresModuleApiPolyfill);
6667
},
6768

6869
setupPreprocessorRegistry(type, registry) {
@@ -169,6 +170,9 @@ module.exports = {
169170

170171
let isProduction = process.env.EMBER_ENV === 'production';
171172

173+
let checker = new VersionChecker(this.parent).for('ember-source', 'npm');
174+
this._requiresModuleApiPolyfill = checker.exists() && checker.lt('3.27.0-alpha.1');
175+
172176
// This is an option intended to be used only be `ember-template-imports`.
173177
// DO NOT USE THIS
174178
let customModules =
@@ -190,7 +194,8 @@ module.exports = {
190194
this.projectConfig(),
191195
templateCompilerPath,
192196
isProduction,
193-
customModules
197+
customModules,
198+
this._requiresModuleApiPolyfill
194199
);
195200

196201
babelPlugins.push(htmlbarsInlinePrecompilePlugin);
@@ -205,14 +210,18 @@ module.exports = {
205210
projectConfig: this.projectConfig(),
206211
templateCompilerPath,
207212
modules: customModules,
213+
requiresModuleApiPolyfill: this._requiresModuleApiPolyfill,
208214
});
209215

210216
babelPlugins.push(htmlBarsPlugin);
211217
}
212218
}
213219

214220
if (this._shouldColocateTemplates() && !utils.isColocatedBabelPluginRegistered(babelPlugins)) {
215-
babelPlugins.push(require.resolve('./colocated-babel-plugin'));
221+
babelPlugins.push([
222+
require.resolve('./colocated-babel-plugin'),
223+
{ requiresModuleApiPolyfill: this._requiresModuleApiPolyfill },
224+
]);
216225
}
217226
},
218227

lib/template-compiler-plugin.js

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function rethrowBuildError(error) {
2424
}
2525

2626
class TemplateCompiler extends Filter {
27-
constructor(inputTree, _options) {
27+
constructor(inputTree, _options, requiresModuleApiPolyfill) {
2828
let options = _options || {};
2929

3030
if (!('persist' in options)) {
@@ -35,6 +35,7 @@ class TemplateCompiler extends Filter {
3535

3636
this.options = options;
3737
this.inputTree = inputTree;
38+
this.requiresModuleApiPolyfill = requiresModuleApiPolyfill;
3839

3940
// TODO: do we need this?
4041
this.precompile = this.options.templateCompiler.precompile;
@@ -51,6 +52,7 @@ class TemplateCompiler extends Filter {
5152
processString(string, relativePath) {
5253
let srcDir = this.inputPaths[0];
5354
let srcName = path.join(srcDir, relativePath);
55+
5456
try {
5557
// we have to reverse these for reasons that are a bit bonkers. the initial
5658
// version of this system used `registeredPlugin` from
@@ -63,25 +65,23 @@ class TemplateCompiler extends Filter {
6365
// sooooooo...... we are forced to maintain that **absolutely bonkers** ordering
6466
let astPlugins = this.options.plugins ? [...this.options.plugins.ast].reverse() : [];
6567

66-
let result =
67-
'export default ' +
68-
utils.template(this.options.templateCompiler, stripBom(string), {
69-
contents: string,
70-
isProduction: this.options.isProduction,
71-
moduleName: relativePath,
72-
parseOptions: {
73-
srcName: srcName,
74-
},
75-
76-
// intentionally not using `plugins: this.options.plugins` here
77-
// because if we do, Ember will mutate the shared plugins object (adding
78-
// all of the built in AST transforms into plugins.ast, which breaks
79-
// persistent caching)
80-
plugins: {
81-
ast: astPlugins,
82-
},
83-
}) +
84-
';';
68+
let precompiled = this.options.templateCompiler.precompile(stripBom(string), {
69+
contents: string,
70+
isProduction: this.options.isProduction,
71+
moduleName: relativePath,
72+
parseOptions: {
73+
srcName: srcName,
74+
},
75+
76+
// intentionally not using `plugins: this.options.plugins` here
77+
// because if we do, Ember will mutate the shared plugins object (adding
78+
// all of the built in AST transforms into plugins.ast, which breaks
79+
// persistent caching)
80+
plugins: {
81+
ast: astPlugins,
82+
},
83+
});
84+
8585
if (this.options.dependencyInvalidation) {
8686
let plugins = pluginsWithDependencies(this.options.plugins.ast);
8787
let dependencies = [];
@@ -91,7 +91,12 @@ class TemplateCompiler extends Filter {
9191
}
9292
this.dependencies.setDependencies(relativePath, dependencies);
9393
}
94-
return result;
94+
95+
if (this.requiresModuleApiPolyfill) {
96+
return `export default Ember.HTMLBars.template(${precompiled});`;
97+
} else {
98+
return `import { createTemplateFactory } from '@ember/template-factory';\n\nexport default createTemplateFactory(${precompiled});`;
99+
}
95100
} catch (error) {
96101
rethrowBuildError(error);
97102
}
@@ -106,6 +111,8 @@ class TemplateCompiler extends Filter {
106111
}
107112
}
108113

114+
strippedOptions._requiresModuleApiPolyfill = this.requiresModuleApiPolyfill;
115+
109116
return strippedOptions;
110117
}
111118

lib/utils.js

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,20 @@ function isInlinePrecompileBabelPluginRegistered(plugins) {
5050
}
5151

5252
function isColocatedBabelPluginRegistered(plugins) {
53-
return plugins.some(
54-
(plugin) => typeof plugin === 'string' && plugin === require.resolve('./colocated-babel-plugin')
55-
);
53+
return plugins.some((plugin) => {
54+
let path = Array.isArray(plugin) ? plugin[0] : plugin;
55+
56+
return typeof path === 'string' && path === require.resolve('./colocated-babel-plugin');
57+
});
5658
}
5759

5860
function buildParalleizedBabelPlugin(
5961
pluginInfo,
6062
projectConfig,
6163
templateCompilerPath,
6264
isProduction,
63-
customModules
65+
customModules,
66+
requiresModuleApiPolyfill
6467
) {
6568
let parallelBabelInfo = {
6669
requireFile: require.resolve('./require-from-worker'),
@@ -71,6 +74,7 @@ function buildParalleizedBabelPlugin(
7174
projectConfig,
7275
parallelConfigs: pluginInfo.parallelConfigs,
7376
modules: Object.assign({}, customModules, INLINE_PRECOMPILE_MODULES),
77+
requiresModuleApiPolyfill,
7478
},
7579
};
7680

@@ -199,12 +203,6 @@ function initializeEmberENV(templateCompiler, EmberENV) {
199203
}
200204
}
201205

202-
function template(templateCompiler, string, options) {
203-
let precompiled = templateCompiler.precompile(string, options);
204-
205-
return 'Ember.HTMLBars.template(' + precompiled + ')';
206-
}
207-
208206
function setup(pluginInfo, options) {
209207
let projectConfig = options.projectConfig || {};
210208
let templateCompilerPath = options.templateCompilerPath;
@@ -261,7 +259,7 @@ function setup(pluginInfo, options) {
261259
{
262260
precompile,
263261
isProduction: options.isProduction,
264-
ensureModuleApiPolyfill: true,
262+
ensureModuleApiPolyfill: options.requiresModuleApiPolyfill,
265263
modules: Object.assign({}, options.modules, INLINE_PRECOMPILE_MODULES),
266264
},
267265
'ember-cli-htmlbars:inline-precompile',
@@ -355,7 +353,6 @@ function setupPlugins(wrappers) {
355353
module.exports = {
356354
buildOptions,
357355
initializeEmberENV,
358-
template,
359356
setup,
360357
makeCacheKey,
361358
setupPlugins,

node-tests/addon-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ describe('ember-cli-htmlbars addon', function () {
3434
project,
3535
parent: project,
3636
ui: this.ui,
37+
_requiresModuleApiPolyfill: true,
3738
});
3839

3940
project.addons.push(this.addon);

0 commit comments

Comments
 (0)