@embroider/core 4.6.8 → 4.6.9

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 (119) hide show
  1. package/README.md +17 -0
  2. package/dist/src/app-files.d.ts +34 -0
  3. package/dist/src/app-files.d.ts.map +1 -0
  4. package/dist/src/app-files.js +201 -0
  5. package/dist/src/app-files.js.map +1 -0
  6. package/dist/src/describe-exports.d.ts +7 -0
  7. package/dist/src/describe-exports.d.ts.map +1 -0
  8. package/dist/src/describe-exports.js +52 -0
  9. package/dist/src/describe-exports.js.map +1 -0
  10. package/dist/src/html-entrypoint.d.ts +23 -0
  11. package/dist/src/html-entrypoint.d.ts.map +1 -0
  12. package/dist/src/html-entrypoint.js +185 -0
  13. package/dist/src/html-entrypoint.js.map +1 -0
  14. package/dist/src/html-placeholder.d.ts +40 -0
  15. package/dist/src/html-placeholder.d.ts.map +1 -0
  16. package/dist/src/html-placeholder.js +130 -0
  17. package/dist/src/html-placeholder.js.map +1 -0
  18. package/dist/src/index.d.ts +15 -0
  19. package/dist/src/index.d.ts.map +1 -0
  20. package/dist/src/index.js +50 -0
  21. package/dist/src/index.js.map +1 -0
  22. package/dist/src/js-handlebars.d.ts +2 -0
  23. package/dist/src/js-handlebars.d.ts.map +1 -0
  24. package/dist/src/js-handlebars.js +20 -0
  25. package/dist/src/js-handlebars.js.map +1 -0
  26. package/dist/src/measure-concat.d.ts +14 -0
  27. package/dist/src/measure-concat.d.ts.map +1 -0
  28. package/dist/src/measure-concat.js +33 -0
  29. package/dist/src/measure-concat.js.map +1 -0
  30. package/dist/src/messages.d.ts +9 -0
  31. package/dist/src/messages.d.ts.map +1 -0
  32. package/dist/src/messages.js +74 -0
  33. package/dist/src/messages.js.map +1 -0
  34. package/dist/src/module-request.d.ts +45 -0
  35. package/dist/src/module-request.d.ts.map +1 -0
  36. package/dist/src/module-request.js +87 -0
  37. package/dist/src/module-request.js.map +1 -0
  38. package/dist/src/module-resolver-options.d.ts +43 -0
  39. package/dist/src/module-resolver-options.d.ts.map +1 -0
  40. package/dist/src/module-resolver-options.js +155 -0
  41. package/dist/src/module-resolver-options.js.map +1 -0
  42. package/dist/src/module-resolver.d.ts +71 -0
  43. package/dist/src/module-resolver.d.ts.map +1 -0
  44. package/dist/src/module-resolver.js +1167 -0
  45. package/dist/src/module-resolver.js.map +1 -0
  46. package/dist/src/node-resolve.d.ts +36 -0
  47. package/dist/src/node-resolve.d.ts.map +1 -0
  48. package/dist/src/node-resolve.js +134 -0
  49. package/dist/src/node-resolve.js.map +1 -0
  50. package/dist/src/options.d.ts +26 -0
  51. package/dist/src/options.d.ts.map +1 -0
  52. package/dist/src/options.js +26 -0
  53. package/dist/src/options.js.map +1 -0
  54. package/dist/src/packager.d.ts +20 -0
  55. package/dist/src/packager.d.ts.map +1 -0
  56. package/dist/src/packager.js +34 -0
  57. package/dist/src/packager.js.map +1 -0
  58. package/dist/src/portable.d.ts +26 -0
  59. package/dist/src/portable.d.ts.map +1 -0
  60. package/dist/src/portable.js +231 -0
  61. package/dist/src/portable.js.map +1 -0
  62. package/dist/src/resolvable-extensions.d.ts +2 -0
  63. package/dist/src/resolvable-extensions.d.ts.map +1 -0
  64. package/dist/src/resolvable-extensions.js +13 -0
  65. package/dist/src/resolvable-extensions.js.map +1 -0
  66. package/dist/src/resolver-loader.d.ts +9 -0
  67. package/dist/src/resolver-loader.d.ts.map +1 -0
  68. package/dist/src/resolver-loader.js +54 -0
  69. package/dist/src/resolver-loader.js.map +1 -0
  70. package/dist/src/stage.d.ts +9 -0
  71. package/dist/src/stage.d.ts.map +1 -0
  72. package/dist/src/stage.js +3 -0
  73. package/dist/src/stage.js.map +1 -0
  74. package/dist/src/virtual-content.d.ts +36 -0
  75. package/dist/src/virtual-content.d.ts.map +1 -0
  76. package/dist/src/virtual-content.js +232 -0
  77. package/dist/src/virtual-content.js.map +1 -0
  78. package/dist/src/virtual-entrypoint.d.ts +22 -0
  79. package/dist/src/virtual-entrypoint.d.ts.map +1 -0
  80. package/dist/src/virtual-entrypoint.js +280 -0
  81. package/dist/src/virtual-entrypoint.js.map +1 -0
  82. package/dist/src/virtual-route-entrypoint.d.ts +11 -0
  83. package/dist/src/virtual-route-entrypoint.d.ts.map +1 -0
  84. package/dist/src/virtual-route-entrypoint.js +68 -0
  85. package/dist/src/virtual-route-entrypoint.js.map +1 -0
  86. package/dist/src/virtual-test-support-styles.d.ts +8 -0
  87. package/dist/src/virtual-test-support-styles.d.ts.map +1 -0
  88. package/dist/src/virtual-test-support-styles.js +61 -0
  89. package/dist/src/virtual-test-support-styles.js.map +1 -0
  90. package/dist/src/virtual-test-support.d.ts +8 -0
  91. package/dist/src/virtual-test-support.d.ts.map +1 -0
  92. package/dist/src/virtual-test-support.js +65 -0
  93. package/dist/src/virtual-test-support.js.map +1 -0
  94. package/dist/src/virtual-vendor-styles.d.ts +9 -0
  95. package/dist/src/virtual-vendor-styles.d.ts.map +1 -0
  96. package/dist/src/virtual-vendor-styles.js +84 -0
  97. package/dist/src/virtual-vendor-styles.js.map +1 -0
  98. package/dist/src/virtual-vendor.d.ts +8 -0
  99. package/dist/src/virtual-vendor.d.ts.map +1 -0
  100. package/dist/src/virtual-vendor.js +55 -0
  101. package/dist/src/virtual-vendor.js.map +1 -0
  102. package/dist/src/wait-for-trees.d.ts +14 -0
  103. package/dist/src/wait-for-trees.d.ts.map +1 -0
  104. package/dist/src/wait-for-trees.js +98 -0
  105. package/dist/src/wait-for-trees.js.map +1 -0
  106. package/dist/tests/babel-debug-util.d.ts +2 -0
  107. package/dist/tests/babel-debug-util.d.ts.map +1 -0
  108. package/dist/tests/babel-debug-util.js +36 -0
  109. package/dist/tests/babel-debug-util.js.map +1 -0
  110. package/dist/tests/example-target.d.ts +3 -0
  111. package/dist/tests/example-target.d.ts.map +1 -0
  112. package/dist/tests/example-target.js +10 -0
  113. package/dist/tests/example-target.js.map +1 -0
  114. package/dist/tests/portable.test.d.ts +2 -0
  115. package/dist/tests/portable.test.d.ts.map +1 -0
  116. package/dist/tests/portable.test.js +14 -0
  117. package/dist/tests/portable.test.js.map +1 -0
  118. package/dist/tsconfig.tsbuildinfo +1 -0
  119. package/package.json +5 -5
