@embroider/compat 3.5.2-unstable.9f1e74e → 3.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +13 -13
  3. package/src/audit/babel-visitor.js +3 -5
  4. package/src/audit/babel-visitor.js.map +1 -1
  5. package/src/audit/build.js.map +1 -1
  6. package/src/audit-cli.js.map +1 -1
  7. package/src/audit.d.ts +54 -6
  8. package/src/audit.js +277 -93
  9. package/src/audit.js.map +1 -1
  10. package/src/babel-plugin-adjust-imports.d.ts +1 -2
  11. package/src/babel-plugin-adjust-imports.js +1 -1
  12. package/src/babel-plugin-adjust-imports.js.map +1 -1
  13. package/src/build-compat-addon.js.map +1 -1
  14. package/src/compat-adapters/@ember/test-waiters.js.map +1 -1
  15. package/src/compat-adapters/@ember-data/debug.d.ts +6 -0
  16. package/src/compat-adapters/@ember-data/debug.js +22 -0
  17. package/src/compat-adapters/@ember-data/debug.js.map +1 -0
  18. package/src/compat-adapters/@ember-data/store.d.ts +5 -1
  19. package/src/compat-adapters/@ember-data/store.js +15 -3
  20. package/src/compat-adapters/@ember-data/store.js.map +1 -1
  21. package/src/compat-adapters/ember-asset-loader.js.map +1 -1
  22. package/src/compat-adapters/ember-cli-babel.js.map +1 -1
  23. package/src/compat-adapters/ember-cli-fastboot.js.map +1 -1
  24. package/src/compat-adapters/ember-cli-mirage.js.map +1 -1
  25. package/src/compat-adapters/ember-composable-helpers.js.map +1 -1
  26. package/src/compat-adapters/ember-data.js.map +1 -1
  27. package/src/compat-adapters/ember-engines.js.map +1 -1
  28. package/src/compat-adapters/ember-macro-helpers.js.map +1 -1
  29. package/src/compat-adapters/ember-scroll-modifiers.js.map +1 -1
  30. package/src/compat-adapters/ember-source.js.map +1 -1
  31. package/src/compat-adapters/ember-svg-jar.js.map +1 -1
  32. package/src/compat-addons.js.map +1 -1
  33. package/src/compat-app-builder.d.ts +31 -9
  34. package/src/compat-app-builder.js +858 -75
  35. package/src/compat-app-builder.js.map +1 -1
  36. package/src/compat-app.d.ts +8 -2
  37. package/src/compat-app.js +57 -54
  38. package/src/compat-app.js.map +1 -1
  39. package/src/compat-utils.js.map +1 -1
  40. package/src/dasherize-component-name.js.map +1 -1
  41. package/src/default-pipeline.d.ts +2 -2
  42. package/src/default-pipeline.js +1 -22
  43. package/src/default-pipeline.js.map +1 -1
  44. package/src/dependency-rules.js.map +1 -1
  45. package/src/detect-babel-plugins.js.map +1 -1
  46. package/src/detect-compact-reexports.js.map +1 -1
  47. package/src/dummy-package.js.map +1 -1
  48. package/src/empty-package-tree.js.map +1 -1
  49. package/src/get-real-addon.js.map +1 -1
  50. package/src/hbs-to-js-broccoli-plugin.js.map +1 -1
  51. package/src/index.d.ts +1 -1
  52. package/src/index.js +1 -2
  53. package/src/index.js.map +1 -1
  54. package/src/merges.js.map +1 -1
  55. package/src/options.d.ts +0 -1
  56. package/src/options.js +0 -1
  57. package/src/options.js.map +1 -1
  58. package/src/prepare-htmlbars-ast-plugins.js.map +1 -1
  59. package/src/rename-require-plugin.js.map +1 -1
  60. package/src/resolver-transform.js +0 -3
  61. package/src/resolver-transform.js.map +1 -1
  62. package/src/rewrite-addon-tree.js.map +1 -1
  63. package/src/smoosh-package-json.js.map +1 -1
  64. package/src/snitch.js.map +1 -1
  65. package/src/standalone-addon-build.js.map +1 -1
  66. package/src/sync-dir.js.map +1 -1
  67. package/src/synthesize-template-only-components.js.map +1 -1
  68. package/src/v1-addon.js.map +1 -1
  69. package/src/v1-appboot.js.map +1 -1
  70. package/src/v1-config.d.ts +8 -0
  71. package/src/v1-config.js +51 -1
  72. package/src/v1-config.js.map +1 -1
  73. package/src/v1-instance-cache.js.map +1 -1
  74. package/src/compat-adapters/ember-fetch.d.ts +0 -5
  75. package/src/compat-adapters/ember-fetch.js +0 -19
  76. package/src/compat-adapters/ember-fetch.js.map +0 -1
  77. package/src/content-for-config.d.ts +0 -11
  78. package/src/content-for-config.js +0 -66
  79. package/src/content-for-config.js.map +0 -1
  80. package/src/http-audit.d.ts +0 -13
  81. package/src/http-audit.js +0 -46
  82. package/src/http-audit.js.map +0 -1
  83. package/src/module-visitor.d.ts +0 -53
  84. package/src/module-visitor.js +0 -286
  85. package/src/module-visitor.js.map +0 -1
@@ -1,46 +1,78 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
2
18
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
19
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
20
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
21
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
22
  return c > 3 && r && Object.defineProperty(target, key, r), r;
7
23
  };
24
+ var __importStar = (this && this.__importStar) || function (mod) {
25
+ if (mod && mod.__esModule) return mod;
26
+ var result = {};
27
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
28
+ __setModuleDefault(result, mod);
29
+ return result;
30
+ };
8
31
  var __importDefault = (this && this.__importDefault) || function (mod) {
9
32
  return (mod && mod.__esModule) ? mod : { "default": mod };
10
33
  };
11
34
  Object.defineProperty(exports, "__esModule", { value: true });
12
35
  exports.CompatAppBuilder = void 0;
13
36
  const core_1 = require("@embroider/core");
37
+ const walk_sync_1 = __importDefault(require("walk-sync"));
14
38
  const path_1 = require("path");
15
39
  const dependency_rules_1 = require("./dependency-rules");
16
40
  const flatMap_1 = __importDefault(require("lodash/flatMap"));
41
+ const sortBy_1 = __importDefault(require("lodash/sortBy"));
42
+ const flatten_1 = __importDefault(require("lodash/flatten"));
43
+ const partition_1 = __importDefault(require("lodash/partition"));
17
44
  const mergeWith_1 = __importDefault(require("lodash/mergeWith"));
18
45
  const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
46
+ const resolve_1 = require("resolve");
19
47
  const bind_decorator_1 = __importDefault(require("bind-decorator"));
20
48
  const fs_extra_1 = require("fs-extra");
49
+ const ember_html_1 = require("@embroider/core/src/ember-html");
21
50
  const portable_babel_config_1 = require("@embroider/core/src/portable-babel-config");
22
51
  const app_files_1 = require("@embroider/core/src/app-files");
23
52
  const portable_1 = require("@embroider/core/src/portable");
53
+ const assert_never_1 = __importDefault(require("assert-never"));
24
54
  const typescript_memoize_1 = require("typescript-memoize");
25
55
  const path_2 = require("path");
26
- const resolve_1 = __importDefault(require("resolve"));
56
+ const resolve_2 = __importDefault(require("resolve"));
27
57
  const fs_extra_2 = require("fs-extra");
28
58
  const node_1 = require("@embroider/macros/src/node");
59
+ const fast_sourcemap_concat_1 = __importDefault(require("fast-sourcemap-concat"));
29
60
  const escape_string_regexp_1 = __importDefault(require("escape-string-regexp"));
30
61
  const sync_dir_1 = require("./sync-dir");
31
62
  // This exists during the actual broccoli build step. As opposed to CompatApp,
32
63
  // which also exists during pipeline-construction time.
