Skip to content

Commit

Permalink
Merge pull request #1653 from embroider-build/virtual-implicit-modules
Browse files Browse the repository at this point in the history
Refactor embroider-implicit-modules export pojo
  • Loading branch information
ef4 authored Jan 9, 2024
2 parents a74ae69 + d5b1b17 commit 289f83d
Show file tree
Hide file tree
Showing 15 changed files with 750 additions and 74 deletions.
30 changes: 22 additions & 8 deletions packages/compat/src/compat-app-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1285,11 +1285,16 @@ export class CompatAppBuilder {
let amdModules = nonFastboot.map(file => this.importPaths(appFiles, file));
let fastbootOnlyAmdModules = fastboot.map(file => this.importPaths(appFiles, file));

// this is a backward-compatibility feature: addons can force inclusion of
// modules.
eagerModules.push('./-embroider-implicit-modules.js');

let params = { amdModules, fastbootOnlyAmdModules, lazyRoutes, lazyEngines, eagerModules, styles };
let params = {
amdModules,
fastbootOnlyAmdModules,
lazyRoutes,
lazyEngines,
eagerModules,
styles,
// this is a backward-compatibility feature: addons can force inclusion of modules.
defineModulesFrom: './-embroider-implicit-modules.js',
};
if (entryParams) {
Object.assign(params, entryParams);
}
Expand Down Expand Up @@ -1351,9 +1356,6 @@ export class CompatAppBuilder {
];

let amdModules: { runtime: string; buildtime: string }[] = [];
// this is a backward-compatibility feature: addons can force inclusion of
// test support modules.
eagerModules.push('./-embroider-implicit-test-modules.js');

for (let relativePath of engine.tests) {
amdModules.push(this.importPaths(engine, relativePath));
Expand All @@ -1363,6 +1365,8 @@ export class CompatAppBuilder {
amdModules,
eagerModules,
testSuffix: true,
// this is a backward-compatibility feature: addons can force inclusion of test support modules.
defineModulesFrom: './-embroider-implicit-test-modules.js',
});

asset = {
Expand Down Expand Up @@ -1400,6 +1404,15 @@ let d = w.define;
}
{{/if}}
{{#if defineModulesFrom ~}}
import implicitModules from "{{js-string-escape defineModulesFrom}}";
for(const [name, module] of Object.entries(implicitModules)) {
d(name, function() { return module });
}
{{/if}}
{{#each eagerModules as |eagerModule| ~}}
i("{{js-string-escape eagerModule}}");
{{/each}}
Expand Down Expand Up @@ -1471,6 +1484,7 @@ if (!runningTests) {
`) as (params: {
amdModules: { runtime: string; buildtime: string }[];
fastbootOnlyAmdModules?: { runtime: string; buildtime: string }[];
defineModulesFrom?: string;
eagerModules?: string[];
autoRun?: boolean;
appBoot?: string;
Expand Down
85 changes: 53 additions & 32 deletions packages/core/src/virtual-content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,8 @@ function renderImplicitModules(
throw new Error(`bug: saw special implicit modules import in non-ember package at ${fromFile}`);
}

let lazyModules: { runtime: string; buildtime: string }[] = [];
let eagerModules: string[] = [];
let ownModules: { runtime: string; buildtime: string }[] = [];
let dependencyModules: string[] = [];

let deps = pkg.dependencies.sort(orderAddons);

Expand Down Expand Up @@ -260,7 +260,7 @@ function renderImplicitModules(
runtime = renamedModules[runtimeRenameLookup];
}
runtime = runtime.split(sep).join('/');
lazyModules.push({
ownModules.push({
runtime,
buildtime: posix.join(packageName, name),
});
Expand All @@ -269,22 +269,34 @@ function renderImplicitModules(
// we don't recurse across an engine boundary. Engines import their own
// implicit-modules.
if (!dep.isEngine()) {
eagerModules.push(posix.join(dep.name, `-embroider-${type}.js`));
dependencyModules.push(posix.join(dep.name, `-embroider-${type}.js`));
}
}
return implicitModulesTemplate({ lazyModules, eagerModules });
return implicitModulesTemplate({ ownModules, dependencyModules });
}

const implicitModulesTemplate = compile(`
import { importSync as i } from '@embroider/macros';
let d = window.define;
{{#each lazyModules as |module|}}
d("{{js-string-escape module.runtime}}", function(){ return i("{{js-string-escape module.buildtime}}");});
{{#each dependencyModules as |module index|}}
import dep{{index}} from "{{js-string-escape module}}";
{{/each}}
{{#each eagerModules as |module|}}
import "{{js-string-escape module}}";
{{#each ownModules as |module index|}}
import * as own{{index}} from "{{js-string-escape module.buildtime}}";
{{/each}}
`) as (params: { eagerModules: string[]; lazyModules: { runtime: string; buildtime: string }[] }) => string;
export default Object.assign({},
{{#each dependencyModules as |module index|}}
dep{{index}},
{{/each}}
{
{{#each ownModules as |module index|}}
"{{js-string-escape module.runtime}}": own{{index}},
{{/each}}
}
);
`) as (params: { dependencyModules: string[]; ownModules: { runtime: string; buildtime: string }[] }) => string;

// meta['renamed-modules'] has mapping from classic filename to real filename.
// This takes that and converts it to the inverst mapping from real import path
Expand Down Expand Up @@ -315,24 +327,33 @@ function orderAddons(depA: Package, depB: Package): number {
}

const renderCJSExternalShim = compile(`
{{#if (eq moduleName "require")}}
const m = window.requirejs;
{{else}}
const m = window.require("{{{js-string-escape moduleName}}}");
{{/if}}
{{!-
There are plenty of hand-written AMD defines floating around
that lack this, and they will break when other build systems
encounter them.
As far as I can tell, Ember's loader was already treating this
case as a module, so in theory we aren't breaking anything by
marking it as such when other packagers come looking.
todo: get review on this part.
-}}
if (m.default && !m.__esModule) {
m.__esModule = true;
}
module.exports = m;
module.exports = new Proxy({}, {
get(target, prop) {
{{!- our proxy always presents as ES module so that we can intercept "get('default')" -}}
if (prop === '__esModule') {
return true;
}
{{#if (eq moduleName "require")}}
const m = window.requirejs;
{{else}}
const m = window.require("{{{js-string-escape moduleName}}}");
{{/if}}
{{!-
There are plenty of hand-written AMD defines floating around
that lack an __esModule declaration.
As far as I can tell, Ember's loader was already treating the Boolean(m.default)===true
case as a module, so in theory we aren't breaking anything by
treating it as such when other packagers come looking.
-}}
if (prop === 'default' && !m.__esModule && !m.default) {
return m;
}
return m[prop];
}
});
`) as (params: { moduleName: string }) => string;
Loading

0 comments on commit 289f83d

Please sign in to comment.