@@ -0,0 +1,1167 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Resolver = void 0;
13
+ const shared_internals_1 = require("@embroider/shared-internals");
14
+ const path_1 = require("path");
15
+ const shared_internals_2 = require("@embroider/shared-internals");
16
+ const debug_1 = __importDefault(require("debug"));
17
+ const assert_never_1 = __importDefault(require("assert-never"));
18
+ const reverse_exports_1 = require("@embroider/reverse-exports");
19
+ const resolve_exports_1 = require("resolve.exports");
20
+ const typescript_memoize_1 = require("typescript-memoize");
21
+ const describe_exports_1 = require("./describe-exports");
22
+ const fs_1 = require("fs");
23
+ const node_resolve_1 = require("./node-resolve");
24
+ const semver_1 = require("semver");
25
+ const module_request_1 = require("./module-request");
26
+ const debug = (0, debug_1.default)('embroider:resolver');
27
+ // Using a formatter makes this work lazy so nothing happens when we aren't
28
+ // logging. It is unfortunate that formatters are a globally mutable config and
29
+ // you can only use single character names, but oh well.
30
+ debug_1.default.formatters.p = (s) => {
31
+ let cwd = process.cwd();
32
+ if (s.startsWith(cwd)) {
33
+ return s.slice(cwd.length + 1);
34
+ }
35
+ return s;
36
+ };
37
+ function logTransition(reason, before, after = before) {
38
+ if (after.resolvedTo) {
39
+ debug(`[%s:resolvedTo] %s because %s\n in %p`, before.debugType, before.specifier, reason, before.fromFile);
40
+ }
41
+ else if (before.specifier !== after.specifier) {
42
+ if (before.fromFile !== after.fromFile) {
43
+ debug(`[%s:aliased and rehomed] %s to %s\n because %s\n from %p\n to %p`, before.debugType, before.specifier, after.specifier, reason, before.fromFile, after.fromFile);
44
+ }
45
+ else {
46
+ debug(`[%s:aliased] %s to %s\n because %s`, before.debugType, before.specifier, after.specifier, reason);
47
+ }
48
+ }
49
+ else if (before.fromFile !== after.fromFile) {
50
+ debug(`[%s:rehomed] %s, because %s\n from %p\n to %p`, before.debugType, before.specifier, reason, before.fromFile, after.fromFile);
51
+ }
52
+ else {
53
+ debug(`[%s:unchanged] %s because %s\n in %p`, before.debugType, before.specifier, reason, before.fromFile);
54
+ }
55
+ return after;
56
+ }
57
+ const compatPattern = /@embroider\/virtual\/(?<type>[^\/]+)\/(?<rest>.*)/;
58
+ class Resolver {
59
+ options;
60
+ constructor(options) {
61
+ this.options = options;
62
+ }
63
+ async beforeResolve(request) {
64
+ if (request.specifier === '@embroider/macros') {
65
+ // the macros package is always handled directly within babel (not
66
+ // necessarily as a real resolvable package), so we should not mess with it.
67
+ // It might not get compiled away until *after* our plugin has run, which is
68
+ // why we need to know about it.
69
+ return logTransition('early exit', request);
70
+ }
71
+ request = this.handleFastbootSwitch(request);
72
+ request = await this.handleGlobalsCompat(request);
73
+ request = this.handleImplicitModules(request);
74
+ request = this.handleImplicitTestScripts(request);
75
+ request = this.handleVendorStyles(request);
76
+ request = this.handleTestSupportStyles(request);
77
+ request = this.handleEntrypoint(request);
78
+ request = this.handleRouteEntrypoint(request);
79
+ request = this.handleRenaming(request);
80
+ request = this.handleVendor(request);
81
+ // we expect the specifier to be app relative at this point - must be after handleRenaming
82
+ request = this.generateFastbootSwitch(request);
83
+ request = this.preHandleExternal(request);
84
+ // this should probably stay the last step in beforeResolve, because it can
85
+ // rehome requests to their un-rewritten locations, and for the most part we
86
+ // want to be dealing with the rewritten packages.
87
+ request = this.handleRewrittenPackages(request);
88
+ return request;
89
+ }
90
+ // This encapsulates the whole resolving process. Given a `defaultResolve`
91
+ // that calls your build system's normal module resolver, this does both pre-
92
+ // and post-resolution adjustments as needed to implement our compatibility
93
+ // rules.
94
+ async resolve(request) {
95
+ request = await this.beforeResolve(request);
96
+ let resolution;
97
+ if (request.resolvedTo) {
98
+ resolution = await (0, module_request_1.extractResolution)(request.resolvedTo);
99
+ }
100
+ else {
101
+ resolution = await request.defaultResolve();
102
+ }
103
+ resolution = await this.afterResolve(request, resolution);
104
+ switch (resolution.type) {
105
+ case 'found':
106
+ return resolution;
107
+ case 'not_found':
108
+ break;
109
+ default:
110
+ throw (0, assert_never_1.default)(resolution);
111
+ }
112
+ request = request.clone();
113
+ let nextRequest = await this.fallbackResolve(request);
114
+ if (nextRequest === request) {
115
+ // no additional fallback is available.
116
+ return resolution;
117
+ }
118
+ if (nextRequest.resolvedTo) {
119
+ return await (0, module_request_1.extractResolution)(nextRequest.resolvedTo);
120
+ }
121
+ if (nextRequest.fromFile === request.fromFile && nextRequest.specifier === request.specifier) {
122
+ throw new Error('Bug Discovered! New request is not === original request but has the same fromFile and specifier. This will likely create a loop.');
123
+ }
124
+ return this.resolve(nextRequest);
125
+ }
126
+ // Use standard NodeJS resolving, with our required compatibility rules on
127
+ // top. This is a convenience method for calling resolveSync with the
128
+ // defaultResolve already configured to be "do the normal node thing".
129
+ async nodeResolve(specifier, fromFile, opts) {
130
+ return (0, node_resolve_1.nodeResolve)(this, specifier, fromFile, opts);
131
+ }
132
+ get packageCache() {
133
+ return shared_internals_2.RewrittenPackageCache.shared('embroider', this.options.appRoot);
134
+ }
135
+ async afterResolve(request, resolution) {
136
+ resolution = await this.handleSyntheticComponents(request, resolution);
137
+ return resolution;
138
+ }
139
+ async handleSyntheticComponents(request, resolution) {
140
+ // Key assumption: the system's defaultResolve performs extension search for
141
+ // extensionless requests, with JS at a higher priority than HBS.
142
+ // When the request had an explicit ".js" extension, the system default
143
+ // extension search doesn't help us locate an HBS, so we need to check for
144
+ // it ourselves here.
145
+ if (resolution.type === 'not_found') {
146
+ let hbsSpecifier = (0, shared_internals_1.syntheticJStoHBS)(request.specifier);
147
+ if (hbsSpecifier) {
148
+ resolution = await this.resolve(request.alias(hbsSpecifier));
149
+ }
150
+ }
151
+ // At this point, we might have resolved an HBS file (either because the
152
+ // request was extensionless and the default search found it, or because of
153
+ // our own code above) when the request was for a JS file.
154
+ if (resolution.type === 'found') {
155
+ let syntheticId = (0, shared_internals_1.needsSyntheticComponentJS)(request.specifier, resolution.filename);
156
+ if (syntheticId && (0, shared_internals_1.isInComponents)(resolution.filename, this.packageCache)) {
157
+ let newRequest = logTransition(`synthetic component JS`, request, request.virtualize({ type: 'template-only-component-js', specifier: syntheticId }));
158
+ return await (0, module_request_1.extractResolution)(newRequest.resolvedTo);
159
+ }
160
+ }
161
+ return resolution;
162
+ }
163
+ logicalPackage(owningPackage, file) {
164
+ let logicalLocation = this.reverseSearchAppTree(file);
165
+ if (logicalLocation) {
166
+ let pkg = this.packageCache.get(logicalLocation.owningEngine.root);
167
+ if (!pkg.isV2Ember()) {
168
+ throw new Error(`bug: all engines should be v2 addons by the time we see them here`);
169
+ }
170
+ return pkg;
171
+ }
172
+ return owningPackage;
173
+ }
174
+ generateFastbootSwitch(request) {
175
+ if (request.resolvedTo) {
176
+ return request;
177
+ }
178
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
179
+ if (!pkg) {
180
+ return request;
181
+ }
182
+ if ((0, shared_internals_1.packageName)(request.specifier)) {
183
+ // not a relative request, and we're assuming all within-engine requests
184
+ // are relative by this point due to `v1 self-import` which happens
185
+ // earlier
186
+ return request;
187
+ }
188
+ let engineConfig = this.engineConfig(pkg.name);
189
+ let appRelativePath = (0, shared_internals_2.explicitRelative)(pkg.root, (0, path_1.resolve)((0, path_1.dirname)(request.fromFile), request.specifier));
190
+ if (engineConfig) {
191
+ for (let candidate of this.withResolvableExtensions(appRelativePath)) {
192
+ let fastbootFile = engineConfig.fastbootFiles[candidate];
193
+ if (fastbootFile) {
194
+ if (fastbootFile.shadowedFilename) {
195
+ let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)((0, path_1.resolve)(pkg.root, fastbootFile.shadowedFilename), 'utf8'), {
196
+ configFile: false,
197
+ });
198
+ let switchFile = fastbootSwitch(candidate, (0, path_1.resolve)(pkg.root, 'package.json'), names);
199
+ if (switchFile.specifier === request.fromFile) {
200
+ return logTransition('internal lookup from fastbootSwitch', request);
201
+ }
202
+ else {
203
+ return logTransition('shadowed app fastboot', request, request.virtualize(switchFile));
204
+ }
205
+ }
206
+ else {
207
+ return logTransition('unshadowed app fastboot', request, request.alias(fastbootFile.localFilename).rehome((0, path_1.resolve)(pkg.root, 'package.json')));
208
+ }
209
+ }
210
+ }
211
+ }
212
+ return request;
213
+ }
214
+ handleFastbootSwitch(request) {
215
+ if (request.resolvedTo) {
216
+ return request;
217
+ }
218
+ let match = decodeFastbootSwitch(request.fromFile);
219
+ if (!match) {
220
+ return request;
221
+ }
222
+ let section;
223
+ if (request.specifier === './browser') {
224
+ section = 'app-js';
225
+ }
226
+ else if (request.specifier === './fastboot') {
227
+ section = 'fastboot-js';
228
+ }
229
+ if (!section) {
230
+ return logTransition('non-special import in fastboot switch', request);
231
+ }
232
+ let pkg = this.packageCache.ownerOfFile(match.filename);
233
+ if (pkg) {
234
+ let rel = (0, shared_internals_2.explicitRelative)(pkg.root, match.filename);
235
+ let engineConfig = this.engineConfig(pkg.name);
236
+ if (engineConfig) {
237
+ let fastbootFile = engineConfig.fastbootFiles[rel];
238
+ if (fastbootFile && fastbootFile.shadowedFilename) {
239
+ let targetFile;
240
+ if (section === 'app-js') {
241
+ targetFile = fastbootFile.shadowedFilename;
242
+ }
243
+ else {
244
+ targetFile = fastbootFile.localFilename;
245
+ }
246
+ return logTransition('matched app entry', request,
247
+ // deliberately not using rehome because we want
248
+ // generateFastbootSwitch to see that this request is coming *from*
249
+ // a fastboot switch so it won't cycle back around. Instead we make
250
+ // the targetFile relative to the fromFile that we already have.
251
+ request.alias((0, shared_internals_2.explicitRelative)((0, path_1.dirname)(request.fromFile), (0, path_1.resolve)(pkg.root, targetFile))));
252
+ }
253
+ }
254
+ let entry = this.getEntryFromMergeMap(rel, pkg.root)?.entry;
255
+ if (entry?.type === 'both') {
256
+ return logTransition('matched addon entry', request, request.alias(entry[section].specifier).rehome(entry[section].fromFile));
257
+ }
258
+ }
259
+ return logTransition('failed to match in fastboot switch', request);
260
+ }
261
+ handleImplicitModules(request) {
262
+ if (request.resolvedTo) {
263
+ return request;
264
+ }
265
+ for (let variant of ['', 'test-']) {
266
+ let suffix = `-embroider-implicit-${variant}modules.js`;
267
+ if (!request.specifier.endsWith(suffix)) {
268
+ continue;
269
+ }
270
+ let filename = request.specifier.slice(0, -1 * suffix.length);
271
+ if (!filename.endsWith('/') && filename.endsWith('\\')) {
272
+ continue;
273
+ }
274
+ filename = filename.slice(0, -1);
275
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
276
+ if (!pkg?.isV2Ember()) {
277
+ throw new Error(`bug: found implicit modules import in non-ember package at ${request.fromFile}`);
278
+ }
279
+ let type = `implicit-${variant}modules`;
280
+ let packageName = (0, shared_internals_1.packageName)(filename);
281
+ if (packageName) {
282
+ let dep = this.packageCache.resolve(packageName, pkg);
283
+ return logTransition(`dep's implicit modules`, request, request.virtualize({ type, specifier: (0, path_1.resolve)(dep.root, `-embroider-${type}.js`), fromFile: dep.root }));
284
+ }
285
+ else {
286
+ return logTransition(`own implicit modules`, request, request.virtualize({ type, specifier: (0, path_1.resolve)(pkg.root, `-embroider-${type}.js`), fromFile: pkg.root }));
287
+ }
288
+ }
289
+ return request;
290
+ }
291
+ handleEntrypoint(request) {
292
+ if (request.resolvedTo) {
293
+ return request;
294
+ }
295
+ const compatModulesSpecifier = '@embroider/virtual/compat-modules';
296
+ let isCompatModules = request.specifier === compatModulesSpecifier || request.specifier.startsWith(compatModulesSpecifier + '/');
297
+ if (!isCompatModules) {
298
+ return request;
299
+ }
300
+ const requestingPkg = this.packageCache.ownerOfFile(request.fromFile);
301
+ if (!requestingPkg?.isV2Ember()) {
302
+ throw new Error(`bug: found entrypoint import in non-ember package at ${request.fromFile}`);
303
+ }
304
+ let pkg;
305
+ if (request.specifier === compatModulesSpecifier) {
306
+ pkg = requestingPkg;
307
+ }
308
+ else {
309
+ let packageName = request.specifier.slice(compatModulesSpecifier.length + 1);
310
+ pkg = this.packageCache.resolve(packageName, requestingPkg);
311
+ }
312
+ let matched = (0, resolve_exports_1.exports)(pkg.packageJSON, '-embroider-entrypoint.js', {
313
+ browser: true,
314
+ conditions: ['default', 'imports'],
315
+ });
316
+ let specifier = (0, path_1.resolve)(pkg.root, matched?.[0] ?? '-embroider-entrypoint.js');
317
+ return logTransition('entrypoint', request, request.virtualize({
318
+ type: 'entrypoint',
319
+ specifier,
320
+ fromDir: (0, path_1.dirname)(specifier),
321
+ }));
322
+ }
323
+ handleRouteEntrypoint(request) {
324
+ if (request.resolvedTo) {
325
+ return request;
326
+ }
327
+ const publicPrefix = '@embroider/core/route/';
328
+ if (!request.specifier.startsWith(publicPrefix)) {
329
+ return request;
330
+ }
331
+ let routeName = request.specifier.slice(publicPrefix.length);
332
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
333
+ if (!pkg?.isV2Ember()) {
334
+ throw new Error(`bug: found entrypoint import in non-ember package at ${request.fromFile}`);
335
+ }
336
+ let matched = (0, resolve_exports_1.exports)(pkg.packageJSON, '-embroider-route-entrypoint.js', {
337
+ browser: true,
338
+ conditions: ['default', 'imports'],
339
+ });
340
+ // The trailing `.js` stops the id from ending in a route-controlled extension
341
+ // like `.map`, which Vite's dev sourcemap middleware hijacks. See #2670.
342
+ let entrypoint = matched ?? '-embroider-route-entrypoint.js';
343
+ let target = `${entrypoint}:route=${routeName}.js`;
344
+ let specifier = (0, path_1.resolve)(pkg.root, target);
345
+ return logTransition('route entrypoint', request, request.virtualize({ type: 'route-entrypoint', specifier, route: routeName, fromDir: (0, path_1.dirname)(specifier) }));
346
+ }
347
+ handleImplicitTestScripts(request) {
348
+ if (request.specifier !== '@embroider/virtual/test-support.js') {
349
+ return request;
350
+ }
351
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
352
+ if (pkg?.root !== this.options.engines[0].root) {
353
+ throw new Error(`bug: found an import of ${request.specifier} in ${request.fromFile}, but this is not the top-level Ember app. The top-level Ember app is the only one that has support for @embroider/virtual/test-support.js. If you think something should be fixed in Embroider, please open an issue on https://github.com/embroider-build/embroider/issues.`);
354
+ }
355
+ return logTransition('test-support', request, request.virtualize({ type: 'test-support-js', specifier: (0, path_1.resolve)(pkg.root, '-embroider-test-support.js') }));
356
+ }
357
+ handleTestSupportStyles(request) {
358
+ if (request.specifier !== '@embroider/virtual/test-support.css') {
359
+ return request;
360
+ }
361
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
362
+ if (pkg?.root !== this.options.engines[0].root) {
363
+ throw new Error(`bug: found an import of ${request.specifier} in ${request.fromFile}, but this is not the top-level Ember app. The top-level Ember app is the only one that has support for @embroider/virtual/test-support.css. If you think something should be fixed in Embroider, please open an issue on https://github.com/embroider-build/embroider/issues.`);
364
+ }
365
+ return logTransition('test-support-styles', request, request.virtualize({
366
+ type: 'test-support-css',
367
+ specifier: (0, path_1.resolve)(pkg.root, '-embroider-test-support-styles.css'),
368
+ }));
369
+ }
370
+ async handleGlobalsCompat(request) {
371
+ if (request.resolvedTo) {
372
+ return request;
373
+ }
374
+ let match = compatPattern.exec(request.specifier);
375
+ if (!match) {
376
+ return request;
377
+ }
378
+ let { type, rest } = match.groups;
379
+ let fromPkg = this.packageCache.ownerOfFile(request.fromFile);
380
+ if (!fromPkg?.isV2Ember()) {
381
+ return request;
382
+ }
383
+ let engine = this.owningEngine(fromPkg);
384
+ switch (type) {
385
+ case 'helpers':
386
+ return this.resolveHelper(rest, engine, request);
387
+ case 'components':
388
+ return this.resolveComponent(rest, engine, request);
389
+ case 'modifiers':
390
+ return this.resolveModifier(rest, engine, request);
391
+ case 'ambiguous':
392
+ return this.resolveHelperOrComponent(rest, engine, request);
393
+ case 'compat-modules':
394
+ return request;
395
+ default:
396
+ throw new Error(`bug: unexepected @embroider/virtual specifier: ${request.specifier}`);
397
+ }
398
+ }
399
+ handleVendorStyles(request) {
400
+ if (request.specifier !== '@embroider/virtual/vendor.css') {
401
+ return request;
402
+ }
403
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
404
+ if (!pkg || !this.options.engines.some(e => e.root === pkg?.root)) {
405
+ throw new Error(`bug: found an import of ${request.specifier} in ${request.fromFile}, but this is not the top-level Ember app or Engine. The top-level Ember app is the only one that has support for @embroider/virtual/vendor.css. If you think something should be fixed in Embroider, please open an issue on https://github.com/embroider-build/embroider/issues.`);
406
+ }
407
+ return logTransition('vendor-styles', request, request.virtualize({ type: 'vendor-css', specifier: (0, path_1.resolve)(pkg.root, '-embroider-vendor-styles.css') }));
408
+ }
409
+ resolveHelper(path, inEngine, request) {
410
+ let target = this.parseGlobalPath(path, inEngine);
411
+ return logTransition('resolveHelper', request, request.alias(`${target.packageName}/helpers/${target.memberName}`).rehome((0, path_1.resolve)(inEngine.root, 'package.json')));
412
+ }
413
+ async resolveComponent(path, inEngine, request) {
414
+ let target = this.parseGlobalPath(path, inEngine);
415
+ let hbsModule = null;
416
+ let jsModule = null;
417
+ // first, the various places our template might be.
418
+ for (let candidate of this.componentTemplateCandidates(target.packageName)) {
419
+ let candidateSpecifier = `${target.packageName}${candidate.prefix}${target.memberName}${candidate.suffix}`;
420
+ let resolution = await this.resolve(request.alias(candidateSpecifier).rehome(target.from));
421
+ if (resolution.type === 'found') {
422
+ hbsModule = resolution;
423
+ break;
424
+ }
425
+ }
426
+ // then the various places our javascript might be.
427
+ for (let candidate of this.componentJSCandidates(target.packageName)) {
428
+ let candidateSpecifier = `${target.packageName}${candidate.prefix}${target.memberName}${candidate.suffix}`;
429
+ let resolution = await this.resolve(request.alias(candidateSpecifier).rehome(target.from));
430
+ // .hbs is a resolvable extension for us, so we need to exclude it here.
431
+ // It matches as a priority lower than .js, so finding an .hbs means
432
+ // there's definitely not a .js.
433
+ if (resolution.type === 'found' && !resolution.filename.endsWith('.hbs')) {
434
+ jsModule = resolution;
435
+ break;
436
+ }
437
+ }
438
+ if (hbsModule) {
439
+ if (!this.emberVersionSupportsSeparateTemplates) {
440
+ throw new Error(`Components with separately resolved templates were removed at Ember 6.0. Migrate to either co-located js/ts + hbs files or to gjs/gts. https://deprecations.emberjs.com/id/component-template-resolving/. Bad template was: ${hbsModule.filename}.`);
441
+ }
442
+ return logTransition(`resolveComponent found legacy HBS`, request, request.virtualize({
443
+ type: 'component-pair',
444
+ hbsModule: hbsModule.filename,
445
+ jsModule: jsModule?.filename ?? null,
446
+ debugName: (0, path_1.basename)(hbsModule.filename).replace(/\.(js|hbs)$/, ''),
447
+ specifier: `${this.options.appRoot}/embroider-pair-component/${encodeURIComponent(hbsModule.filename)}/__vpc__/${encodeURIComponent(jsModule?.filename ?? '')}`,
448
+ }));
449
+ }
450
+ else if (jsModule) {
451
+ return logTransition(`resolving to resolveComponent found only JS`, request, request.resolveTo(jsModule));
452
+ }
453
+ else {
454
+ return logTransition(`resolveComponent failed`, request);
455
+ }
456
+ }
457
+ async resolveHelperOrComponent(path, inEngine, request) {
458
+ // resolveHelper just rewrites our request to one that should target the
459
+ // component, so here to resolve the ambiguity we need to actually resolve
460
+ // that candidate to see if it works.
461
+ let helperCandidate = this.resolveHelper(path, inEngine, request);
462
+ let helperMatch = await this.resolve(request.alias(helperCandidate.specifier).rehome(helperCandidate.fromFile));
463
+ if (helperMatch.type === 'found') {
464
+ return logTransition('resolve to ambiguous case matched a helper', request, request.resolveTo(helperMatch));
465
+ }
466
+ // unlike resolveHelper, resolveComponent already does pre-resolution in
467
+ // order to deal with its own internal ambiguity around JS vs HBS vs
468
+ // colocation.≥
469
+ let componentMatch = await this.resolveComponent(path, inEngine, request);
470
+ if (componentMatch !== request) {
471
+ return logTransition('ambiguous case matched a cmoponent', request, componentMatch);
472
+ }
473
+ // this is the hard failure case -- we were supposed to find something and
474
+ // didn't. Let the normal resolution process progress so the user gets a
475
+ // normal build error.
476
+ return logTransition('ambiguous case failing', request);
477
+ }
478
+ resolveModifier(path, inEngine, request) {
479
+ let target = this.parseGlobalPath(path, inEngine);
480
+ return logTransition('resolveModifier', request, request
481
+ .alias(`${target.packageName}/modifiers/${target.memberName}`)
482
+ .rehome((0, path_1.resolve)(inEngine.root, 'package.json')));
483
+ }
484
+ *componentTemplateCandidates(inPackageName) {
485
+ yield { prefix: '/templates/components/', suffix: '' };
486
+ yield { prefix: '/components/', suffix: '/template' };
487
+ let pods = this.podPrefix(inPackageName);
488
+ if (pods) {
489
+ yield { prefix: `${pods}/components/`, suffix: '/template' };
490
+ }
491
+ }
492
+ *componentJSCandidates(inPackageName) {
493
+ yield { prefix: '/components/', suffix: '' };
494
+ yield { prefix: '/components/', suffix: '/index' };
495
+ yield { prefix: '/components/', suffix: '/component' };
496
+ let pods = this.podPrefix(inPackageName);
497
+ if (pods) {
498
+ yield { prefix: `${pods}/components/`, suffix: '/component' };
499
+ }
500
+ }
501
+ podPrefix(targetPackageName) {
502
+ if (targetPackageName === this.options.modulePrefix && this.options.podModulePrefix) {
503
+ if (!this.options.podModulePrefix.startsWith(this.options.modulePrefix)) {
504
+ throw new Error(`Your podModulePrefix (${this.options.podModulePrefix}) does not start with your app module prefix (${this.options.modulePrefix}). Not gonna support that silliness.`);
505
+ }
506
+ return this.options.podModulePrefix.slice(this.options.modulePrefix.length);
507
+ }
508
+ }
509
+ // for paths that come from non-strict templates
510
+ parseGlobalPath(path, inEngine) {
511
+ let parts = path.split('@');
512
+ if (parts.length > 1 && parts[0].length > 0) {
513
+ return { packageName: parts[0], memberName: parts[1], from: (0, path_1.resolve)(inEngine.root, 'package.json') };
514
+ }
515
+ else {
516
+ return { packageName: inEngine.packageName, memberName: path, from: (0, path_1.resolve)(inEngine.root, 'package.json') };
517
+ }
518
+ }
519
+ engineConfig(packageName) {
520
+ return this.options.engines.find(e => e.packageName === packageName);
521
+ }
522
+ get mergeMap() {
523
+ return this.mergeMaps.forward;
524
+ }
525
+ get reverseMergeMap() {
526
+ return this.mergeMaps.reverse;
527
+ }
528
+ // This is where we figure out how all the classic treeForApp merging bottoms
529
+ // out.
530
+ get mergeMaps() {
531
+ let forward = new Map();
532
+ let reverse = new Map();
533
+ for (let engine of this.options.engines) {
534
+ let engineModules = new Map();
535
+ for (let addonConfig of engine.activeAddons) {
536
+ let addon = this.packageCache.get(addonConfig.root);
537
+ if (!addon.isV2Addon()) {
538
+ continue;
539
+ }
540
+ let appJS = addon.meta['app-js'];
541
+ if (appJS) {
542
+ for (let [inEngineName, inAddonName] of Object.entries(appJS)) {
543
+ if (!inEngineName.startsWith('./')) {
544
+ throw new Error(`addon ${addon.name} declares app-js in its package.json with the illegal name "${inEngineName}". It must start with "./" to make it clear that it's relative to the app`);
545
+ }
546
+ if (!inAddonName.startsWith('./')) {
547
+ throw new Error(`addon ${addon.name} declares app-js in its package.json with the illegal name "${inAddonName}". It must start with "./" to make it clear that it's relative to the addon`);
548
+ }
549
+ let specifier = (0, reverse_exports_1.externalName)(addon.packageJSON, inAddonName);
550
+ if (!specifier) {
551
+ throw new Error(`${addon.name}'s package.json app-js refers to ${inAddonName}, but that module is not accessible from outside the package`);
552
+ }
553
+ reverse.set((0, path_1.resolve)(addon.root, inAddonName), { inEngineName, owningPackageRoot: addon.root });
554
+ let prevEntry = engineModules.get(inEngineName);
555
+ switch (prevEntry?.type) {
556
+ case undefined:
557
+ engineModules.set(inEngineName, {
558
+ type: 'app-only',
559
+ 'app-js': {
560
+ specifier,
561
+ fromFile: addonConfig.canResolveFromFile,
562
+ fromPackageName: addon.name,
563
+ },
564
+ });
565
+ break;
566
+ case 'app-only':
567
+ case 'both':
568
+ // first match wins, so this one is shadowed
569
+ break;
570
+ case 'fastboot-only':
571
+ engineModules.set(inEngineName, {
572
+ type: 'both',
573
+ 'app-js': {
574
+ specifier,
575
+ fromFile: addonConfig.canResolveFromFile,
576
+ fromPackageName: addon.name,
577
+ },
578
+ 'fastboot-js': prevEntry['fastboot-js'],
579
+ });
580
+ break;
581
+ }
582
+ }
583
+ }
584
+ let fastbootJS = addon.meta['fastboot-js'];
585
+ if (fastbootJS) {
586
+ for (let [inEngineName, inAddonName] of Object.entries(fastbootJS)) {
587
+ if (!inEngineName.startsWith('./')) {
588
+ throw new Error(`addon ${addon.name} declares fastboot-js in its package.json with the illegal name "${inEngineName}". It must start with "./" to make it clear that it's relative to the app`);
589
+ }
590
+ if (!inAddonName.startsWith('./')) {
591
+ throw new Error(`addon ${addon.name} declares fastboot-js in its package.json with the illegal name "${inAddonName}". It must start with "./" to make it clear that it's relative to the addon`);
592
+ }
593
+ let specifier = (0, reverse_exports_1.externalName)(addon.packageJSON, inAddonName);
594
+ if (!specifier) {
595
+ throw new Error(`${addon.name}'s package.json fastboot-js refers to ${inAddonName}, but that module is not accessible from outside the package`);
596
+ }
597
+ reverse.set((0, path_1.resolve)(addon.root, inAddonName), { inEngineName, owningPackageRoot: addon.root });
598
+ let prevEntry = engineModules.get(inEngineName);
599
+ switch (prevEntry?.type) {
600
+ case undefined:
601
+ engineModules.set(inEngineName, {
602
+ type: 'fastboot-only',
603
+ 'fastboot-js': {
604
+ specifier,
605
+ fromFile: addonConfig.canResolveFromFile,
606
+ fromPackageName: addon.name,
607
+ },
608
+ });
609
+ break;
610
+ case 'fastboot-only':
611
+ case 'both':
612
+ // first match wins, so this one is shadowed
613
+ break;
614
+ case 'app-only':
615
+ engineModules.set(inEngineName, {
616
+ type: 'both',
617
+ 'fastboot-js': {
618
+ specifier,
619
+ fromFile: addonConfig.canResolveFromFile,
620
+ fromPackageName: addon.name,
621
+ },
622
+ 'app-js': prevEntry['app-js'],
623
+ });
624
+ break;
625
+ }
626
+ }
627
+ }
628
+ }
629
+ forward.set(engine.root, engineModules);
630
+ }
631
+ return { forward, reverse };
632
+ }
633
+ owningEngine(pkg) {
634
+ let owningEngine = this.options.engines.find(e => pkg.isEngine() ? e.root === pkg.root : e.activeAddons.find(a => a.root === pkg.root));
635
+ if (!owningEngine) {
636
+ throw new Error(`bug in @embroider/core/src/module-resolver: cannot figure out the owning engine for ${pkg.root}`);
637
+ }
638
+ return owningEngine;
639
+ }
640
+ get emberVersion() {
641
+ return this.packageCache.get(this.options.engines[0].root).dependencies.find(d => d.name === 'ember-source')
642
+ .version;
643
+ }
644
+ get emberVersionSupportsSeparateTemplates() {
645
+ return (0, semver_1.satisfies)(this.emberVersion, '< 6.0.0-alpha.0', {
646
+ includePrerelease: true,
647
+ });
648
+ }
649
+ handleRewrittenPackages(request) {
650
+ if (request.resolvedTo) {
651
+ return request;
652
+ }
653
+ let requestingPkg = this.packageCache.ownerOfFile(request.fromFile);
654
+ if (!requestingPkg) {
655
+ return request;
656
+ }
657
+ let packageName = (0, shared_internals_1.packageName)(request.specifier);
658
+ if (!packageName) {
659
+ // relative request
660
+ return request;
661
+ }
662
+ let targetPkg;
663
+ if (packageName !== requestingPkg.name) {
664
+ // non-relative, non-self request, so check if it aims at a rewritten addon
665
+ try {
666
+ targetPkg = this.packageCache.resolve(packageName, requestingPkg);
667
+ }
668
+ catch (err) {
669
+ if (err.code !== 'MODULE_NOT_FOUND') {
670
+ throw err;
671
+ }
672
+ }
673
+ }
674
+ let originalRequestingPkg = this.packageCache.original(requestingPkg);
675
+ let originalTargetPkg = targetPkg ? this.packageCache.original(targetPkg) : undefined;
676
+ if (targetPkg && originalTargetPkg !== targetPkg) {
677
+ // in this case it doesn't matter whether or not the requesting package
678
+ // was moved. RewrittenPackageCache.resolve already took care of finding
679
+ // the right target, and we redirect the request so it will look inside
680
+ // that target.
681
+ return logTransition('request targets a moved package', request, this.resolveWithinMovedPackage(request, targetPkg));
682
+ }
683
+ else if (originalRequestingPkg !== requestingPkg) {
684
+ if (targetPkg) {
685
+ // in this case, the requesting package is moved but its destination is
686
+ // not, so we need to rehome the request back to the original location.
687
+ return logTransition('outbound request from moved package', request, request
688
+ // setting meta here because if this fails, we want the fallback
689
+ // logic to revert our rehome and continue from the *moved* package.
690
+ .withMeta({ originalFromFile: request.fromFile })
691
+ .rehome((0, path_1.resolve)(originalRequestingPkg.root, 'package.json')));
692
+ }
693
+ else {
694
+ // requesting package was moved and we failed to find its target. We
695
+ // can't let that accidentally succeed in the defaultResolve because we
696
+ // could escape the moved package system.
697
+ return logTransition('missing outbound request from moved package', request, request.notFound());
698
+ }
699
+ }
700
+ return request;
701
+ }
702
+ get renameModulesMap() {
703
+ let extensionPattern = (0, shared_internals_1.extensionsPattern)(this.options.resolvableExtensions);
704
+ let map = new Map();
705
+ for (let [candidate, replacement] of Object.entries(this.options.renameModules)) {
706
+ map.set(candidate, replacement);
707
+ let withoutExtension = candidate.replace(extensionPattern, '');
708
+ if (withoutExtension !== candidate) {
709
+ map.set(withoutExtension, replacement);
710
+ let withoutIndex = withoutExtension.replace(/\/index$/, '');
711
+ if (withoutIndex !== withoutExtension) {
712
+ map.set(withoutIndex, replacement);
713
+ }
714
+ }
715
+ }
716
+ return map;
717
+ }
718
+ handleRenaming(request) {
719
+ if (request.resolvedTo) {
720
+ return request;
721
+ }
722
+ let packageName = (0, shared_internals_1.packageName)(request.specifier);
723
+ if (!packageName) {
724
+ return request;
725
+ }
726
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
727
+ // real deps take precedence over renaming rules. That is, a package like
728
+ // ember-source might provide backburner via module renaming, but if you
729
+ // have an explicit dependency on backburner you should still get that real
730
+ // copy.
731
+ if (!pkg?.hasDependency(packageName)) {
732
+ let replacement = this.renameModulesMap.get(request.specifier);
733
+ if (replacement !== undefined) {
734
+ return logTransition(`renameModules`, request, request.alias(replacement));
735
+ }
736
+ if (this.options.renamePackages[packageName]) {
737
+ return logTransition(`renamePackages`, request, request.alias(request.specifier.replace(packageName, this.options.renamePackages[packageName])));
738
+ }
739
+ }
740
+ if (!pkg || !pkg.isV2Ember()) {
741
+ return request;
742
+ }
743
+ if (pkg.name === packageName) {
744
+ // we found a self-import
745
+ if (pkg.meta?.['auto-upgraded'] && !pkg.isEngine()) {
746
+ // auto-upgraded packages always get automatically adjusted. They never
747
+ // supported fancy package.json exports features so this direct mapping
748
+ // to the root is always right.
749
+ // "my-app/foo" -> "./foo" from app's package.json
750
+ // "my-addon/foo" -> "my-addon/foo" from a package that's guaranteed to be able to resolve my-addon
751
+ let owningEngine = this.owningEngine(pkg);
752
+ let addonConfig = owningEngine.activeAddons.find(a => a.root === pkg.root);
753
+ if (addonConfig) {
754
+ // auto-upgraded addons get special support for self-resolving here.
755
+ return logTransition(`v1 addon self-import`, request, request.rehome(addonConfig.canResolveFromFile));
756
+ }
757
+ else if (owningEngine.root === pkg.root) {
758
+ for (let engineConfig of this.options.engines) {
759
+ for (let activeAddon of engineConfig.activeAddons) {
760
+ if (activeAddon.root === pkg.root) {
761
+ return logTransition(`v1 engine self-import`, request, request.rehome(activeAddon.canResolveFromFile));
762
+ }
763
+ }
764
+ }
765
+ }
766
+ else {
767
+ // auto-upgraded apps will necessarily have packageJSON.exports
768
+ // because we insert them, so for that support we can fall through to
769
+ // that support below.
770
+ }
771
+ }
772
+ // v2 packages are supposed to use package.json `exports` to enable
773
+ // self-imports, but not all build tools actually follow the spec. This
774
+ // is a workaround for badly behaved packagers.
775
+ //
776
+ // Known upstream bugs this works around:
777
+ // - https://github.com/vitejs/vite/issues/9731
778
+ if (pkg.packageJSON.exports) {
779
+ let found = (0, resolve_exports_1.exports)(pkg.packageJSON, request.specifier, {
780
+ browser: true,
781
+ conditions: ['default', 'imports'],
782
+ });
783
+ if (found?.[0]) {
784
+ return logTransition(`v2 self-import with package.json exports`, request, request.alias(found?.[0]).rehome((0, path_1.resolve)(pkg.root, 'package.json')));
785
+ }
786
+ }
787
+ }
788
+ return request;
789
+ }
790
+ handleVendor(request) {
791
+ if (request.specifier !== '@embroider/virtual/vendor.js') {
792
+ return request;
793
+ }
794
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
795
+ if (pkg?.root !== this.options.engines[0].root) {
796
+ throw new Error(`bug: found an import of ${request.specifier} in ${request.fromFile}, but this is not the top-level Ember app. The top-level Ember app is the only one that has support for @embroider/virtual/vendor.js. If you think something should be fixed in Embroider, please open an issue on https://github.com/embroider-build/embroider/issues.`);
797
+ }
798
+ return logTransition('vendor', request, request.virtualize({ type: 'vendor-js', specifier: (0, path_1.resolve)(pkg.root, '-embroider-vendor.js') }));
799
+ }
800
+ resolveWithinMovedPackage(request, pkg) {
801
+ let levels = ['..'];
802
+ if (pkg.name.startsWith('@')) {
803
+ levels.push('..');
804
+ }
805
+ let originalFromFile = request.fromFile;
806
+ let newRequest = request.rehome((0, path_1.resolve)(pkg.root, ...levels, 'moved-package-target.js'));
807
+ if (newRequest === request) {
808
+ return request;
809
+ }
810
+ // setting meta because if this fails, we want the fallback to pick up back
811
+ // in the original requesting package.
812
+ return newRequest.withMeta({ originalFromFile });
813
+ }
814
+ preHandleExternal(request) {
815
+ if (request.resolvedTo) {
816
+ return request;
817
+ }
818
+ let { specifier, fromFile } = request;
819
+ let pkg = this.packageCache.ownerOfFile(fromFile);
820
+ if (!pkg || !pkg.isV2Ember()) {
821
+ return request;
822
+ }
823
+ let packageName = (0, shared_internals_1.packageName)(specifier);
824
+ if (!packageName) {
825
+ let absoluteSpecifier = (0, path_1.resolve)((0, path_1.dirname)(fromFile), specifier);
826
+ if (!absoluteSpecifier.startsWith(pkg.root)) {
827
+ // this relative path escape its package. So it's not really using
828
+ // normal inter-package resolving and we should leave it alone. This
829
+ // case comes up especially when babel transforms are trying to insert
830
+ // references to runtime utilities, like we do in @embroider/macros.
831
+ return logTransition('beforeResolve: relative path escapes its package', request);
832
+ }
833
+ // if the requesting file is in an addon's app-js, the relative request
834
+ // should really be understood as a request for a module in the containing
835
+ // engine.
836
+ let logicalLocation = this.reverseSearchAppTree(request.fromFile);
837
+ if (logicalLocation) {
838
+ return logTransition('beforeResolve: relative import in app-js', request, request.alias(path_1.posix.join(logicalLocation.owningEngine.packageName, (0, path_1.dirname)(logicalLocation.inAppName), request.specifier)));
839
+ }
840
+ return request;
841
+ }
842
+ if (shared_internals_1.emberVirtualPeerDeps.has(packageName) && !pkg.hasDependency(packageName)) {
843
+ // addons (whether auto-upgraded or not) may use the app's
844
+ // emberVirtualPeerDeps, like "@glimmer/component" etc.
845
+ let addon = this.locateActiveAddon(packageName);
846
+ if (!addon) {
847
+ throw new Error(`${pkg.name} is trying to import the emberVirtualPeerDep "${packageName}", but it seems to be missing`);
848
+ }
849
+ return logTransition(`emberVirtualPeerDeps`, request, request.rehome(addon.canResolveFromFile));
850
+ }
851
+ // if this file is part of an addon's app-js, it's really the logical
852
+ // package to which it belongs (normally the app) that affects some policy
853
+ // choices about what it can import
854
+ let logicalPackage = this.logicalPackage(pkg, fromFile);
855
+ if (logicalPackage.meta?.['auto-upgraded'] && !logicalPackage.hasDependency('ember-auto-import')) {
856
+ try {
857
+ let dep = this.packageCache.resolve(packageName, logicalPackage);
858
+ if (!dep.isEmberAddon()) {
859
+ // classic ember addons can only import non-ember dependencies if they
860
+ // have ember-auto-import.
861
+ return logTransition('v1 package without auto-import', request, request.notFound());
862
+ }
863
+ }
864
+ catch (err) {
865
+ if (err.code !== 'MODULE_NOT_FOUND') {
866
+ throw err;
867
+ }
868
+ }
869
+ }
870
+ // assertions on what native v2 addons can import
871
+ if (!pkg.needsLooseResolving() &&
872
+ !appImportInAppTree(pkg, logicalPackage, packageName) &&
873
+ !reliablyResolvable(pkg, packageName)) {
874
+ throw new Error(`${pkg.name} is trying to import from ${packageName} but that is not one of its explicit dependencies`);
875
+ }
876
+ return request;
877
+ }
878
+ locateActiveAddon(packageName) {
879
+ if (packageName === this.options.modulePrefix) {
880
+ // the app itself is something that addon's can classically resolve if they know it's name.
881
+ return {
882
+ root: this.options.appRoot,
883
+ canResolveFromFile: (0, path_1.resolve)(this.packageCache.maybeMoved(this.packageCache.get(this.options.appRoot)).root, 'package.json'),
884
+ };
885
+ }
886
+ for (let engine of this.options.engines) {
887
+ for (let addon of engine.activeAddons) {
888
+ if (addon.name === packageName) {
889
+ return addon;
890
+ }
891
+ }
892
+ }
893
+ }
894
+ async fallbackResolve(request) {
895
+ if (request.resolvedTo) {
896
+ throw new Error('Build tool bug detected! Fallback resolve should never see an already-resolved request.');
897
+ }
898
+ if (request.specifier === '@embroider/macros') {
899
+ // the macros package is always handled directly within babel (not
900
+ // necessarily as a real resolvable package), so we should not mess with it.
901
+ // It might not get compiled away until *after* our plugin has run, which is
902
+ // why we need to know about it.
903
+ return logTransition('fallback early exit', request);
904
+ }
905
+ if (compatPattern.test(request.specifier)) {
906
+ // Some kinds of compat requests get rewritten into other things
907
+ // deterministically. For example, "@embroider/virtual/helpers/whatever"
908
+ // means only "the-current-engine/helpers/whatever", and if that doesn't
909
+ // actually exist it's that path that will show up as a missing import.
910
+ //
911
+ // But others have an ambiguous meaning. For example,
912
+ // @embroider/virtual/components/whatever can mean several different
913
+ // things. If we're unable to find any of them, the actual
914
+ // "@embroider/virtual" request will fall through all the way to here.
915
+ //
916
+ // In that case, we don't want to externalize that failure. We know it's
917
+ // not a classic runtime thing. It's better to let it be a build error
918
+ // here.
919
+ return request;
920
+ }
921
+ let abortFallback = (() => {
922
+ const unmodified = request;
923
+ // Whenever fallbackResolve gives up, it should return the original
924
+ // unmodifiedRequest so that we communicate clearly that no further
925
+ // fallbacks should be attempted. Internally, we track a modifiedRequest
926
+ // that has been adjusted to compensate for rehoming.
927
+ return (desc) => logTransition(desc, unmodified);
928
+ })();
929
+ request = this.restoreRehomedRequest(request);
930
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
931
+ if (!pkg?.isV2Ember()) {
932
+ // this request is coming from a file that appears to be owned by no ember
933
+ // package. We offer one fallback behavior for such files. They're allowed
934
+ // to resolve from the app's namespace.
935
+ //
936
+ // This makes it possible for integrations like vite to leave references
937
+ // to the app in their pre-bundled dependencies, which will end up in an
938
+ // arbitrary cache that is not inside any particular package.
939
+ let description = pkg ? 'non-ember package' : 'unowned module';
940
+ let packageName = (0, shared_internals_1.packageName)(request.specifier);
941
+ if (packageName === this.options.modulePrefix) {
942
+ return logTransition(`fallbackResolver: ${description} resolved app namespace`, request, request.rehome(this.packageCache.maybeMoved(this.packageCache.get(this.options.appRoot)).root));
943
+ }
944
+ return abortFallback(`fallbackResolver: ${description}`);
945
+ }
946
+ let packageName = (0, shared_internals_1.packageName)(request.specifier);
947
+ if (!packageName) {
948
+ // this is a relative import
949
+ return this.relativeFallbackResolve(pkg, request, abortFallback);
950
+ }
951
+ if (pkg.needsLooseResolving()) {
952
+ let activeAddon = this.maybeFallbackToActiveAddon(request, packageName);
953
+ if (activeAddon) {
954
+ return activeAddon;
955
+ }
956
+ }
957
+ let logicalLocation = this.reverseSearchAppTree(request.fromFile);
958
+ if (logicalLocation) {
959
+ // the requesting file is in an addon's appTree. We didn't succeed in
960
+ // resolving this (non-relative) request from inside the actual addon, so
961
+ // next try to resolve it from the corresponding logical location in the
962
+ // app.
963
+ return logTransition('fallbackResolve: retry from logical home of app-js file', request,
964
+ // it might look more precise to rehome into logicalLocation.inAppName
965
+ // rather than package.json. But that logical location may not actually
966
+ // exist, and some systems (including node's require.resolve) will be
967
+ // mad about trying to resolve from notional paths that don't really
968
+ // exist.
969
+ request.rehome((0, path_1.resolve)(logicalLocation.owningEngine.root, 'package.json')));
970
+ }
971
+ let targetingEngine = this.engineConfig(packageName);
972
+ if (targetingEngine) {
973
+ let appJSMatch = await this.searchAppTree(request, targetingEngine, request.specifier.replace(packageName, '.'));
974
+ if (appJSMatch) {
975
+ return logTransition('fallbackResolve: non-relative appJsMatch', request, appJSMatch);
976
+ }
977
+ }
978
+ // this is falling through with the original specifier which was
979
+ // non-resolvable, which will presumably cause a static build error in stage3.
980
+ return abortFallback('fallbackResolve final exit');
981
+ }
982
+ restoreRehomedRequest(request) {
983
+ // meta.originalFromFile gets set when we want to try to rehome a request
984
+ // but then come back to the original location here in the fallback when the
985
+ // rehomed request fails
986
+ let originalFromFile = request.meta?.originalFromFile;
987
+ if (typeof originalFromFile === 'string') {
988
+ return request.rehome(originalFromFile);
989
+ }
990
+ return request;
991
+ }
992
+ async relativeFallbackResolve(pkg, request, abortFallback) {
993
+ let withinEngine = this.engineConfig(pkg.name);
994
+ if (withinEngine) {
995
+ // it's a relative import inside an engine (which also means app), which
996
+ // means we may need to satisfy the request via app tree merging.
997
+ let logicalName = engineRelativeName(pkg, (0, path_1.resolve)((0, path_1.dirname)(request.fromFile), request.specifier));
998
+ if (!logicalName) {
999
+ return abortFallback('fallbackResolve: relative failure because this file is not externally accessible');
1000
+ }
1001
+ let appJSMatch = await this.searchAppTree(request, withinEngine, logicalName);
1002
+ if (appJSMatch) {
1003
+ return logTransition('fallbackResolve: relative appJsMatch', request, appJSMatch);
1004
+ }
1005
+ else {
1006
+ return abortFallback('fallbackResolve: relative appJs search failure');
1007
+ }
1008
+ }
1009
+ else {
1010
+ // nothing else to do for relative imports
1011
+ return abortFallback('fallbackResolve: relative failure');
1012
+ }
1013
+ }
1014
+ maybeFallbackToActiveAddon(request, requestedPackageName) {
1015
+ // auto-upgraded packages can fall back to the set of known active addons
1016
+ let addon = this.locateActiveAddon(requestedPackageName);
1017
+ if (addon) {
1018
+ const rehomed = request.rehome(addon.canResolveFromFile);
1019
+ if (rehomed !== request) {
1020
+ return logTransition(`activeAddons`, request, rehomed);
1021
+ }
1022
+ }
1023
+ }
1024
+ getEntryFromMergeMap(inEngineSpecifier, root) {
1025
+ let entry;
1026
+ for (let candidate of this.withResolvableExtensions(inEngineSpecifier)) {
1027
+ entry = this.mergeMap.get(root)?.get(candidate);
1028
+ if (entry) {
1029
+ return { entry, matched: candidate };
1030
+ }
1031
+ }
1032
+ }
1033
+ *withResolvableExtensions(filename) {
1034
+ if (filename.match(/\.(hbs|js|hbs\.js)$/)) {
1035
+ yield filename;
1036
+ }
1037
+ else {
1038
+ for (let ext of ['.js', '.hbs.js', '.hbs']) {
1039
+ yield `${filename}${ext}`;
1040
+ }
1041
+ }
1042
+ }
1043
+ async searchAppTree(request, engine, inEngineSpecifier) {
1044
+ let matched = this.getEntryFromMergeMap(inEngineSpecifier, engine.root);
1045
+ switch (matched?.entry.type) {
1046
+ case undefined:
1047
+ return undefined;
1048
+ case 'app-only':
1049
+ return request.alias(matched.entry['app-js'].specifier).rehome(matched.entry['app-js'].fromFile);
1050
+ case 'fastboot-only':
1051
+ return request.alias(matched.entry['fastboot-js'].specifier).rehome(matched.entry['fastboot-js'].fromFile);
1052
+ case 'both':
1053
+ let foundAppJS = await this.resolve(request.alias(matched.entry['app-js'].specifier).rehome(matched.entry['app-js'].fromFile));
1054
+ if (foundAppJS.type !== 'found') {
1055
+ throw new Error(`${matched.entry['app-js'].fromPackageName} declared ${inEngineSpecifier} in packageJSON.ember-addon.app-js, but that module does not exist`);
1056
+ }
1057
+ let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)(foundAppJS.filename, 'utf8'), { configFile: false });
1058
+ return request.virtualize(fastbootSwitch(matched.matched, (0, path_1.resolve)(engine.root, 'package.json'), names));
1059
+ }
1060
+ }
1061
+ // check whether the given file with the given owningPackage is an addon's
1062
+ // appTree, and if so return the notional location within the app (or owning
1063
+ // engine) that it "logically" lives at.
1064
+ reverseSearchAppTree(fromFile) {
1065
+ let match = this.reverseMergeMap.get(fromFile);
1066
+ if (match) {
1067
+ return {
1068
+ owningEngine: this.owningEngine(this.packageCache.get(match.owningPackageRoot)),
1069
+ inAppName: match.inEngineName,
1070
+ };
1071
+ }
1072
+ }
1073
+ // check if this file is resolvable as a global component, and if so return
1074
+ // its dasherized name
1075
+ reverseComponentLookup(filename) {
1076
+ const owningPackage = this.packageCache.ownerOfFile(filename);
1077
+ if (!owningPackage?.isV2Ember()) {
1078
+ return;
1079
+ }
1080
+ let engineConfig = this.options.engines.find(e => e.root === owningPackage.root);
1081
+ if (engineConfig) {
1082
+ // we're directly inside an engine, so we're potentially resolvable as a
1083
+ // global component
1084
+ let inAppName = engineRelativeName(owningPackage, filename);
1085
+ if (inAppName) {
1086
+ return this.tryReverseComponent(engineConfig.packageName, inAppName);
1087
+ }
1088
+ }
1089
+ let engineInfo = this.reverseSearchAppTree(filename);
1090
+ if (engineInfo) {
1091
+ // we're in some addon's app tree, so we're potentially resolvable as a
1092
+ // global component
1093
+ return this.tryReverseComponent(engineInfo.owningEngine.packageName, engineInfo.inAppName);
1094
+ }
1095
+ }
1096
+ tryReverseComponent(inEngineName, relativePath) {
1097
+ let extensionless = relativePath.replace((0, shared_internals_1.extensionsPattern)(this.options.resolvableExtensions), '');
1098
+ let candidates = [...this.componentJSCandidates(inEngineName), ...this.componentTemplateCandidates(inEngineName)];
1099
+ for (let candidate of candidates) {
1100
+ if (extensionless.startsWith(`.${candidate.prefix}`) && extensionless.endsWith(candidate.suffix)) {
1101
+ return extensionless.slice(candidate.prefix.length + 1, extensionless.length - candidate.suffix.length);
1102
+ }
1103
+ }
1104
+ return undefined;
1105
+ }
1106
+ }
1107
+ exports.Resolver = Resolver;
1108
+ __decorate([
1109
+ (0, typescript_memoize_1.Memoize)()
1110
+ ], Resolver.prototype, "mergeMaps", null);
1111
+ __decorate([
1112
+ (0, typescript_memoize_1.Memoize)()
1113
+ ], Resolver.prototype, "emberVersionSupportsSeparateTemplates", null);
1114
+ __decorate([
1115
+ (0, typescript_memoize_1.Memoize)()
1116
+ ], Resolver.prototype, "renameModulesMap", null);
1117
+ // we don't want to allow things that resolve only by accident that are likely
1118
+ // to break in other setups. For example: import your dependencies'
1119
+ // dependencies, or importing your own name from within a monorepo (which will
1120
+ // work because of the symlinking) without setting up "exports" (which makes
1121
+ // your own name reliably resolvable)
1122
+ function reliablyResolvable(pkg, packageName) {
1123
+ if (pkg.hasDependency(packageName)) {
1124
+ return true;
1125
+ }
1126
+ if (pkg.name === packageName && pkg.packageJSON.exports) {
1127
+ return true;
1128
+ }
1129
+ if (shared_internals_1.emberVirtualPeerDeps.has(packageName) || shared_internals_1.emberVirtualPackages.has(packageName)) {
1130
+ return true;
1131
+ }
1132
+ return false;
1133
+ }
1134
+ //
1135
+ function appImportInAppTree(inPackage, inLogicalPackage, importedPackageName) {
1136
+ return inPackage !== inLogicalPackage && importedPackageName === inLogicalPackage.name;
1137
+ }
1138
+ function engineRelativeName(pkg, filename) {
1139
+ let outsideName = (0, reverse_exports_1.externalName)(pkg.packageJSON, (0, shared_internals_2.explicitRelative)(pkg.root, filename));
1140
+ if (outsideName) {
1141
+ return '.' + outsideName.slice(pkg.name.length);
1142
+ }
1143
+ }
1144
+ const fastbootSwitchSuffix = '/embroider_fastboot_switch';
1145
+ function fastbootSwitch(specifier, fromFile, names) {
1146
+ let filename = `${(0, path_1.resolve)((0, path_1.dirname)(fromFile), specifier)}${fastbootSwitchSuffix}`;
1147
+ let virtualSpecifier;
1148
+ if (names.size > 0) {
1149
+ virtualSpecifier = `${filename}?names=${[...names].join(',')}`;
1150
+ }
1151
+ else {
1152
+ virtualSpecifier = filename;
1153
+ }
1154
+ return {
1155
+ type: 'fastboot-switch',
1156
+ specifier: virtualSpecifier,
1157
+ names,
1158
+ hasDefaultExport: 'x',
1159
+ };
1160
+ }
1161
+ function decodeFastbootSwitch(filename) {
1162
+ let index = filename.indexOf(fastbootSwitchSuffix);
1163
+ if (index >= 0) {
1164
+ return { filename: filename.slice(0, index) };
1165
+ }
1166
+ }
1167
+ //# sourceMappingURL=module-resolver.js.map