33
64
  class CompatAppBuilder {
34
- constructor(root, origAppPackage, appPackageWithMovedDeps, options, compatApp, configTree, contentForTree, synthVendor, synthStyles) {
65
+ constructor(root, origAppPackage, appPackageWithMovedDeps, options, compatApp, configTree, synthVendor, synthStyles) {
35
66
  this.root = root;
36
67
  this.origAppPackage = origAppPackage;
37
68
  this.appPackageWithMovedDeps = appPackageWithMovedDeps;
38
69
  this.options = options;
39
70
  this.compatApp = compatApp;
40
71
  this.configTree = configTree;
41
- this.contentForTree = contentForTree;
42
72
  this.synthVendor = synthVendor;
43
73
  this.synthStyles = synthStyles;
74
+ // for each relativePath, an Asset we have already emitted
75
+ this.assets = new Map();
44
76
  this.firstBuild = true;
45
77
  }
46
78
  fastbootJSSrcDir() {
@@ -49,6 +81,54 @@ class CompatAppBuilder {
49
81
  return target;
50
82
  }
51
83
  }
84
+ extractAssets(treePaths) {
85
+ let assets = [];
86
+ // Everything in our traditional public tree is an on-disk asset
87
+ if (treePaths.publicTree) {
88
+ walk_sync_1.default
89
+ .entries(treePaths.publicTree, {
90
+ directories: false,
91
+ })
92
+ .forEach(entry => {
93
+ assets.push({
94
+ kind: 'on-disk',
95
+ relativePath: entry.relativePath,
96
+ sourcePath: entry.fullPath,
97
+ mtime: entry.mtime,
98
+ size: entry.size,
99
+ });
100
+ });
101
+ }
102
+ // ember-cli traditionally outputs a dummy testem.js file to prevent
103
+ // spurious errors when running tests under "ember s".
104
+ if (this.compatApp.shouldBuildTests) {
105
+ let testemAsset = this.findTestemAsset();
106
+ if (testemAsset) {
107
+ assets.push(testemAsset);
108
+ }
109
+ }
110
+ for (let asset of this.emberEntrypoints(treePaths.htmlTree)) {
111
+ assets.push(asset);
112
+ }
113
+ return assets;
114
+ }
115
+ findTestemAsset() {
116
+ let sourcePath;
117
+ try {
118
+ sourcePath = (0, resolve_1.sync)('ember-cli/lib/broccoli/testem.js', { basedir: this.root });
119
+ }
120
+ catch (err) { }
121
+ if (sourcePath) {
122
+ let stat = (0, fs_extra_1.statSync)(sourcePath);
123
+ return {
124
+ kind: 'on-disk',
125
+ relativePath: 'testem.js',
126
+ sourcePath,
127
+ mtime: stat.mtime.getTime(),
128
+ size: stat.size,
129
+ };
130
+ }
131
+ }
52
132
  activeAddonChildren(pkg) {
53
133
  let result = pkg.dependencies.filter(this.isActiveAddon).filter(
54
134
  // When looking for child addons, we want to ignore 'peerDependencies' of
@@ -97,19 +177,43 @@ class CompatAppBuilder {
97
177
  // For TS, we defer to ember-cli-babel, and the setting for
98
178
  // "enableTypescriptTransform" can be set with and without
99
179
  // ember-cli-typescript
100
- return ['.wasm', '.mjs', '.js', '.json', '.ts', '.hbs', '.hbs.js', '.gjs', '.gts'];
180
+ return ['.wasm', '.mjs', '.js', '.json', '.ts', '.hbs', '.hbs.js'];
101
181
  }
102
- addEmberEntrypoints(htmlTreePath) {
103
- let classicEntrypoints = ['index.html', 'tests/index.html'];
182
+ *emberEntrypoints(htmlTreePath) {
183
+ let classicEntrypoints = [
184
+ { entrypoint: 'index.html', includeTests: false },
185
+ { entrypoint: 'tests/index.html', includeTests: true },
186
+ ];
104
187
  if (!this.compatApp.shouldBuildTests) {
105
188
  classicEntrypoints.pop();
106
189
  }
107
- for (let entrypoint of classicEntrypoints) {
190
+ for (let { entrypoint, includeTests } of classicEntrypoints) {
108
191
  let sourcePath = (0, path_2.join)(htmlTreePath, entrypoint);
109
- let rewrittenAppPath = (0, path_2.join)(this.root, entrypoint);
110
- (0, fs_extra_1.writeFileSync)(rewrittenAppPath, (0, fs_extra_1.readFileSync)(sourcePath));
192
+ let stats = (0, fs_extra_1.statSync)(sourcePath);
193
+ let asset = {
194
+ kind: 'ember',
195
+ relativePath: entrypoint,
196
+ includeTests,
197
+ sourcePath,
198
+ mtime: stats.mtime.getTime(),
199
+ size: stats.size,
200
+ rootURL: this.rootURL(),
201
+ prepare: (dom) => {
202
+ let scripts = [...dom.window.document.querySelectorAll('script')];
203
+ let styles = [...dom.window.document.querySelectorAll('link[rel*="stylesheet"]')];
204
+ return {
205
+ javascript: this.compatApp.findAppScript(scripts, entrypoint),
206
+ styles: this.compatApp.findAppStyles(styles, entrypoint),
207
+ implicitScripts: this.compatApp.findVendorScript(scripts, entrypoint),
208
+ implicitStyles: this.compatApp.findVendorStyles(styles, entrypoint),
209
+ testJavascript: this.compatApp.findTestScript(scripts),
210
+ implicitTestScripts: this.compatApp.findTestSupportScript(scripts),
211
+ implicitTestStyles: this.compatApp.findTestSupportStyles(styles),
212
+ };
213
+ },
214
+ };
215
+ yield asset;
111
216
  }
112
- return classicEntrypoints;
113
217
  }
114
218
  modulePrefix() {
115
219
  return this.configTree.readConfig().modulePrefix;
@@ -129,6 +233,10 @@ class CompatAppBuilder {
129
233
  resolverConfig(engines) {
130
234
  let renamePackages = Object.assign({}, ...this.allActiveAddons.map(dep => dep.meta['renamed-packages']));
131
235
  let renameModules = Object.assign({}, ...this.allActiveAddons.map(dep => dep.meta['renamed-modules']));
236
+ let activeAddons = {};
237
+ for (let addon of this.allActiveAddons) {
238
+ activeAddons[addon.name] = addon.root;
239
+ }
132
240
  let options = {
133
241
  staticHelpers: this.options.staticHelpers,
134
242
  staticModifiers: this.options.staticModifiers,
@@ -137,6 +245,7 @@ class CompatAppBuilder {
137
245
  };
138
246
  let config = {
139
247
  // this part is the base ModuleResolverOptions as required by @embroider/core
248
+ activeAddons,
140
249
  renameModules,
141
250
  renamePackages,
142
251
  resolvableExtensions: this.resolvableExtensions(),
@@ -148,34 +257,118 @@ class CompatAppBuilder {
148
257
  root: (0, fs_extra_1.realpathSync)(index === 0 ? this.root : appFiles.engine.package.root),
149
258
  fastbootFiles: appFiles.fastbootFiles,
150
259
  activeAddons: [...appFiles.engine.addons]
151
- .map(([addon, canResolveFromFile]) => ({
152
- name: addon.name,
153
- root: addon.root,
154
- canResolveFromFile,
260
+ .map(a => ({
261
+ name: a.name,
262
+ root: a.root,
155
263
  }))
156
264
  // the traditional order is the order in which addons will run, such
157
265
  // that the last one wins. Our resolver's order is the order to
158
266
  // search, so first one wins.
159
267
  .reverse(),
160
- isLazy: appFiles.engine.package.isLazyEngine(),
161
268
  })),
162
269
  amdCompatibility: this.options.amdCompatibility,
163
270
  // this is the additional stufff that @embroider/compat adds on top to do
164
271
  // global template resolving
165
272
  modulePrefix: this.modulePrefix(),
166
- splitAtRoutes: this.options.splitAtRoutes,
167
273
  podModulePrefix: this.podModulePrefix(),
168
274
  activePackageRules: this.activeRules(),
169
275
  options,
170
- autoRun: this.compatApp.autoRun,
171
- staticAppPaths: this.options.staticAppPaths,
172
276
  };
173
277
  return config;
174
278
  }
279
+ scriptPriority(pkg) {
280
+ switch (pkg.name) {
281
+ case 'loader.js':
282
+ return 0;
283
+ case 'ember-source':
284
+ return 10;
285
+ default:
286
+ return 1000;
287
+ }
288
+ }
175
289
  get resolvableExtensionsPattern() {
176
290
  return (0, core_1.extensionsPattern)(this.resolvableExtensions());
177
291
  }
178
- async babelConfig(resolverConfig) {
292
+ impliedAssets(type, engine, emberENV) {
293
+ let result = this.impliedAddonAssets(type, engine).map((sourcePath) => {
294
+ let stats = (0, fs_extra_1.statSync)(sourcePath);
295
+ return {
296
+ kind: 'on-disk',
297
+ relativePath: (0, core_1.explicitRelative)(this.root, sourcePath),
298
+ sourcePath,
299
+ mtime: stats.mtimeMs,
300
+ size: stats.size,
301
+ };
302
+ });
303
+ if (type === 'implicit-scripts') {
304
+ result.unshift({
305
+ kind: 'in-memory',
306
+ relativePath: '_testing_prefix_.js',
307
+ source: `var runningTests=false;`,
308
+ });
309
+ result.unshift({
310
+ kind: 'in-memory',
311
+ relativePath: '_ember_env_.js',
312
+ source: `window.EmberENV={ ...(window.EmberENV || {}), ...${JSON.stringify(emberENV, null, 2)} };`,
313
+ });
314
+ result.push({
315
+ kind: 'in-memory',
316
+ relativePath: '_loader_.js',
317
+ source: `loader.makeDefaultExport=false;`,
318
+ });
319
+ }
320
+ if (type === 'implicit-test-scripts') {
321
+ // this is the traditional test-support-suffix.js
322
+ result.push({
323
+ kind: 'in-memory',
324
+ relativePath: '_testing_suffix_.js',
325
+ source: `
326
+ var runningTests=true;
327
+ if (typeof Testem !== 'undefined' && (typeof QUnit !== 'undefined' || typeof Mocha !== 'undefined')) {
328
+ Testem.hookIntoTestFramework();
329
+ }`,
330
+ });
331
+ // whether or not anybody was actually using @embroider/macros
332
+ // explicitly as an addon, we ensure its test-support file is always
333
+ // present.
334
+ if (!result.find(s => s.kind === 'on-disk' && s.sourcePath.endsWith('embroider-macros-test-support.js'))) {
335
+ result.unshift({
336
+ kind: 'on-disk',
337
+ sourcePath: require.resolve('@embroider/macros/src/vendor/embroider-macros-test-support'),
338
+ mtime: 0,
339
+ size: 0,
340
+ relativePath: 'embroider-macros-test-support.js',
341
+ });
342
+ }
343
+ }
344
+ return result;
345
+ }
346
+ impliedAddonAssets(type, { engine }) {
347
+ let result = [];
348
+ for (let addon of (0, sortBy_1.default)(Array.from(engine.addons), this.scriptPriority.bind(this))) {
349
+ let implicitScripts = addon.meta[type];
350
+ if (implicitScripts) {
351
+ let styles = [];
352
+ let options = { basedir: addon.root };
353
+ for (let mod of implicitScripts) {
354
+ if (type === 'implicit-styles') {
355
+ // exclude engines because they will handle their own css importation
356
+ if (!addon.isLazyEngine()) {
357
+ styles.push(resolve_2.default.sync(mod, options));
358
+ }
359
+ }
360
+ else {
361
+ result.push(resolve_2.default.sync(mod, options));
362
+ }
363
+ }
364
+ if (styles.length) {
365
+ result = [...styles, ...result];
366
+ }
367
+ }
368
+ }
369
+ return result;
370
+ }
371
+ babelConfig(resolverConfig) {
179
372
  let babel = (0, cloneDeep_1.default)(this.compatApp.babelConfig());
180
373
  if (!babel.plugins) {
181
374
  babel.plugins = [];
@@ -185,10 +378,7 @@ class CompatAppBuilder {
185
378
  babel.plugins.push(require.resolve('@babel/plugin-syntax-dynamic-import'));
186
379
  // https://github.com/webpack/webpack/issues/12154
187
380
  babel.plugins.push(require.resolve('./rename-require-plugin'));
188
- babel.plugins.push([
189
- require.resolve('babel-plugin-ember-template-compilation'),
190
- await this.etcOptions(resolverConfig),
191
- ]);
381
+ babel.plugins.push([require.resolve('babel-plugin-ember-template-compilation'), this.etcOptions(resolverConfig)]);
192
382
  // this is @embroider/macros configured for full stage3 resolution
193
383
  babel.plugins.push(...this.compatApp.macrosConfig.babelPluginConfig());
194
384
  let colocationOptions = {
@@ -240,6 +430,107 @@ class CompatAppBuilder {
240
430
  addCachablePlugin(portable.config);
241
431
  return portable;
242
432
  }
433
+ insertEmberApp(asset, appFiles, prepared, emberENV) {
434
+ let html = asset.html;
435
+ if (this.fastbootConfig) {
436
+ // ignore scripts like ember-cli-livereload.js which are not really associated with
437
+ // "the app".
438
+ let ignoreScripts = html.dom.window.document.querySelectorAll('script');
439
+ ignoreScripts.forEach(script => {
440
+ script.setAttribute('data-fastboot-ignore', '');
441
+ });
442
+ }
443
+ // our tests entrypoint already includes a correct module dependency on the
444
+ // app, so we only insert the app when we're not inserting tests
445
+ if (!asset.fileAsset.includeTests) {
446
+ let appJS = this.topAppJSAsset(appFiles, prepared);
447
+ html.insertScriptTag(html.javascript, appJS.relativePath, { type: 'module' });
448
+ }
449
+ if (this.fastbootConfig) {
450
+ // any extra fastboot app files get inserted into our html.javascript
451
+ // section, after the app has been inserted.
452
+ for (let script of this.fastbootConfig.extraAppFiles) {
453
+ html.insertScriptTag(html.javascript, script, { tag: 'fastboot-script' });
454
+ }
455
+ }
456
+ html.insertStyleLink(html.styles, `assets/${this.origAppPackage.name}.css`);
457
+ const parentEngine = appFiles.find(e => !e.engine.parent);
458
+ let vendorJS = this.implicitScriptsAsset(prepared, parentEngine, emberENV);
459
+ if (vendorJS) {
460
+ html.insertScriptTag(html.implicitScripts, vendorJS.relativePath);
461
+ }
462
+ if (this.fastbootConfig) {
463
+ // any extra fastboot vendor files get inserted into our
464
+ // html.implicitScripts section, after the regular implicit script
465
+ // (vendor.js) have been inserted.
466
+ for (let script of this.fastbootConfig.extraVendorFiles) {
467
+ html.insertScriptTag(html.implicitScripts, script, { tag: 'fastboot-script' });
468
+ }
469
+ }
470
+ let implicitStyles = this.implicitStylesAsset(prepared, parentEngine);
471
+ if (implicitStyles) {
472
+ html.insertStyleLink(html.implicitStyles, implicitStyles.relativePath);
473
+ }
474
+ if (!asset.fileAsset.includeTests) {
475
+ return;
476
+ }
477
+ // Test-related assets happen below this point
478
+ let testJS = this.testJSEntrypoint(appFiles, prepared);
479
+ html.insertScriptTag(html.testJavascript, testJS.relativePath, { type: 'module' });
480
+ let implicitTestScriptsAsset = this.implicitTestScriptsAsset(prepared, parentEngine);
481
+ if (implicitTestScriptsAsset) {
482
+ html.insertScriptTag(html.implicitTestScripts, implicitTestScriptsAsset.relativePath);
483
+ }
484
+ let implicitTestStylesAsset = this.implicitTestStylesAsset(prepared, parentEngine);
485
+ if (implicitTestStylesAsset) {
486
+ html.insertStyleLink(html.implicitTestStyles, implicitTestStylesAsset.relativePath);
487
+ }
488
+ }
489
+ implicitScriptsAsset(prepared, application, emberENV) {
490
+ let asset = prepared.get('assets/vendor.js');
491
+ if (!asset) {
492
+ let implicitScripts = this.impliedAssets('implicit-scripts', application, emberENV);
493
+ if (implicitScripts.length > 0) {
494
+ asset = new ConcatenatedAsset('assets/vendor.js', implicitScripts, this.resolvableExtensionsPattern);
495
+ prepared.set(asset.relativePath, asset);
496
+ }
497
+ }
498
+ return asset;
499
+ }
500
+ implicitStylesAsset(prepared, application) {
501
+ let asset = prepared.get('assets/vendor.css');
502
+ if (!asset) {
503
+ let implicitStyles = this.impliedAssets('implicit-styles', application);
504
+ if (implicitStyles.length > 0) {
505
+ // we reverse because we want the synthetic vendor style at the top
506
+ asset = new ConcatenatedAsset('assets/vendor.css', implicitStyles.reverse(), this.resolvableExtensionsPattern);
507
+ prepared.set(asset.relativePath, asset);
508
+ }
509
+ }
510
+ return asset;
511
+ }
512
+ implicitTestScriptsAsset(prepared, application) {
513
+ let testSupportJS = prepared.get('assets/test-support.js');
514
+ if (!testSupportJS) {
515
+ let implicitTestScripts = this.impliedAssets('implicit-test-scripts', application);
516
+ if (implicitTestScripts.length > 0) {
517
+ testSupportJS = new ConcatenatedAsset('assets/test-support.js', implicitTestScripts, this.resolvableExtensionsPattern);
518
+ prepared.set(testSupportJS.relativePath, testSupportJS);
519
+ }
520
+ }
521
+ return testSupportJS;
522
+ }
523
+ implicitTestStylesAsset(prepared, application) {
524
+ let asset = prepared.get('assets/test-support.css');
525
+ if (!asset) {
526
+ let implicitTestStyles = this.impliedAssets('implicit-test-styles', application);
527
+ if (implicitTestStyles.length > 0) {
528
+ asset = new ConcatenatedAsset('assets/test-support.css', implicitTestStyles, this.resolvableExtensionsPattern);
529
+ prepared.set(asset.relativePath, asset);
530
+ }
531
+ }
532
+ return asset;
533
+ }
243
534
  // recurse to find all active addons that don't cross an engine boundary.
244
535
  // Inner engines themselves will be returned, but not those engines' children.
245
536
  // The output set's insertion order is the proper ember-cli compatible
@@ -249,31 +540,22 @@ class CompatAppBuilder {
249
540
  if (!child.isEngine()) {
250
541
  this.findActiveAddons(child, engine, true);
251
542
  }
252
- let canResolveFrom;
253
- if (pkg === this.appPackageWithMovedDeps) {
254
- // we want canResolveFrom to always be a rewritten package path, and our
255
- // app's package is not rewritten yet here.
256
- canResolveFrom = (0, path_1.resolve)(this.root, 'package.json');
257
- }
258
- else {
259
- // whereas our addons are already moved
260
- canResolveFrom = (0, path_1.resolve)(pkg.root, 'package.json');
261
- }
262
- engine.addons.set(child, canResolveFrom);
543
+ engine.addons.add(child);
263
544
  }
264
545
  // ensure addons are applied in the correct order, if set (via @embroider/compat/v1-addon)
265
546
  if (!isChild) {
266
- engine.addons = new Map([...engine.addons].sort(([a], [b]) => {
547
+ engine.addons = new Set([...engine.addons].sort((a, b) => {
267
548
  return (a.meta['order-index'] || 0) - (b.meta['order-index'] || 0);
268
549
  }));
269
550
  }
270
551
  }
271
- partitionEngines() {
552
+ partitionEngines(appJSPath) {
272
553
  let queue = [
273
554
  {
274
555
  package: this.appPackageWithMovedDeps,
275
- addons: new Map(),
276
- isApp: true,
556
+ addons: new Set(),
557
+ parent: undefined,
558
+ sourcePath: appJSPath,
277
559
  modulePrefix: this.modulePrefix(),
278
560
  appRelativePath: '.',
279
561
  },
@@ -286,13 +568,14 @@ class CompatAppBuilder {
286
568
  break;
287
569
  }
288
570
  this.findActiveAddons(current.package, current);
289
- for (let addon of current.addons.keys()) {
571
+ for (let addon of current.addons) {
290
572
  if (addon.isEngine() && !seenEngines.has(addon)) {
291
573
  seenEngines.add(addon);
292
574
  queue.push({
293
575
  package: addon,
294
- addons: new Map(),
295
- isApp: !current,
576
+ addons: new Set(),
577
+ parent: current,
578
+ sourcePath: addon.root,
296
579
  modulePrefix: addon.name,
297
580
  appRelativePath: (0, core_1.explicitRelative)(this.root, addon.root),
298
581
  });
@@ -318,8 +601,8 @@ class CompatAppBuilder {
318
601
  updateAppJS(appJSPath) {
319
602
  var _a;
320
603
  if (!this.engines) {
321
- this.engines = this.partitionEngines().map(engine => {
322
- if (engine.isApp) {
604
+ this.engines = this.partitionEngines(appJSPath).map(engine => {
605
+ if (engine.sourcePath === appJSPath) {
323
606
  // this is the app. We have more to do for the app than for other
324
607
  // engines.
325
608
  let fastbootSync;
@@ -341,7 +624,7 @@ class CompatAppBuilder {
341
624
  // their files, not doing any actual copying or building.
342
625
  return {
343
626
  engine,
344
- appSync: new sync_dir_1.SyncDir(engine.package.root, undefined),
627
+ appSync: new sync_dir_1.SyncDir(engine.sourcePath, undefined),
345
628
  // AFAIK, we've never supported a fastboot overlay directory in an
346
629
  // engine. But if we do need that, it would go here.
347
630
  fastbootSync: undefined,
@@ -355,13 +638,164 @@ class CompatAppBuilder {
355
638
  }
356
639
  return this.engines.map(({ engine, appSync, fastbootSync }) => {
357
640
  var _a;
358
- return new app_files_1.AppFiles(engine, appSync.files, (_a = fastbootSync === null || fastbootSync === void 0 ? void 0 : fastbootSync.files) !== null && _a !== void 0 ? _a : new Set(), this.resolvableExtensionsPattern, this.staticAppPathsPattern, this.podModulePrefix());
641
+ return new app_files_1.AppFiles(engine, appSync.files, (_a = fastbootSync === null || fastbootSync === void 0 ? void 0 : fastbootSync.files) !== null && _a !== void 0 ? _a : new Set(), this.resolvableExtensionsPattern, this.podModulePrefix());
359
642
  });
360
643
  }
361
- get staticAppPathsPattern() {
362
- if (this.options.staticAppPaths.length > 0) {
363
- return new RegExp('^(?:' + this.options.staticAppPaths.map(staticAppPath => (0, escape_string_regexp_1.default)(staticAppPath)).join('|') + ')(?:$|/)');
644
+ prepareAsset(asset, appFiles, prepared, emberENV) {
645
+ if (asset.kind === 'ember') {
646
+ let prior = this.assets.get(asset.relativePath);
647
+ let parsed;
648
+ if (prior && prior.kind === 'built-ember' && prior.parsedAsset.validFor(asset)) {
649
+ // we can reuse the parsed html
650
+ parsed = prior.parsedAsset;
651
+ parsed.html.clear();
652
+ }
653
+ else {
654
+ parsed = new ParsedEmberAsset(asset);
655
+ }
656
+ this.insertEmberApp(parsed, appFiles, prepared, emberENV);
657
+ prepared.set(asset.relativePath, new BuiltEmberAsset(parsed));
658
+ }
659
+ else {
660
+ prepared.set(asset.relativePath, asset);
661
+ }
662
+ }
663
+ prepareAssets(requestedAssets, appFiles, emberENV) {
664
+ let prepared = new Map();
665
+ for (let asset of requestedAssets) {
666
+ this.prepareAsset(asset, appFiles, prepared, emberENV);
667
+ }
668
+ return prepared;
669
+ }
670
+ assetIsValid(asset, prior) {
671
+ if (!prior) {
672
+ return false;
673
+ }
674
+ switch (asset.kind) {
675
+ case 'on-disk':
676
+ return prior.kind === 'on-disk' && prior.size === asset.size && prior.mtime === asset.mtime;
677
+ case 'in-memory':
678
+ return prior.kind === 'in-memory' && stringOrBufferEqual(prior.source, asset.source);
679
+ case 'built-ember':
680
+ return prior.kind === 'built-ember' && prior.source === asset.source;
681
+ case 'concatenated-asset':
682
+ return (prior.kind === 'concatenated-asset' &&
683
+ prior.sources.length === asset.sources.length &&
684
+ prior.sources.every((priorFile, index) => {
685
+ let newFile = asset.sources[index];
686
+ return this.assetIsValid(newFile, priorFile);
687
+ }));
688
+ }
689
+ }
690
+ updateOnDiskAsset(asset) {
691
+ let destination = (0, path_2.join)(this.root, asset.relativePath);
692
+ (0, fs_extra_2.ensureDirSync)((0, path_2.dirname)(destination));
693
+ (0, fs_extra_2.copySync)(asset.sourcePath, destination, { dereference: true });
694
+ }
695
+ updateInMemoryAsset(asset) {
696
+ let destination = (0, path_2.join)(this.root, asset.relativePath);
697
+ (0, fs_extra_2.ensureDirSync)((0, path_2.dirname)(destination));
698
+ (0, fs_extra_1.writeFileSync)(destination, asset.source, 'utf8');
699
+ }
700
+ updateBuiltEmberAsset(asset) {
701
+ let destination = (0, path_2.join)(this.root, asset.relativePath);
702
+ (0, fs_extra_2.ensureDirSync)((0, path_2.dirname)(destination));
703
+ (0, fs_extra_1.writeFileSync)(destination, asset.source, 'utf8');
704
+ }
705
+ async updateConcatenatedAsset(asset) {
706
+ let concat = new fast_sourcemap_concat_1.default({
707
+ outputFile: (0, path_2.join)(this.root, asset.relativePath),
708
+ mapCommentType: asset.relativePath.endsWith('.js') ? 'line' : 'block',
709
+ baseDir: this.root,
710
+ });
711
+ if (process.env.EMBROIDER_CONCAT_STATS) {
712
+ let MeasureConcat = (await Promise.resolve().then(() => __importStar(require('@embroider/core/src/measure-concat')))).default;
713
+ concat = new MeasureConcat(asset.relativePath, concat, this.root);
714
+ }
715
+ for (let source of asset.sources) {
716
+ switch (source.kind) {
717
+ case 'on-disk':
718
+ concat.addFile((0, core_1.explicitRelative)(this.root, source.sourcePath));
719
+ break;
720
+ case 'in-memory':
721
+ if (typeof source.source !== 'string') {
722
+ throw new Error(`attempted to concatenated a Buffer-backed in-memory asset`);
723
+ }
724
+ concat.addSpace(source.source);
725
+ break;
726
+ default:
727
+ (0, assert_never_1.default)(source);
728
+ }
729
+ }
730
+ await concat.end();
731
+ }
732
+ async updateAssets(requestedAssets, appFiles, emberENV) {
733
+ let assets = this.prepareAssets(requestedAssets, appFiles, emberENV);
734
+ for (let asset of assets.values()) {
735
+ if (this.assetIsValid(asset, this.assets.get(asset.relativePath))) {
736
+ continue;
737
+ }
738
+ (0, core_1.debug)('rebuilding %s', asset.relativePath);
739
+ switch (asset.kind) {
740
+ case 'on-disk':
741
+ this.updateOnDiskAsset(asset);
742
+ break;
743
+ case 'in-memory':
744
+ this.updateInMemoryAsset(asset);
745
+ break;
746
+ case 'built-ember':
747
+ this.updateBuiltEmberAsset(asset);
748
+ break;
749
+ case 'concatenated-asset':
750
+ await this.updateConcatenatedAsset(asset);
751
+ break;
752
+ default:
753
+ (0, assert_never_1.default)(asset);
754
+ }
755
+ }
756
+ for (let oldAsset of this.assets.values()) {
757
+ if (!assets.has(oldAsset.relativePath)) {
758
+ (0, fs_extra_1.unlinkSync)((0, path_2.join)(this.root, oldAsset.relativePath));
759
+ }
364
760
  }
761
+ this.assets = assets;
762
+ return [...assets.values()];
763
+ }
764
+ gatherAssets(inputPaths) {
765
+ // first gather all the assets out of addons
766
+ let assets = [];
767
+ for (let pkg of this.allActiveAddons) {
768
+ if (pkg.meta['public-assets']) {
769
+ for (let [filename, appRelativeURL] of Object.entries(pkg.meta['public-assets'] || {})) {
770
+ let sourcePath = (0, path_1.resolve)(pkg.root, filename);
771
+ let stats = (0, fs_extra_1.statSync)(sourcePath);
772
+ assets.push({
773
+ kind: 'on-disk',
774
+ sourcePath,
775
+ relativePath: appRelativeURL,
776
+ mtime: stats.mtimeMs,
777
+ size: stats.size,
778
+ });
779
+ }
780
+ }
781
+ }
782
+ if (this.activeFastboot) {
783
+ const source = `
784
+ (function(){
785
+ var key = '_embroider_macros_runtime_config';
786
+ if (!window[key]){ window[key] = [];}
787
+ window[key].push(function(m) {
788
+ m.setGlobalConfig('fastboot', Object.assign({}, m.getGlobalConfig().fastboot, { isRunning: true }));
789
+ });
790
+ }())`;
791
+ assets.push({
792
+ kind: 'in-memory',
793
+ source,
794
+ relativePath: 'assets/embroider_macros_fastboot_init.js',
795
+ });
796
+ }
797
+ // and finally tack on the ones from our app itself
798
+ return assets.concat(this.extractAssets(inputPaths));
365
799
  }
366
800
  async build(inputPaths) {
367
801
  // on the first build, we lock down the macros config. on subsequent builds,
@@ -373,18 +807,29 @@ class CompatAppBuilder {
373
807
  this.firstBuild = false;
374
808
  }
375
809
  let appFiles = this.updateAppJS(inputPaths.appJS);
376
- let assetPaths = this.addEmberEntrypoints(inputPaths.htmlTree);
810
+ let emberENV = this.configTree.readConfig().EmberENV;
811
+ let assets = this.gatherAssets(inputPaths);
812
+ let finalAssets = await this.updateAssets(assets, appFiles, emberENV);
813
+ let assetPaths = assets.map(asset => asset.relativePath);
377
814
  if (this.activeFastboot) {
378
815
  // when using fastboot, our own package.json needs to be in the output so fastboot can read it.
379
816
  assetPaths.push('package.json');
380
817
  }
818
+ for (let asset of finalAssets) {
819
+ // our concatenated assets all have map files that ride along. Here we're
820
+ // telling the final stage packager to be sure and serve the map files
821
+ // too.
822
+ if (asset.kind === 'concatenated-asset') {
823
+ assetPaths.push(asset.sourcemapPath);
824
+ }
825
+ }
381
826
  let meta = {
382
827
  type: 'app',
383
828
  version: 2,
384
829
  assets: assetPaths,
385
830
  babel: {
386
831
  filename: '_babel_config_.js',
387
- isParallelSafe: true, // TODO
832
+ isParallelSafe: true,
388
833
  majorVersion: this.compatApp.babelMajorVersion(),
389
834
  fileFilter: '_babel_filter_.js',
390
835
  },
@@ -396,12 +841,8 @@ class CompatAppBuilder {
396
841
  (0, fs_extra_1.writeFileSync)((0, path_2.join)(this.root, 'package.json'), JSON.stringify(pkg, null, 2), 'utf8');
397
842
  let resolverConfig = this.resolverConfig(appFiles);
398
843
  this.addResolverConfig(resolverConfig);
399
- this.addContentForConfig(this.contentForTree.readContents());
400
- this.addEmberEnvConfig(this.configTree.readConfig().EmberENV);
401
- this.addAppBoot(this.compatApp.appBoot.readAppBoot());
402
- let babelConfig = await this.babelConfig(resolverConfig);
844
+ let babelConfig = this.babelConfig(resolverConfig);
403
845
  this.addBabelConfig(babelConfig);
404
- this.addMacrosConfig(this.compatApp.macrosConfig.babelPluginConfig()[0]);
405
846
  }
406
847
  combinePackageJSON(meta) {
407
848
  let pkgLayers = [this.origAppPackage.packageJSON];
@@ -414,7 +855,7 @@ class CompatAppBuilder {
414
855
  pkgLayers.push({ keywords: ['ember-addon'], 'ember-addon': meta });
415
856
  return combinePackageJSON(...pkgLayers);
416
857
  }
417
- async etcOptions(resolverConfig) {
858
+ etcOptions(resolverConfig) {
418
859
  let transforms = this.compatApp.htmlbarsPlugins;
419
860
  let { plugins: macroPlugins, setConfig } = node_1.MacrosConfig.transforms();
420
861
  setConfig(this.compatApp.macrosConfig);
@@ -431,7 +872,7 @@ class CompatAppBuilder {
431
872
  transforms.push([require.resolve('./resolver-transform'), opts]);
432
873
  }
433
874
  let resolver = new core_1.Resolver(resolverConfig);
434
- let resolution = await resolver.nodeResolve('ember-source/vendor/ember/ember-template-compiler', (0, path_1.resolve)(this.root, 'package.json'));
875
+ let resolution = resolver.nodeResolve('ember-source/vendor/ember/ember-template-compiler', (0, path_1.resolve)(this.root, 'package.json'));
435
876
  if (resolution.type !== 'real') {
436
877
  throw new Error(`bug: unable to resolve ember-template-compiler from ${this.root}`);
437
878
  }
@@ -449,7 +890,7 @@ class CompatAppBuilder {
449
890
  if (i < hint.resolve.length - 1) {
450
891
  target = (0, path_2.join)(target, 'package.json');
451
892
  }
452
- cursor = resolve_1.default.sync(target, { basedir: (0, path_2.dirname)(cursor) });
893
+ cursor = resolve_2.default.sync(target, { basedir: (0, path_2.dirname)(cursor) });
453
894
  }
454
895
  return {
455
896
  requireFile: cursor,
@@ -462,35 +903,246 @@ class CompatAppBuilder {
462
903
  if (!pconfig.isParallelSafe) {
463
904
  (0, core_1.warn)('Your build is slower because some babel plugins are non-serializable');
464
905
  }
465
- (0, fs_extra_1.writeFileSync)((0, path_2.join)((0, core_1.locateEmbroiderWorkingDir)(this.compatApp.root), '_babel_config_.js'), `module.exports = ${JSON.stringify(pconfig.config, null, 2)}`, 'utf8');
466
- (0, fs_extra_1.writeFileSync)((0, path_2.join)((0, core_1.locateEmbroiderWorkingDir)(this.compatApp.root), '_babel_filter_.js'), babelFilterTemplate({ skipBabel: this.options.skipBabel, appRoot: this.origAppPackage.root }), 'utf8');
906
+ (0, fs_extra_1.writeFileSync)((0, path_2.join)(this.root, '_babel_config_.js'), `module.exports = ${JSON.stringify(pconfig.config, null, 2)}`, 'utf8');
907
+ (0, fs_extra_1.writeFileSync)((0, path_2.join)(this.root, '_babel_filter_.js'), babelFilterTemplate({ skipBabel: this.options.skipBabel, appRoot: this.origAppPackage.root }), 'utf8');
467
908
  }
468
909
  addResolverConfig(config) {
469
910
  (0, fs_extra_1.outputJSONSync)((0, path_2.join)((0, core_1.locateEmbroiderWorkingDir)(this.compatApp.root), 'resolver.json'), config, { spaces: 2 });
470
911
  }
471
- addContentForConfig(contentForConfig) {
472
- (0, fs_extra_1.outputJSONSync)((0, path_2.join)((0, core_1.locateEmbroiderWorkingDir)(this.compatApp.root), 'content-for.json'), contentForConfig, {
473
- spaces: 2,
474
- });
912
+ shouldSplitRoute(routeName) {
913
+ return (!this.options.splitAtRoutes ||
914
+ this.options.splitAtRoutes.find(pattern => {
915
+ if (typeof pattern === 'string') {
916
+ return pattern === routeName;
917
+ }
918
+ else {
919
+ return pattern.test(routeName);
920
+ }
921
+ }));
475
922
  }
476
- addEmberEnvConfig(emberEnvConfig) {
477
- (0, fs_extra_1.outputJSONSync)((0, path_2.join)((0, core_1.locateEmbroiderWorkingDir)(this.compatApp.root), 'ember-env.json'), emberEnvConfig, {
478
- spaces: 2,
479
- });
923
+ splitRoute(routeName, files, addToParent, addLazyBundle) {
924
+ let shouldSplit = routeName && this.shouldSplitRoute(routeName);
925
+ let ownFiles = [];
926
+ let ownNames = new Set();
927
+ if (files.template) {
928
+ if (shouldSplit) {
929
+ ownFiles.push(files.template);
930
+ ownNames.add(routeName);
931
+ }
932
+ else {
933
+ addToParent(routeName, files.template);
934
+ }
935
+ }
936
+ if (files.controller) {
937
+ if (shouldSplit) {
938
+ ownFiles.push(files.controller);
939
+ ownNames.add(routeName);
940
+ }
941
+ else {
942
+ addToParent(routeName, files.controller);
943
+ }
944
+ }
945
+ if (files.route) {
946
+ if (shouldSplit) {
947
+ ownFiles.push(files.route);
948
+ ownNames.add(routeName);
949
+ }
950
+ else {
951
+ addToParent(routeName, files.route);
952
+ }
953
+ }
954
+ for (let [childName, childFiles] of files.children) {
955
+ this.splitRoute(`${routeName}.${childName}`, childFiles, (childRouteName, childFile) => {
956
+ // this is our child calling "addToParent"
957
+ if (shouldSplit) {
958
+ ownFiles.push(childFile);
959
+ ownNames.add(childRouteName);
960
+ }
961
+ else {
962
+ addToParent(childRouteName, childFile);
963
+ }
964
+ }, (routeNames, files) => {
965
+ addLazyBundle(routeNames, files);
966
+ });
967
+ }
968
+ if (ownFiles.length > 0) {
969
+ addLazyBundle([...ownNames], ownFiles);
970
+ }
480
971
  }
481
- addMacrosConfig(macrosConfig) {
482
- (0, fs_extra_1.outputJSONSync)((0, path_2.join)((0, core_1.locateEmbroiderWorkingDir)(this.compatApp.root), 'macros-config.json'), macrosConfig, {
483
- spaces: 2,
972
+ topAppJSAsset(engines, prepared) {
973
+ let [app, ...childEngines] = engines;
974
+ let relativePath = `assets/${this.origAppPackage.name}.js`;
975
+ return this.appJSAsset(relativePath, app, childEngines, prepared, {
976
+ autoRun: this.compatApp.autoRun,
977
+ appBoot: !this.compatApp.autoRun ? this.compatApp.appBoot.readAppBoot() : '',
978
+ mainModule: (0, core_1.explicitRelative)((0, path_2.dirname)(relativePath), 'app'),
979
+ appConfig: this.configTree.readConfig().APP,
484
980
  });
485
981
  }
486
- addAppBoot(appBoot) {
487
- (0, fs_extra_1.writeFileSync)((0, path_2.join)((0, core_1.locateEmbroiderWorkingDir)(this.compatApp.root), 'ember-app-boot.js'), appBoot !== null && appBoot !== void 0 ? appBoot : '');
982
+ get staticAppPathsPattern() {
983
+ if (this.options.staticAppPaths.length > 0) {
984
+ return new RegExp('^(?:' + this.options.staticAppPaths.map(staticAppPath => (0, escape_string_regexp_1.default)(staticAppPath)).join('|') + ')(?:$|/)');
985
+ }
986
+ }
987
+ requiredOtherFiles(appFiles) {
988
+ let pattern = this.staticAppPathsPattern;
989
+ if (pattern) {
990
+ return appFiles.otherAppFiles.filter(f => {
991
+ return !pattern.test(f);
992
+ });
993
+ }
994
+ else {
995
+ return appFiles.otherAppFiles;
996
+ }
997
+ }
998
+ appJSAsset(relativePath, appFiles, childEngines, prepared, entryParams) {
999
+ let cached = prepared.get(relativePath);
1000
+ if (cached) {
1001
+ return cached;
1002
+ }
1003
+ let eagerModules = [];
1004
+ let requiredAppFiles = [this.requiredOtherFiles(appFiles)];
1005
+ if (!this.options.staticComponents) {
1006
+ requiredAppFiles.push(appFiles.components);
1007
+ }
1008
+ if (!this.options.staticHelpers) {
1009
+ requiredAppFiles.push(appFiles.helpers);
1010
+ }
1011
+ if (!this.options.staticModifiers) {
1012
+ requiredAppFiles.push(appFiles.modifiers);
1013
+ }
1014
+ let styles = [];
1015
+ // only import styles from engines with a parent (this excludeds the parent application) as their styles
1016
+ // will be inserted via a direct <link> tag.
1017
+ if (appFiles.engine.parent && appFiles.engine.package.isLazyEngine()) {
1018
+ let implicitStyles = this.impliedAssets('implicit-styles', appFiles);
1019
+ for (let style of implicitStyles) {
1020
+ styles.push({
1021
+ path: (0, core_1.explicitRelative)('assets/_engine_', style.relativePath),
1022
+ });
1023
+ }
1024
+ let engineMeta = appFiles.engine.package.meta;
1025
+ if (engineMeta && engineMeta['implicit-styles']) {
1026
+ for (let style of engineMeta['implicit-styles']) {
1027
+ styles.push({
1028
+ path: (0, core_1.explicitRelative)((0, path_2.dirname)(relativePath), (0, path_2.join)(appFiles.engine.appRelativePath, style)),
1029
+ });
1030
+ }
1031
+ }
1032
+ }
1033
+ let lazyEngines = [];
1034
+ for (let childEngine of childEngines) {
1035
+ let asset = this.appJSAsset(`assets/_engine_/${encodeURIComponent(childEngine.engine.package.name)}.js`, childEngine, [], prepared);
1036
+ if (childEngine.engine.package.isLazyEngine()) {
1037
+ lazyEngines.push({
1038
+ names: [childEngine.engine.package.name],
1039
+ path: (0, core_1.explicitRelative)((0, path_2.dirname)(relativePath), asset.relativePath),
1040
+ });
1041
+ }
1042
+ else {
1043
+ eagerModules.push((0, core_1.explicitRelative)((0, path_2.dirname)(relativePath), asset.relativePath));
1044
+ }
1045
+ }
1046
+ let lazyRoutes = [];
1047
+ for (let [routeName, routeFiles] of appFiles.routeFiles.children) {
1048
+ this.splitRoute(routeName, routeFiles, (_, filename) => {
1049
+ requiredAppFiles.push([filename]);
1050
+ }, (routeNames, files) => {
1051
+ let routeEntrypoint = `assets/_route_/${encodeURIComponent(routeNames[0])}.js`;
1052
+ if (!prepared.has(routeEntrypoint)) {
1053
+ prepared.set(routeEntrypoint, this.routeEntrypoint(appFiles, routeEntrypoint, files));
1054
+ }
1055
+ lazyRoutes.push({
1056
+ names: routeNames,
1057
+ path: this.importPaths(appFiles, routeEntrypoint).buildtime,
1058
+ });
1059
+ });
1060
+ }
1061
+ let [fastboot, nonFastboot] = (0, partition_1.default)(excludeDotFiles((0, flatten_1.default)(requiredAppFiles)), file => appFiles.isFastbootOnly.get(file));
1062
+ let amdModules = nonFastboot.map(file => this.importPaths(appFiles, file));
1063
+ let fastbootOnlyAmdModules = fastboot.map(file => this.importPaths(appFiles, file));
1064
+ // this is a backward-compatibility feature: addons can force inclusion of
1065
+ // modules.
1066
+ eagerModules.push('./-embroider-implicit-modules.js');
1067
+ let params = { amdModules, fastbootOnlyAmdModules, lazyRoutes, lazyEngines, eagerModules, styles };
1068
+ if (entryParams) {
1069
+ Object.assign(params, entryParams);
1070
+ }
1071
+ let source = entryTemplate(params);
1072
+ let asset = {
1073
+ kind: 'in-memory',
1074
+ source,
1075
+ relativePath,
1076
+ };
1077
+ prepared.set(relativePath, asset);
1078
+ return asset;
1079
+ }
1080
+ importPaths({ engine }, engineRelativePath) {
1081
+ let noHBS = engineRelativePath.replace(this.resolvableExtensionsPattern, '').replace(/\.hbs$/, '');
1082
+ return {
1083
+ runtime: `${engine.modulePrefix}/${noHBS}`,
1084
+ buildtime: path_1.posix.join(engine.package.name, engineRelativePath),
1085
+ };
1086
+ }
1087
+ routeEntrypoint(appFiles, relativePath, files) {
1088
+ let [fastboot, nonFastboot] = (0, partition_1.default)(files, file => appFiles.isFastbootOnly.get(file));
1089
+ let asset = {
1090
+ kind: 'in-memory',
1091
+ source: routeEntryTemplate({
1092
+ files: nonFastboot.map(f => this.importPaths(appFiles, f)),
1093
+ fastbootOnlyFiles: fastboot.map(f => this.importPaths(appFiles, f)),
1094
+ }),
1095
+ relativePath,
1096
+ };
1097
+ return asset;
1098
+ }
1099
+ testJSEntrypoint(appFiles, prepared) {
1100
+ let asset = prepared.get(`assets/test.js`);
1101
+ if (asset) {
1102
+ return asset;
1103
+ }
1104
+ // We're only building tests from the first engine (the app). This is the
1105
+ // normal thing to do -- tests from engines don't automatically roll up into
1106
+ // the app.
1107
+ let engine = appFiles[0];
1108
+ const myName = 'assets/test.js';
1109
+ // tests necessarily also include the app. This is where we account for
1110
+ // that. The classic solution was to always include the app's separate
1111
+ // script tag in the tests HTML, but that isn't as easy for final stage
1112
+ // packagers to understand. It's better to express it here as a direct
1113
+ // module dependency.
1114
+ let eagerModules = [
1115
+ 'ember-testing',
1116
+ (0, core_1.explicitRelative)((0, path_2.dirname)(myName), this.topAppJSAsset(appFiles, prepared).relativePath),
1117
+ ];
1118
+ let amdModules = [];
1119
+ // this is a backward-compatibility feature: addons can force inclusion of
1120
+ // test support modules.
1121
+ eagerModules.push('./-embroider-implicit-test-modules.js');
1122
+ for (let relativePath of engine.tests) {
1123
+ amdModules.push(this.importPaths(engine, relativePath));
1124
+ }
1125
+ let source = entryTemplate({
1126
+ amdModules,
1127
+ eagerModules,
1128
+ testSuffix: true,
1129
+ });
1130
+ asset = {
1131
+ kind: 'in-memory',
1132
+ source,
1133
+ relativePath: myName,
1134
+ };
1135
+ prepared.set(asset.relativePath, asset);
1136
+ return asset;
488
1137
  }
489
1138
  }
490
1139
  exports.CompatAppBuilder = CompatAppBuilder;
491
1140
  __decorate([
492
1141
  (0, typescript_memoize_1.Memoize)()
493
1142
  ], CompatAppBuilder.prototype, "fastbootJSSrcDir", null);
1143
+ __decorate([
1144
+ (0, typescript_memoize_1.Memoize)()
1145
+ ], CompatAppBuilder.prototype, "findTestemAsset", null);
494
1146
  __decorate([
495
1147
  (0, typescript_memoize_1.Memoize)()
496
1148
  ], CompatAppBuilder.prototype, "allActiveAddons", null);
@@ -517,10 +1169,10 @@ __decorate([
517
1169
  ], CompatAppBuilder.prototype, "fastbootConfig", null);
518
1170
  __decorate([
519
1171
  (0, typescript_memoize_1.Memoize)()
520
- ], CompatAppBuilder.prototype, "staticAppPathsPattern", null);
1172
+ ], CompatAppBuilder.prototype, "portableHints", null);
521
1173
  __decorate([
522
1174
  (0, typescript_memoize_1.Memoize)()
523
- ], CompatAppBuilder.prototype, "portableHints", null);
1175
+ ], CompatAppBuilder.prototype, "staticAppPathsPattern", null);
524
1176
  function defaultAddonPackageRules() {
525
1177
  return (0, fs_extra_2.readdirSync)((0, path_2.join)(__dirname, 'addon-dependency-rules'))
526
1178
  .map(filename => {
@@ -532,6 +1184,104 @@ function defaultAddonPackageRules() {
532
1184
  .filter(Boolean)
533
1185
  .reduce((a, b) => a.concat(b), []);
534
1186
  }
1187
+ const entryTemplate = (0, core_1.jsHandlebarsCompile)(`
1188
+ import { importSync as i, macroCondition, getGlobalConfig } from '@embroider/macros';
1189
+ let w = window;
1190
+ let d = w.define;
1191
+
1192
+ {{#if styles}}
1193
+ if (macroCondition(!getGlobalConfig().fastboot?.isRunning)) {
1194
+ {{#each styles as |stylePath| ~}}
1195
+ i("{{js-string-escape stylePath.path}}");
1196
+ {{/each}}
1197
+ }
1198
+ {{/if}}
1199
+
1200
+ {{#each eagerModules as |eagerModule| ~}}
1201
+ i("{{js-string-escape eagerModule}}");
1202
+ {{/each}}
1203
+
1204
+ {{#each amdModules as |amdModule| ~}}
1205
+ d("{{js-string-escape amdModule.runtime}}", function(){ return i("{{js-string-escape amdModule.buildtime}}");});
1206
+ {{/each}}
1207
+
1208
+ {{#if fastbootOnlyAmdModules}}
1209
+ if (macroCondition(getGlobalConfig().fastboot?.isRunning)) {
1210
+ {{#each fastbootOnlyAmdModules as |amdModule| ~}}
1211
+ d("{{js-string-escape amdModule.runtime}}", function(){ return i("{{js-string-escape amdModule.buildtime}}");});
1212
+ {{/each}}
1213
+ }
1214
+ {{/if}}
1215
+
1216
+
1217
+ {{#if lazyRoutes}}
1218
+ w._embroiderRouteBundles_ = [
1219
+ {{#each lazyRoutes as |route|}}
1220
+ {
1221
+ names: {{json-stringify route.names}},
1222
+ load: function() {
1223
+ return import("{{js-string-escape route.path}}");
1224
+ }
1225
+ },
1226
+ {{/each}}
1227
+ ]
1228
+ {{/if}}
1229
+
1230
+ {{#if lazyEngines}}
1231
+ w._embroiderEngineBundles_ = [
1232
+ {{#each lazyEngines as |engine|}}
1233
+ {
1234
+ names: {{json-stringify engine.names}},
1235
+ load: function() {
1236
+ return import("{{js-string-escape engine.path}}");
1237
+ }
1238
+ },
1239
+ {{/each}}
1240
+ ]
1241
+ {{/if}}
1242
+
1243
+ {{#if autoRun ~}}
1244
+ if (!runningTests) {
1245
+ i("{{js-string-escape mainModule}}").default.create({{json-stringify appConfig}});
1246
+ }
1247
+ {{else if appBoot ~}}
1248
+ {{ appBoot }}
1249
+ {{/if}}
1250
+
1251
+ {{#if testSuffix ~}}
1252
+ {{!- TODO: both of these suffixes should get dynamically generated so they incorporate
1253
+ any content-for added by addons. -}}
1254
+
1255
+
1256
+ {{!- this is the traditional tests-suffix.js -}}
1257
+ i('../tests/test-helper');
1258
+ EmberENV.TESTS_FILE_LOADED = true;
1259
+ {{/if}}
1260
+ `);
1261
+ const routeEntryTemplate = (0, core_1.jsHandlebarsCompile)(`
1262
+ import { importSync as i } from '@embroider/macros';
1263
+ let d = window.define;
1264
+ {{#each files as |amdModule| ~}}
1265
+ d("{{js-string-escape amdModule.runtime}}", function(){ return i("{{js-string-escape amdModule.buildtime}}");});
1266
+ {{/each}}
1267
+ {{#if fastbootOnlyFiles}}
1268
+ import { macroCondition, getGlobalConfig } from '@embroider/macros';
1269
+ if (macroCondition(getGlobalConfig().fastboot?.isRunning)) {
1270
+ {{#each fastbootOnlyFiles as |amdModule| ~}}
1271
+ d("{{js-string-escape amdModule.runtime}}", function(){ return i("{{js-string-escape amdModule.buildtime}}");});
1272
+ {{/each}}
1273
+ }
1274
+ {{/if}}
1275
+ `);
1276
+ function stringOrBufferEqual(a, b) {
1277
+ if (typeof a === 'string' && typeof b === 'string') {
1278
+ return a === b;
1279
+ }
1280
+ if (a instanceof Buffer && b instanceof Buffer) {
1281
+ return Buffer.compare(a, b) === 0;
1282
+ }
1283
+ return false;
1284
+ }
535
1285
  const babelFilterTemplate = (0, core_1.jsHandlebarsCompile)(`
536
1286
  const { babelFilter } = require(${JSON.stringify(require.resolve('@embroider/core'))});
537
1287
  module.exports = babelFilter({{json-stringify skipBabel}}, "{{js-string-escape appRoot}}");
@@ -571,4 +1321,37 @@ function addCachablePlugin(babelConfig) {
571
1321
  ]);
572
1322
  }
573
1323
  }
1324
+ function excludeDotFiles(files) {
1325
+ return files.filter(file => !file.startsWith('.') && !file.includes('/.'));
1326
+ }
1327
+ class ParsedEmberAsset {
1328
+ constructor(asset) {
1329
+ this.kind = 'parsed-ember';
1330
+ this.fileAsset = asset;
1331
+ this.html = new ember_html_1.PreparedEmberHTML(asset);
1332
+ this.relativePath = asset.relativePath;
1333
+ }
1334
+ validFor(other) {
1335
+ return this.fileAsset.mtime === other.mtime && this.fileAsset.size === other.size;
1336
+ }
1337
+ }
1338
+ class BuiltEmberAsset {
1339
+ constructor(asset) {
1340
+ this.kind = 'built-ember';
1341
+ this.parsedAsset = asset;
1342
+ this.source = asset.html.dom.serialize();
1343
+ this.relativePath = asset.relativePath;
1344
+ }
1345
+ }
1346
+ class ConcatenatedAsset {
1347
+ constructor(relativePath, sources, resolvableExtensions) {
1348
+ this.relativePath = relativePath;
1349
+ this.sources = sources;
1350
+ this.resolvableExtensions = resolvableExtensions;
1351
+ this.kind = 'concatenated-asset';
1352
+ }
1353
+ get sourcemapPath() {
1354
+ return this.relativePath.replace(this.resolvableExtensions, '') + '.map';
1355
+ }
1356
+ }
574
1357
  //# sourceMappingURL=compat-app-builder.js.map