@embroider/core 3.4.19 → 3.4.20-unstable.01e21e6

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 (64) hide show
  1. package/package.json +19 -9
  2. package/src/app-files.d.ts +3 -5
  3. package/src/app-files.js +25 -8
  4. package/src/app-files.js.map +1 -1
  5. package/src/index.d.ts +3 -3
  6. package/src/index.js +3 -3
  7. package/src/index.js.map +1 -1
  8. package/src/measure-concat.js +1 -2
  9. package/src/measure-concat.js.map +1 -1
  10. package/src/module-request.d.ts +42 -0
  11. package/src/module-request.js +91 -0
  12. package/src/module-request.js.map +1 -0
  13. package/src/module-resolver-options.d.ts +42 -0
  14. package/src/module-resolver-options.js +164 -0
  15. package/src/module-resolver-options.js.map +1 -0
  16. package/src/module-resolver.d.ts +17 -60
  17. package/src/module-resolver.js +425 -307
  18. package/src/module-resolver.js.map +1 -1
  19. package/src/node-resolve.d.ts +29 -0
  20. package/src/node-resolve.js +112 -0
  21. package/src/node-resolve.js.map +1 -0
  22. package/src/options.d.ts +0 -7
  23. package/src/options.js +0 -1
  24. package/src/options.js.map +1 -1
  25. package/src/resolver-loader.js +8 -1
  26. package/src/resolver-loader.js.map +1 -1
  27. package/src/virtual-content.d.ts +6 -4
  28. package/src/virtual-content.js +67 -99
  29. package/src/virtual-content.js.map +1 -1
  30. package/src/virtual-entrypoint.d.ts +19 -0
  31. package/src/virtual-entrypoint.js +289 -0
  32. package/src/virtual-entrypoint.js.map +1 -0
  33. package/src/virtual-route-entrypoint.d.ts +15 -0
  34. package/src/virtual-route-entrypoint.js +94 -0
  35. package/src/virtual-route-entrypoint.js.map +1 -0
  36. package/src/virtual-test-support-styles.d.ts +4 -0
  37. package/src/virtual-test-support-styles.js +64 -0
  38. package/src/virtual-test-support-styles.js.map +1 -0
  39. package/src/virtual-test-support.d.ts +4 -0
  40. package/src/virtual-test-support.js +68 -0
  41. package/src/virtual-test-support.js.map +1 -0
  42. package/src/virtual-vendor-styles.d.ts +4 -0
  43. package/src/virtual-vendor-styles.js +82 -0
  44. package/src/virtual-vendor-styles.js.map +1 -0
  45. package/src/virtual-vendor.d.ts +4 -0
  46. package/src/virtual-vendor.js +57 -0
  47. package/src/virtual-vendor.js.map +1 -0
  48. package/types/virtual/index.d.ts +9 -0
  49. package/types/virtual/index.js +3 -0
  50. package/src/asset.d.ts +0 -32
  51. package/src/asset.js +0 -3
  52. package/src/asset.js.map +0 -1
  53. package/src/ember-html.d.ts +0 -43
  54. package/src/ember-html.js +0 -110
  55. package/src/ember-html.js.map +0 -1
  56. package/src/portable-babel-config.d.ts +0 -11
  57. package/src/portable-babel-config.js +0 -132
  58. package/src/portable-babel-config.js.map +0 -1
  59. package/src/portable-babel-launcher.d.ts +0 -6
  60. package/src/portable-babel-launcher.js +0 -75
  61. package/src/portable-babel-launcher.js.map +0 -1
  62. package/src/to-broccoli-plugin.d.ts +0 -8
  63. package/src/to-broccoli-plugin.js +0 -30
  64. package/src/to-broccoli-plugin.js.map +0 -1
@@ -15,64 +15,52 @@ const path_1 = require("path");
15
15
  const shared_internals_2 = require("@embroider/shared-internals");
16
16
  const debug_1 = __importDefault(require("debug"));
17
17
  const assert_never_1 = __importDefault(require("assert-never"));
18
- const resolve_1 = __importDefault(require("resolve"));
18
+ const reverse_exports_1 = require("@embroider/reverse-exports");
19
+ const resolve_exports_1 = require("resolve.exports");
19
20
  const virtual_content_1 = require("./virtual-content");
20
21
  const typescript_memoize_1 = require("typescript-memoize");
21
22
  const describe_exports_1 = require("./describe-exports");
22
23
  const fs_1 = require("fs");
24
+ const node_resolve_1 = require("./node-resolve");
25
+ const virtual_route_entrypoint_1 = require("./virtual-route-entrypoint");
23
26
  const semver_1 = require("semver");
24
27
  const debug = (0, debug_1.default)('embroider:resolver');
28
+ // Using a formatter makes this work lazy so nothing happens when we aren't
29
+ // logging. It is unfortunate that formatters are a globally mutable config and
30
+ // you can only use single character names, but oh well.
31
+ debug_1.default.formatters.p = (s) => {
32
+ let cwd = process.cwd();
33
+ if (s.startsWith(cwd)) {
34
+ return s.slice(cwd.length + 1);
35
+ }
36
+ return s;
37
+ };
25
38
  function logTransition(reason, before, after = before) {
26
- if (after.isVirtual) {
27
- debug(`virtualized %s in %s because %s`, before.specifier, before.fromFile, reason);
39
+ if (after.resolvedTo) {
40
+ debug(`[%s:resolvedTo] %s because %s\n in %p`, before.debugType, before.specifier, reason, before.fromFile);
28
41
  }
29
42
  else if (before.specifier !== after.specifier) {
30
43
  if (before.fromFile !== after.fromFile) {
31
- debug(`aliased and rehomed: %s to %s, from %s to %s because %s`, before.specifier, after.specifier, before.fromFile, after.fromFile, reason);
44
+ 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);
32
45
  }
33
46
  else {
34
- debug(`aliased: %s to %s in %s because`, before.specifier, after.specifier, before.fromFile, reason);
47
+ debug(`[%s:aliased] %s to %s\n because %s`, before.debugType, before.specifier, after.specifier, reason);
35
48
  }
36
49
  }
37
50
  else if (before.fromFile !== after.fromFile) {
38
- debug(`rehomed: %s from %s to %s because`, before.specifier, before.fromFile, after.fromFile, reason);
51
+ debug(`[%s:rehomed] %s, because %s\n from %p\n to %p`, before.debugType, before.specifier, reason, before.fromFile, after.fromFile);
39
52
  }
40
53
  else {
41
- debug(`unchanged: %s in %s because %s`, before.specifier, before.fromFile, reason);
54
+ debug(`[%s:unchanged] %s because %s\n in %p`, before.debugType, before.specifier, reason, before.fromFile);
42
55
  }
43
56
  return after;
44
57
  }
45
- const compatPattern = /#embroider_compat\/(?<type>[^\/]+)\/(?<rest>.*)/;
46
- class NodeModuleRequest {
47
- constructor(specifier, fromFile, isVirtual, meta) {
48
- this.specifier = specifier;
49
- this.fromFile = fromFile;
50
- this.isVirtual = isVirtual;
51
- this.meta = meta;
52
- }
53
- alias(specifier) {
54
- return new NodeModuleRequest(specifier, this.fromFile, false, this.meta);
55
- }
56
- rehome(fromFile) {
57
- if (this.fromFile === fromFile) {
58
- return this;
59
- }
60
- else {
61
- return new NodeModuleRequest(this.specifier, fromFile, false, this.meta);
62
- }
63
- }
64
- virtualize(filename) {
65
- return new NodeModuleRequest(filename, this.fromFile, true, this.meta);
66
- }
67
- withMeta(meta) {
68
- return new NodeModuleRequest(this.specifier, this.fromFile, this.isVirtual, meta);
69
- }
70
- }
58
+ const compatPattern = /@embroider\/virtual\/(?<type>[^\/]+)\/(?<rest>.*)/;
71
59
  class Resolver {
72
60
  constructor(options) {
73
61
  this.options = options;
74
62
  }
75
- beforeResolve(request) {
63
+ async beforeResolve(request) {
76
64
  if (request.specifier === '@embroider/macros') {
77
65
  // the macros package is always handled directly within babel (not
78
66
  // necessarily as a real resolvable package), so we should not mess with it.
@@ -81,9 +69,15 @@ class Resolver {
81
69
  return logTransition('early exit', request);
82
70
  }
83
71
  request = this.handleFastbootSwitch(request);
84
- request = this.handleGlobalsCompat(request);
72
+ request = await this.handleGlobalsCompat(request);
85
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);
86
79
  request = this.handleRenaming(request);
80
+ request = this.handleVendor(request);
87
81
  // we expect the specifier to be app relative at this point - must be after handleRenaming
88
82
  request = this.generateFastbootSwitch(request);
89
83
  request = this.preHandleExternal(request);
@@ -97,34 +91,20 @@ class Resolver {
97
91
  // that calls your build system's normal module resolver, this does both pre-
98
92
  // and post-resolution adjustments as needed to implement our compatibility
99
93
  // rules.
100
- //
101
- // Depending on the plugin architecture you're working in, it may be easier to
102
- // call beforeResolve and fallbackResolve directly, in which case matching the
103
- // details of the recursion to what this method does are your responsibility.
104
- async resolve(request, defaultResolve) {
105
- let gen = this.internalResolve(request, defaultResolve);
106
- let out = gen.next();
107
- while (!out.done) {
108
- out = gen.next(await out.value);
109
- }
110
- return out.value;
111
- }
112
- // synchronous alternative to resolve() above. Because our own internals are
113
- // all synchronous, you can use this if your defaultResolve function is
114
- // synchronous.
115
- resolveSync(request, defaultResolve) {
116
- let gen = this.internalResolve(request, defaultResolve);
117
- let out = gen.next();
118
- while (!out.done) {
119
- out = gen.next(out.value);
120
- }
121
- return out.value;
122
- }
123
- // Our core implementation is a generator so it can power both resolve() and
124
- // resolveSync()
125
- *internalResolve(request, defaultResolve) {
126
- request = this.beforeResolve(request);
127
- let resolution = yield defaultResolve(request);
94
+ async resolve(request) {
95
+ request = await this.beforeResolve(request);
96
+ let resolution;
97
+ if (request.resolvedTo) {
98
+ if (typeof request.resolvedTo === 'function') {
99
+ resolution = await request.resolvedTo();
100
+ }
101
+ else {
102
+ resolution = request.resolvedTo;
103
+ }
104
+ }
105
+ else {
106
+ resolution = await request.defaultResolve();
107
+ }
128
108
  switch (resolution.type) {
129
109
  case 'found':
130
110
  return resolution;
@@ -133,59 +113,30 @@ class Resolver {
133
113
  default:
134
114
  throw (0, assert_never_1.default)(resolution);
135
115
  }
136
- let nextRequest = this.fallbackResolve(request);
116
+ request = request.clone();
117
+ let nextRequest = await this.fallbackResolve(request);
137
118
  if (nextRequest === request) {
138
119
  // no additional fallback is available.
139
120
  return resolution;
140
121
  }
122
+ if (nextRequest.resolvedTo) {
123
+ if (typeof nextRequest.resolvedTo === 'function') {
124
+ return await nextRequest.resolvedTo();
125
+ }
126
+ else {
127
+ return nextRequest.resolvedTo;
128
+ }
129
+ }
141
130
  if (nextRequest.fromFile === request.fromFile && nextRequest.specifier === request.specifier) {
142
131
  throw new Error('Bug Discovered! New request is not === original request but has the same fromFile and specifier. This will likely create a loop.');
143
132
  }
144
- if (nextRequest.isVirtual) {
145
- // virtual requests are terminal, there is no more beforeResolve or
146
- // fallbackResolve around them. The defaultResolve is expected to know how
147
- // to implement them.
148
- return yield defaultResolve(nextRequest);
149
- }
150
- return yield* this.internalResolve(nextRequest, defaultResolve);
133
+ return this.resolve(nextRequest);
151
134
  }
152
135
  // Use standard NodeJS resolving, with our required compatibility rules on
153
136
  // top. This is a convenience method for calling resolveSync with the
154
137
  // defaultResolve already configured to be "do the normal node thing".
155
- nodeResolve(specifier, fromFile) {
156
- let resolution = this.resolveSync(new NodeModuleRequest(specifier, fromFile, false, undefined), request => {
157
- if (request.isVirtual) {
158
- return {
159
- type: 'found',
160
- result: {
161
- type: 'virtual',
162
- content: (0, virtual_content_1.virtualContent)(request.specifier, this),
163
- filename: request.specifier,
164
- },
165
- };
166
- }
167
- try {
168
- let filename = resolve_1.default.sync(request.specifier, {
169
- basedir: (0, path_1.dirname)(request.fromFile),
170
- extensions: this.options.resolvableExtensions,
171
- });
172
- return { type: 'found', result: { type: 'real', filename } };
173
- }
174
- catch (err) {
175
- if (err.code !== 'MODULE_NOT_FOUND') {
176
- throw err;
177
- }
178
- return { type: 'not_found', err };
179
- }
180
- });
181
- switch (resolution.type) {
182
- case 'not_found':
183
- return resolution;
184
- case 'found':
185
- return resolution.result;
186
- default:
187
- throw (0, assert_never_1.default)(resolution);
188
- }
138
+ async nodeResolve(specifier, fromFile) {
139
+ return (0, node_resolve_1.nodeResolve)(this, specifier, fromFile);
189
140
  }
190
141
  get packageCache() {
191
142
  return shared_internals_2.RewrittenPackageCache.shared('embroider', this.options.appRoot);
@@ -202,6 +153,9 @@ class Resolver {
202
153
  return owningPackage;
203
154
  }
204
155
  generateFastbootSwitch(request) {
156
+ if (request.resolvedTo) {
157
+ return request;
158
+ }
205
159
  let pkg = this.packageCache.ownerOfFile(request.fromFile);
206
160
  if (!pkg) {
207
161
  return request;
@@ -219,7 +173,9 @@ class Resolver {
219
173
  let fastbootFile = engineConfig.fastbootFiles[candidate];
220
174
  if (fastbootFile) {
221
175
  if (fastbootFile.shadowedFilename) {
222
- let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)((0, path_1.resolve)(pkg.root, fastbootFile.shadowedFilename), 'utf8'), {});
176
+ let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)((0, path_1.resolve)(pkg.root, fastbootFile.shadowedFilename), 'utf8'), {
177
+ configFile: false,
178
+ });
223
179
  let switchFile = (0, virtual_content_1.fastbootSwitch)(candidate, (0, path_1.resolve)(pkg.root, 'package.json'), names);
224
180
  if (switchFile === request.fromFile) {
225
181
  return logTransition('internal lookup from fastbootSwitch', request);
@@ -238,6 +194,9 @@ class Resolver {
238
194
  }
239
195
  handleFastbootSwitch(request) {
240
196
  var _a;
197
+ if (request.resolvedTo) {
198
+ return request;
199
+ }
241
200
  let match = (0, virtual_content_1.decodeFastbootSwitch)(request.fromFile);
242
201
  if (!match) {
243
202
  return request;
@@ -276,12 +235,15 @@ class Resolver {
276
235
  }
277
236
  let entry = (_a = this.getEntryFromMergeMap(rel, pkg.root)) === null || _a === void 0 ? void 0 : _a.entry;
278
237
  if ((entry === null || entry === void 0 ? void 0 : entry.type) === 'both') {
279
- return logTransition('matched addon entry', request, request.alias(entry[section].localPath).rehome((0, path_1.resolve)(entry[section].packageRoot, 'package.json')));
238
+ return logTransition('matched addon entry', request, request.alias(entry[section].specifier).rehome(entry[section].fromFile));
280
239
  }
281
240
  }
282
241
  return logTransition('failed to match in fastboot switch', request);
283
242
  }
284
243
  handleImplicitModules(request) {
244
+ if (request.resolvedTo) {
245
+ return request;
246
+ }
285
247
  let im = (0, virtual_content_1.decodeImplicitModules)(request.specifier);
286
248
  if (!im) {
287
249
  return request;
@@ -299,7 +261,97 @@ class Resolver {
299
261
  return logTransition(`own implicit modules`, request, request.virtualize((0, path_1.resolve)(pkg.root, `-embroider-${im.type}.js`)));
300
262
  }
301
263
  }
302
- handleGlobalsCompat(request) {
264
+ handleEntrypoint(request) {
265
+ var _a;
266
+ if (request.resolvedTo) {
267
+ return request;
268
+ }
269
+ //TODO move the extra forwardslash handling out into the vite plugin
270
+ const candidates = [
271
+ '@embroider/virtual/compat-modules',
272
+ '/@embroider/virtual/compat-modules',
273
+ './@embroider/virtual/compat-modules',
274
+ ];
275
+ if (!candidates.some(c => request.specifier.startsWith(c + '/') || request.specifier === c)) {
276
+ return request;
277
+ }
278
+ const result = /\.?\/?@embroider\/virtual\/compat-modules(?:\/(?<packageName>.*))?/.exec(request.specifier);
279
+ if (!result) {
280
+ // TODO make a better error
281
+ throw new Error('entrypoint does not match pattern' + request.specifier);
282
+ }
283
+ const { packageName } = result.groups;
284
+ const requestingPkg = this.packageCache.ownerOfFile(request.fromFile);
285
+ if (!(requestingPkg === null || requestingPkg === void 0 ? void 0 : requestingPkg.isV2Ember())) {
286
+ throw new Error(`bug: found entrypoint import in non-ember package at ${request.fromFile}`);
287
+ }
288
+ let pkg;
289
+ if (packageName) {
290
+ pkg = this.packageCache.resolve(packageName, requestingPkg);
291
+ }
292
+ else {
293
+ pkg = requestingPkg;
294
+ }
295
+ let matched = (0, resolve_exports_1.exports)(pkg.packageJSON, '-embroider-entrypoint.js', {
296
+ browser: true,
297
+ conditions: ['default', 'imports'],
298
+ });
299
+ return logTransition('entrypoint', request, request.virtualize((0, path_1.resolve)(pkg.root, (_a = matched === null || matched === void 0 ? void 0 : matched[0]) !== null && _a !== void 0 ? _a : '-embroider-entrypoint.js')));
300
+ }
301
+ handleRouteEntrypoint(request) {
302
+ if (request.resolvedTo) {
303
+ return request;
304
+ }
305
+ let routeName = (0, virtual_route_entrypoint_1.decodePublicRouteEntrypoint)(request.specifier);
306
+ if (!routeName) {
307
+ return request;
308
+ }
309
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
310
+ if (!(pkg === null || pkg === void 0 ? void 0 : pkg.isV2Ember())) {
311
+ throw new Error(`bug: found entrypoint import in non-ember package at ${request.fromFile}`);
312
+ }
313
+ let matched = (0, resolve_exports_1.exports)(pkg.packageJSON, '-embroider-route-entrypoint.js', {
314
+ browser: true,
315
+ conditions: ['default', 'imports'],
316
+ });
317
+ return logTransition('route entrypoint', request, request.virtualize((0, virtual_route_entrypoint_1.encodeRouteEntrypoint)(pkg.root, matched === null || matched === void 0 ? void 0 : matched[0], routeName)));
318
+ }
319
+ handleImplicitTestScripts(request) {
320
+ //TODO move the extra forwardslash handling out into the vite plugin
321
+ const candidates = [
322
+ '@embroider/virtual/test-support.js',
323
+ '/@embroider/virtual/test-support.js',
324
+ './@embroider/virtual/test-support.js',
325
+ ];
326
+ if (!candidates.includes(request.specifier)) {
327
+ return request;
328
+ }
329
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
330
+ if ((pkg === null || pkg === void 0 ? void 0 : pkg.root) !== this.options.engines[0].root) {
331
+ 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.`);
332
+ }
333
+ return logTransition('test-support', request, request.virtualize((0, path_1.resolve)(pkg.root, '-embroider-test-support.js')));
334
+ }
335
+ handleTestSupportStyles(request) {
336
+ //TODO move the extra forwardslash handling out into the vite plugin
337
+ const candidates = [
338
+ '@embroider/virtual/test-support.css',
339
+ '/@embroider/virtual/test-support.css',
340
+ './@embroider/virtual/test-support.css',
341
+ ];
342
+ if (!candidates.includes(request.specifier)) {
343
+ return request;
344
+ }
345
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
346
+ if ((pkg === null || pkg === void 0 ? void 0 : pkg.root) !== this.options.engines[0].root) {
347
+ 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.`);
348
+ }
349
+ return logTransition('test-support-styles', request, request.virtualize((0, path_1.resolve)(pkg.root, '-embroider-test-support-styles.css')));
350
+ }
351
+ async handleGlobalsCompat(request) {
352
+ if (request.resolvedTo) {
353
+ return request;
354
+ }
303
355
  let match = compatPattern.exec(request.specifier);
304
356
  if (!match) {
305
357
  return request;
@@ -320,62 +372,86 @@ class Resolver {
320
372
  case 'ambiguous':
321
373
  return this.resolveHelperOrComponent(rest, engine, request);
322
374
  default:
323
- throw new Error(`bug: unexepected #embroider_compat specifier: ${request.specifier}`);
375
+ throw new Error(`bug: unexepected @embroider/virtual specifier: ${request.specifier}`);
376
+ }
377
+ }
378
+ handleVendorStyles(request) {
379
+ //TODO move the extra forwardslash handling out into the vite plugin
380
+ const candidates = [
381
+ '@embroider/virtual/vendor.css',
382
+ '/@embroider/virtual/vendor.css',
383
+ './@embroider/virtual/vendor.css',
384
+ ];
385
+ if (!candidates.includes(request.specifier)) {
386
+ return request;
324
387
  }
388
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
389
+ if (!pkg || !this.options.engines.some(e => e.root === (pkg === null || pkg === void 0 ? void 0 : pkg.root))) {
390
+ 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.`);
391
+ }
392
+ return logTransition('vendor-styles', request, request.virtualize((0, path_1.resolve)(pkg.root, '-embroider-vendor-styles.css')));
325
393
  }
326
394
  resolveHelper(path, inEngine, request) {
327
395
  let target = this.parseGlobalPath(path, inEngine);
328
396
  return logTransition('resolveHelper', request, request.alias(`${target.packageName}/helpers/${target.memberName}`).rehome((0, path_1.resolve)(inEngine.root, 'package.json')));
329
397
  }
330
- resolveComponent(path, inEngine, request) {
398
+ async resolveComponent(path, inEngine, request) {
331
399
  let target = this.parseGlobalPath(path, inEngine);
332
400
  let hbsModule = null;
333
401
  let jsModule = null;
334
402
  // first, the various places our template might be.
335
403
  for (let candidate of this.componentTemplateCandidates(target.packageName)) {
336
- let resolution = this.nodeResolve(`${target.packageName}${candidate.prefix}${target.memberName}${candidate.suffix}`, target.from);
337
- if (resolution.type === 'real') {
338
- hbsModule = resolution.filename;
404
+ let candidateSpecifier = `${target.packageName}${candidate.prefix}${target.memberName}${candidate.suffix}`;
405
+ let resolution = await this.resolve(request.alias(candidateSpecifier).rehome(target.from).withMeta({
406
+ runtimeFallback: false,
407
+ }));
408
+ if (resolution.type === 'found') {
409
+ hbsModule = resolution;
339
410
  break;
340
411
  }
341
412
  }
342
413
  // then the various places our javascript might be.
343
414
  for (let candidate of this.componentJSCandidates(target.packageName)) {
344
- let resolution = this.nodeResolve(`${target.packageName}${candidate.prefix}${target.memberName}${candidate.suffix}`, target.from);
415
+ let candidateSpecifier = `${target.packageName}${candidate.prefix}${target.memberName}${candidate.suffix}`;
416
+ let resolution = await this.resolve(request.alias(candidateSpecifier).rehome(target.from).withMeta({
417
+ runtimeFallback: false,
418
+ }));
345
419
  // .hbs is a resolvable extension for us, so we need to exclude it here.
346
420
  // It matches as a priority lower than .js, so finding an .hbs means
347
421
  // there's definitely not a .js.
348
- if (resolution.type === 'real' && !resolution.filename.endsWith('.hbs')) {
349
- jsModule = resolution.filename;
422
+ if (resolution.type === 'found' && !resolution.filename.endsWith('.hbs')) {
423
+ jsModule = resolution;
350
424
  break;
351
425
  }
352
426
  }
353
427
  if (hbsModule) {
354
428
  if (!this.emberVersionSupportsSeparateTemplates) {
355
- 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}.`);
429
+ 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}.`);
356
430
  }
357
- return logTransition(`resolveComponent found legacy HBS`, request, request.virtualize((0, virtual_content_1.virtualPairComponent)(hbsModule, jsModule)));
431
+ return logTransition(`resolveComponent found legacy HBS`, request, request.virtualize((0, virtual_content_1.virtualPairComponent)(hbsModule.filename, jsModule === null || jsModule === void 0 ? void 0 : jsModule.filename)));
358
432
  }
359
433
  else if (jsModule) {
360
- return logTransition(`resolveComponent found only JS`, request, request.alias(jsModule).rehome(target.from));
434
+ return logTransition(`resolving to resolveComponent found only JS`, request, request.resolveTo(jsModule));
361
435
  }
362
436
  else {
363
437
  return logTransition(`resolveComponent failed`, request);
364
438
  }
365
439
  }
366
- resolveHelperOrComponent(path, inEngine, request) {
440
+ async resolveHelperOrComponent(path, inEngine, request) {
367
441
  // resolveHelper just rewrites our request to one that should target the
368
442
  // component, so here to resolve the ambiguity we need to actually resolve
369
443
  // that candidate to see if it works.
370
444
  let helperCandidate = this.resolveHelper(path, inEngine, request);
371
- let helperMatch = this.nodeResolve(helperCandidate.specifier, helperCandidate.fromFile);
372
- if (helperMatch.type === 'real') {
373
- return logTransition('ambiguous case matched a helper', request, helperCandidate);
445
+ let helperMatch = await this.resolve(request.alias(helperCandidate.specifier).rehome(helperCandidate.fromFile).withMeta({
446
+ runtimeFallback: false,
447
+ }));
448
+ if (helperMatch.type === 'found') {
449
+ return logTransition('resolve to ambiguous case matched a helper', request, request.resolveTo(helperMatch));
374
450
  }
375
451
  // unlike resolveHelper, resolveComponent already does pre-resolution in
376
452
  // order to deal with its own internal ambiguity around JS vs HBS vs
377
453
  // colocation.≥
378
- let componentMatch = this.resolveComponent(path, inEngine, request);
454
+ let componentMatch = await this.resolveComponent(path, inEngine, request);
379
455
  if (componentMatch !== request) {
380
456
  return logTransition('ambiguous case matched a cmoponent', request, componentMatch);
381
457
  }
@@ -400,6 +476,7 @@ class Resolver {
400
476
  }
401
477
  *componentJSCandidates(inPackageName) {
402
478
  yield { prefix: '/components/', suffix: '' };
479
+ yield { prefix: '/components/', suffix: '/index' };
403
480
  yield { prefix: '/components/', suffix: '/component' };
404
481
  let pods = this.podPrefix(inPackageName);
405
482
  if (pods) {
@@ -418,10 +495,10 @@ class Resolver {
418
495
  parseGlobalPath(path, inEngine) {
419
496
  let parts = path.split('@');
420
497
  if (parts.length > 1 && parts[0].length > 0) {
421
- return { packageName: parts[0], memberName: parts[1], from: (0, path_1.resolve)(inEngine.root, 'pacakge.json') };
498
+ return { packageName: parts[0], memberName: parts[1], from: (0, path_1.resolve)(inEngine.root, 'package.json') };
422
499
  }
423
500
  else {
424
- return { packageName: inEngine.packageName, memberName: path, from: (0, path_1.resolve)(inEngine.root, 'pacakge.json') };
501
+ return { packageName: inEngine.packageName, memberName: path, from: (0, path_1.resolve)(inEngine.root, 'package.json') };
425
502
  }
426
503
  }
427
504
  engineConfig(packageName) {
@@ -447,14 +524,18 @@ class Resolver {
447
524
  if (!inAddonName.startsWith('./')) {
448
525
  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`);
449
526
  }
527
+ let specifier = (0, reverse_exports_1.externalName)(addon.packageJSON, inAddonName);
528
+ if (!specifier) {
529
+ throw new Error(`${addon.name}'s package.json app-js refers to ${inAddonName}, but that module is not accessible from outside the package`);
530
+ }
450
531
  let prevEntry = engineModules.get(inEngineName);
451
532
  switch (prevEntry === null || prevEntry === void 0 ? void 0 : prevEntry.type) {
452
533
  case undefined:
453
534
  engineModules.set(inEngineName, {
454
535
  type: 'app-only',
455
536
  'app-js': {
456
- localPath: inAddonName,
457
- packageRoot: addon.root,
537
+ specifier,
538
+ fromFile: addonConfig.canResolveFromFile,
458
539
  fromPackageName: addon.name,
459
540
  },
460
541
  });
@@ -467,8 +548,8 @@ class Resolver {
467
548
  engineModules.set(inEngineName, {
468
549
  type: 'both',
469
550
  'app-js': {
470
- localPath: inAddonName,
471
- packageRoot: addon.root,
551
+ specifier,
552
+ fromFile: addonConfig.canResolveFromFile,
472
553
  fromPackageName: addon.name,
473
554
  },
474
555
  'fastboot-js': prevEntry['fastboot-js'],
@@ -486,14 +567,18 @@ class Resolver {
486
567
  if (!inAddonName.startsWith('./')) {
487
568
  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`);
488
569
  }
570
+ let specifier = (0, reverse_exports_1.externalName)(addon.packageJSON, inAddonName);
571
+ if (!specifier) {
572
+ throw new Error(`${addon.name}'s package.json fastboot-js refers to ${inAddonName}, but that module is not accessible from outside the package`);
573
+ }
489
574
  let prevEntry = engineModules.get(inEngineName);
490
575
  switch (prevEntry === null || prevEntry === void 0 ? void 0 : prevEntry.type) {
491
576
  case undefined:
492
577
  engineModules.set(inEngineName, {
493
578
  type: 'fastboot-only',
494
579
  'fastboot-js': {
495
- localPath: inAddonName,
496
- packageRoot: addon.root,
580
+ specifier,
581
+ fromFile: addonConfig.canResolveFromFile,
497
582
  fromPackageName: addon.name,
498
583
  },
499
584
  });
@@ -506,8 +591,8 @@ class Resolver {
506
591
  engineModules.set(inEngineName, {
507
592
  type: 'both',
508
593
  'fastboot-js': {
509
- localPath: inAddonName,
510
- packageRoot: addon.root,
594
+ specifier,
595
+ fromFile: addonConfig.canResolveFromFile,
511
596
  fromPackageName: addon.name,
512
597
  },
513
598
  'app-js': prevEntry['app-js'],
@@ -538,7 +623,7 @@ class Resolver {
538
623
  });
539
624
  }
540
625
  handleRewrittenPackages(request) {
541
- if (request.isVirtual) {
626
+ if (request.resolvedTo) {
542
627
  return request;
543
628
  }
544
629
  let requestingPkg = this.packageCache.ownerOfFile(request.fromFile);
@@ -557,10 +642,6 @@ class Resolver {
557
642
  targetPkg = this.packageCache.resolve(packageName, requestingPkg);
558
643
  }
559
644
  catch (err) {
560
- // this is not the place to report resolution failures. If the thing
561
- // doesn't resolve, we're just not interested in redirecting it for
562
- // backward-compat, that's all. The rest of the system will take care of
563
- // reporting a failure to resolve (or handling it a different way)
564
645
  if (err.code !== 'MODULE_NOT_FOUND') {
565
646
  throw err;
566
647
  }
@@ -576,14 +657,26 @@ class Resolver {
576
657
  return logTransition('request targets a moved package', request, this.resolveWithinMovedPackage(request, targetPkg));
577
658
  }
578
659
  else if (originalRequestingPkg !== requestingPkg) {
579
- // in this case, the requesting package is moved but its destination is
580
- // not, so we need to rehome the request back to the original location.
581
- return logTransition('outbound request from moved package', request, request.withMeta({ wasMovedTo: request.fromFile }).rehome((0, path_1.resolve)(originalRequestingPkg.root, 'package.json')));
660
+ if (targetPkg) {
661
+ // in this case, the requesting package is moved but its destination is
662
+ // not, so we need to rehome the request back to the original location.
663
+ return logTransition('outbound request from moved package', request, request
664
+ // setting meta here because if this fails, we want the fallback
665
+ // logic to revert our rehome and continue from the *moved* package.
666
+ .withMeta({ originalFromFile: request.fromFile })
667
+ .rehome((0, path_1.resolve)(originalRequestingPkg.root, 'package.json')));
668
+ }
669
+ else {
670
+ // requesting package was moved and we failed to find its target. We
671
+ // can't let that accidentally succeed in the defaultResolve because we
672
+ // could escape the moved package system.
673
+ return logTransition('missing outbound request from moved package', request, request.notFound());
674
+ }
582
675
  }
583
676
  return request;
584
677
  }
585
678
  handleRenaming(request) {
586
- if (request.isVirtual) {
679
+ if (request.resolvedTo) {
587
680
  return request;
588
681
  }
589
682
  let packageName = (0, shared_internals_1.packageName)(request.specifier);
@@ -591,14 +684,11 @@ class Resolver {
591
684
  return request;
592
685
  }
593
686
  let pkg = this.packageCache.ownerOfFile(request.fromFile);
594
- if (!pkg || !pkg.isV2Ember()) {
595
- return request;
596
- }
597
687
  // real deps take precedence over renaming rules. That is, a package like
598
688
  // ember-source might provide backburner via module renaming, but if you
599
689
  // have an explicit dependency on backburner you should still get that real
600
690
  // copy.
601
- if (!pkg.hasDependency(packageName)) {
691
+ if (!(pkg === null || pkg === void 0 ? void 0 : pkg.hasDependency(packageName))) {
602
692
  for (let [candidate, replacement] of Object.entries(this.options.renameModules)) {
603
693
  if (candidate === request.specifier) {
604
694
  return logTransition(`renameModules`, request, request.alias(replacement));
@@ -616,30 +706,79 @@ class Resolver {
616
706
  return logTransition(`renamePackages`, request, request.alias(request.specifier.replace(packageName, this.options.renamePackages[packageName])));
617
707
  }
618
708
  }
619
- if (pkg.meta['auto-upgraded'] && pkg.name === packageName) {
620
- // we found a self-import, resolve it for them. Only auto-upgraded
621
- // packages get this help, v2 packages are natively supposed to make their
622
- // own modules resolvable, and we want to push them all to do that
623
- // correctly.
624
- return logTransition(`v1 self-import`, request, request.alias(request.specifier.replace(pkg.name, '.')).rehome((0, path_1.resolve)(pkg.root, 'package.json')));
709
+ if (!pkg || !pkg.isV2Ember()) {
710
+ return request;
711
+ }
712
+ if (pkg.name === packageName) {
713
+ // we found a self-import
714
+ if (pkg.meta['auto-upgraded']) {
715
+ // auto-upgraded packages always get automatically adjusted. They never
716
+ // supported fancy package.json exports features so this direct mapping
717
+ // to the root is always right.
718
+ // "my-app/foo" -> "./foo" from app's package.json
719
+ // "my-addon/foo" -> "my-addon/foo" from a package that's guaranteed to be able to resolve my-addon
720
+ let owningEngine = this.owningEngine(pkg);
721
+ let addonConfig = owningEngine.activeAddons.find(a => a.root === pkg.root);
722
+ if (addonConfig) {
723
+ // auto-upgraded addons get special support for self-resolving here.
724
+ return logTransition(`v1 addon self-import`, request, request.rehome(addonConfig.canResolveFromFile));
725
+ }
726
+ else {
727
+ // auto-upgraded apps will necessarily have packageJSON.exports
728
+ // because we insert them, so for that support we can fall through to
729
+ // that support below.
730
+ }
731
+ }
732
+ // v2 packages are supposed to use package.json `exports` to enable
733
+ // self-imports, but not all build tools actually follow the spec. This
734
+ // is a workaround for badly behaved packagers.
735
+ //
736
+ // Known upstream bugs this works around:
737
+ // - https://github.com/vitejs/vite/issues/9731
738
+ if (pkg.packageJSON.exports) {
739
+ let found = (0, resolve_exports_1.exports)(pkg.packageJSON, request.specifier, {
740
+ browser: true,
741
+ conditions: ['default', 'imports'],
742
+ });
743
+ if (found === null || found === void 0 ? void 0 : found[0]) {
744
+ return logTransition(`v2 self-import with package.json exports`, request, request.alias(found === null || found === void 0 ? void 0 : found[0]).rehome((0, path_1.resolve)(pkg.root, 'package.json')));
745
+ }
746
+ }
625
747
  }
626
748
  return request;
627
749
  }
750
+ handleVendor(request) {
751
+ //TODO move the extra forwardslash handling out into the vite plugin
752
+ const candidates = [
753
+ '@embroider/virtual/vendor.js',
754
+ '/@embroider/virtual/vendor.js',
755
+ './@embroider/virtual/vendor.js',
756
+ ];
757
+ if (!candidates.includes(request.specifier)) {
758
+ return request;
759
+ }
760
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
761
+ if ((pkg === null || pkg === void 0 ? void 0 : pkg.root) !== this.options.engines[0].root) {
762
+ 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.`);
763
+ }
764
+ return logTransition('vendor', request, request.virtualize((0, path_1.resolve)(pkg.root, '-embroider-vendor.js')));
765
+ }
628
766
  resolveWithinMovedPackage(request, pkg) {
629
767
  let levels = ['..'];
630
768
  if (pkg.name.startsWith('@')) {
631
769
  levels.push('..');
632
770
  }
771
+ let originalFromFile = request.fromFile;
633
772
  let newRequest = request.rehome((0, path_1.resolve)(pkg.root, ...levels, 'moved-package-target.js'));
634
773
  if (newRequest === request) {
635
774
  return request;
636
775
  }
637
- return newRequest.withMeta({
638
- resolvedWithinPackage: pkg.root,
639
- });
776
+ // setting meta because if this fails, we want the fallback to pick up back
777
+ // in the original requesting package.
778
+ return newRequest.withMeta({ originalFromFile });
640
779
  }
641
780
  preHandleExternal(request) {
642
- if (request.isVirtual) {
781
+ if (request.resolvedTo) {
643
782
  return request;
644
783
  }
645
784
  let { specifier, fromFile } = request;
@@ -649,11 +788,6 @@ class Resolver {
649
788
  }
650
789
  let packageName = (0, shared_internals_1.packageName)(specifier);
651
790
  if (!packageName) {
652
- // This is a relative import. We don't automatically externalize those
653
- // because it's rare, and by keeping them static we give better errors. But
654
- // we do allow them to be explicitly externalized by the package author (or
655
- // a compat adapter). In the metadata, they would be listed in
656
- // package-relative form, so we need to convert this specifier to that.
657
791
  let absoluteSpecifier = (0, path_1.resolve)((0, path_1.dirname)(fromFile), specifier);
658
792
  if (!absoluteSpecifier.startsWith(pkg.root)) {
659
793
  // this relative path escape its package. So it's not really using
@@ -662,36 +796,23 @@ class Resolver {
662
796
  // references to runtime utilities, like we do in @embroider/macros.
663
797
  return logTransition('beforeResolve: relative path escapes its package', request);
664
798
  }
665
- let packageRelativeSpecifier = (0, shared_internals_2.explicitRelative)(pkg.root, absoluteSpecifier);
666
- if (isExplicitlyExternal(packageRelativeSpecifier, pkg)) {
667
- let publicSpecifier = absoluteSpecifier.replace(pkg.root, pkg.name);
668
- return this.external('beforeResolve', request, publicSpecifier);
669
- }
670
799
  // if the requesting file is in an addon's app-js, the relative request
671
800
  // should really be understood as a request for a module in the containing
672
- // engine
801
+ // engine.
673
802
  let logicalLocation = this.reverseSearchAppTree(pkg, request.fromFile);
674
803
  if (logicalLocation) {
675
- return logTransition('beforeResolve: relative import in app-js', request, request.rehome((0, path_1.resolve)(logicalLocation.owningEngine.root, logicalLocation.inAppName)));
804
+ 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)));
676
805
  }
677
806
  return request;
678
807
  }
679
- // absolute package imports can also be explicitly external based on their
680
- // full specifier name
681
- if (isExplicitlyExternal(specifier, pkg)) {
682
- return this.external('beforeResolve', request, specifier);
683
- }
684
- if (shared_internals_1.emberVirtualPackages.has(packageName) && !pkg.hasDependency(packageName)) {
685
- return this.external('beforeResolve emberVirtualPackages', request, specifier);
686
- }
687
808
  if (shared_internals_1.emberVirtualPeerDeps.has(packageName) && !pkg.hasDependency(packageName)) {
688
809
  // addons (whether auto-upgraded or not) may use the app's
689
810
  // emberVirtualPeerDeps, like "@glimmer/component" etc.
690
- if (!this.options.activeAddons[packageName]) {
691
- throw new Error(`${pkg.name} is trying to import the app's ${packageName} package, but it seems to be missing`);
811
+ let addon = this.locateActiveAddon(packageName);
812
+ if (!addon) {
813
+ throw new Error(`${pkg.name} is trying to import the emberVirtualPeerDep "${packageName}", but it seems to be missing`);
692
814
  }
693
- let newHome = (0, path_1.resolve)(this.packageCache.maybeMoved(this.packageCache.get(this.options.appRoot)).root, 'package.json');
694
- return logTransition(`emberVirtualPeerDeps in v2 addon`, request, request.rehome(newHome));
815
+ return logTransition(`emberVirtualPeerDeps`, request, request.rehome(addon.canResolveFromFile));
695
816
  }
696
817
  // if this file is part of an addon's app-js, it's really the logical
697
818
  // package to which it belongs (normally the app) that affects some policy
@@ -700,10 +821,10 @@ class Resolver {
700
821
  if (logicalPackage.meta['auto-upgraded'] && !logicalPackage.hasDependency('ember-auto-import')) {
701
822
  try {
702
823
  let dep = this.packageCache.resolve(packageName, logicalPackage);
703
- if (!dep.isEmberPackage()) {
824
+ if (!dep.isEmberAddon()) {
704
825
  // classic ember addons can only import non-ember dependencies if they
705
826
  // have ember-auto-import.
706
- return this.external('v1 package without auto-import', request, specifier);
827
+ return logTransition('v1 package without auto-import', request, request.notFound());
707
828
  }
708
829
  }
709
830
  catch (err) {
@@ -713,49 +834,33 @@ class Resolver {
713
834
  }
714
835
  }
715
836
  // assertions on what native v2 addons can import
716
- if (!pkg.meta['auto-upgraded']) {
717
- if (!pkg.meta['auto-upgraded'] &&
718
- !appImportInAppTree(pkg, logicalPackage, packageName) &&
719
- !reliablyResolvable(pkg, packageName)) {
720
- throw new Error(`${pkg.name} is trying to import from ${packageName} but that is not one of its explicit dependencies`);
721
- }
837
+ if (!pkg.needsLooseResolving() &&
838
+ !appImportInAppTree(pkg, logicalPackage, packageName) &&
839
+ !reliablyResolvable(pkg, packageName)) {
840
+ throw new Error(`${pkg.name} is trying to import from ${packageName} but that is not one of its explicit dependencies`);
722
841
  }
723
842
  return request;
724
843
  }
725
- external(label, request, specifier) {
726
- if (this.options.amdCompatibility === 'cjs') {
727
- let filename = (0, virtual_content_1.virtualExternalCJSModule)(specifier);
728
- return logTransition(label, request, request.virtualize(filename));
729
- }
730
- else if (this.options.amdCompatibility) {
731
- let entry = this.options.amdCompatibility.es.find(entry => entry[0] === specifier || entry[0] + '/index' === specifier);
732
- if (!entry && request.specifier === 'require') {
733
- entry = ['require', ['default', 'has']];
734
- }
735
- if (!entry) {
736
- throw new Error(`A module tried to resolve "${request.specifier}" and didn't find it (${label}).
737
-
738
- - Maybe a dependency declaration is missing?
739
- - Remember that v1 addons can only import non-Ember-addon NPM dependencies if they include ember-auto-import in their dependencies.
740
- - If this dependency is available in the AMD loader (because someone manually called "define()" for it), you can configure a shim like:
741
-
742
- amdCompatibility: {
743
- es: [
744
- ["${request.specifier}", ["default", "yourNamedExportsGoHere"]],
745
- ]
746
- }
747
-
748
- `);
749
- }
750
- let filename = (0, virtual_content_1.virtualExternalESModule)(specifier, entry[1]);
751
- return logTransition(label, request, request.virtualize(filename));
844
+ locateActiveAddon(packageName) {
845
+ if (packageName === this.options.modulePrefix) {
846
+ // the app itself is something that addon's can classically resolve if they know it's name.
847
+ return {
848
+ root: this.options.appRoot,
849
+ canResolveFromFile: (0, path_1.resolve)(this.packageCache.maybeMoved(this.packageCache.get(this.options.appRoot)).root, 'package.json'),
850
+ };
752
851
  }
753
- else {
754
- throw new Error(`Embroider's amdCompatibility option is disabled, but something tried to use it to access "${request.specifier}"`);
852
+ for (let engine of this.options.engines) {
853
+ for (let addon of engine.activeAddons) {
854
+ if (addon.name === packageName) {
855
+ return addon;
856
+ }
857
+ }
755
858
  }
756
859
  }
757
- fallbackResolve(request) {
758
- var _a, _b, _c;
860
+ async fallbackResolve(request) {
861
+ if (request.resolvedTo) {
862
+ throw new Error('Build tool bug detected! Fallback resolve should never see an already-resolved request.');
863
+ }
759
864
  if (request.specifier === '@embroider/macros') {
760
865
  // the macros package is always handled directly within babel (not
761
866
  // necessarily as a real resolvable package), so we should not mess with it.
@@ -763,108 +868,124 @@ class Resolver {
763
868
  // why we need to know about it.
764
869
  return logTransition('fallback early exit', request);
765
870
  }
766
- let { specifier, fromFile } = request;
767
- if (compatPattern.test(specifier)) {
871
+ if (compatPattern.test(request.specifier)) {
768
872
  // Some kinds of compat requests get rewritten into other things
769
- // deterministically. For example, "#embroider_compat/helpers/whatever"
873
+ // deterministically. For example, "@embroider/virtual/helpers/whatever"
770
874
  // means only "the-current-engine/helpers/whatever", and if that doesn't
771
875
  // actually exist it's that path that will show up as a missing import.
772
876
  //
773
877
  // But others have an ambiguous meaning. For example,
774
- // #embroider_compat/components/whatever can mean several different
878
+ // @embroider/virtual/components/whatever can mean several different
775
879
  // things. If we're unable to find any of them, the actual
776
- // "#embroider_compat" request will fall through all the way to here.
880
+ // "@embroider/virtual" request will fall through all the way to here.
777
881
  //
778
882
  // In that case, we don't want to externalize that failure. We know it's
779
883
  // not a classic runtime thing. It's better to let it be a build error
780
884
  // here.
781
885
  return request;
782
886
  }
783
- if (fromFile.endsWith('moved-package-target.js')) {
784
- if (!((_a = request.meta) === null || _a === void 0 ? void 0 : _a.resolvedWithinPackage)) {
785
- throw new Error(`bug: embroider resolver's meta is not propagating`);
786
- }
787
- fromFile = (0, path_1.resolve)((_b = request.meta) === null || _b === void 0 ? void 0 : _b.resolvedWithinPackage, 'package.json');
788
- }
789
- let pkg = this.packageCache.ownerOfFile(fromFile);
790
- if (!pkg) {
791
- return logTransition('no identifiable owningPackage', request);
887
+ let pkg = this.packageCache.ownerOfFile(request.fromFile);
888
+ if (pkg) {
889
+ ({ pkg, request } = this.restoreRehomedRequest(pkg, request));
792
890
  }
793
- // if we rehomed this request to its un-rewritten location in order to try
794
- // to do the defaultResolve from there, now we refer back to the rewritten
795
- // location because that's what we want to use when asking things like
796
- // isV2Ember()
797
- let movedPkg = this.packageCache.maybeMoved(pkg);
798
- if (movedPkg !== pkg) {
799
- if (!((_c = request.meta) === null || _c === void 0 ? void 0 : _c.wasMovedTo)) {
800
- throw new Error(`bug: embroider resolver's meta is not propagating`);
891
+ if (!(pkg === null || pkg === void 0 ? void 0 : pkg.isV2Ember())) {
892
+ // this request is coming from a file that appears to be owned by no ember
893
+ // package. We offer one fallback behavior for such files. They're allowed
894
+ // to resolve from the app's namespace.
895
+ //
896
+ // This makes it possible for integrations like vite to leave references
897
+ // to the app in their pre-bundled dependencies, which will end up in an
898
+ // arbitrary cache that is not inside any particular package.
899
+ let description = pkg ? 'non-ember package' : 'unowned module';
900
+ let packageName = (0, shared_internals_1.packageName)(request.specifier);
901
+ if (packageName === this.options.modulePrefix) {
902
+ return logTransition(`fallbackResolver: ${description} resolved app namespace`, request, request.rehome(this.packageCache.maybeMoved(this.packageCache.get(this.options.appRoot)).root));
801
903
  }
802
- fromFile = request.meta.wasMovedTo;
803
- pkg = movedPkg;
804
- }
805
- if (!pkg.isV2Ember()) {
806
- return logTransition('fallbackResolve: not in an ember package', request);
904
+ return logTransition(`fallbackResolver: ${description}`, request);
807
905
  }
808
- let packageName = (0, shared_internals_1.packageName)(specifier);
906
+ let packageName = (0, shared_internals_1.packageName)(request.specifier);
809
907
  if (!packageName) {
810
908
  // this is a relative import
811
- let withinEngine = this.engineConfig(pkg.name);
812
- if (withinEngine) {
813
- // it's a relative import inside an engine (which also means app), which
814
- // means we may need to satisfy the request via app tree merging.
815
- let appJSMatch = this.searchAppTree(request, withinEngine, (0, shared_internals_2.explicitRelative)(pkg.root, (0, path_1.resolve)((0, path_1.dirname)(fromFile), specifier)));
816
- if (appJSMatch) {
817
- return logTransition('fallbackResolve: relative appJsMatch', request, appJSMatch);
818
- }
819
- else {
820
- return logTransition('fallbackResolve: relative appJs search failure', request);
821
- }
822
- }
823
- else {
824
- // nothing else to do for relative imports
825
- return logTransition('fallbackResolve: relative failure', request);
826
- }
909
+ return this.relativeFallbackResolve(pkg, request);
827
910
  }
828
- // auto-upgraded packages can fall back to the set of known active addons
829
- if (pkg.meta['auto-upgraded'] && this.options.activeAddons[packageName]) {
830
- const rehomed = this.resolveWithinMovedPackage(request, this.packageCache.get(this.options.activeAddons[packageName]));
831
- if (rehomed !== request) {
832
- return logTransition(`activeAddons`, request, rehomed);
911
+ if (pkg.needsLooseResolving()) {
912
+ let activeAddon = this.maybeFallbackToActiveAddon(request, packageName);
913
+ if (activeAddon) {
914
+ return activeAddon;
833
915
  }
834
916
  }
835
- let logicalLocation = this.reverseSearchAppTree(pkg, fromFile);
917
+ let logicalLocation = this.reverseSearchAppTree(pkg, request.fromFile);
836
918
  if (logicalLocation) {
837
919
  // the requesting file is in an addon's appTree. We didn't succeed in
838
920
  // resolving this (non-relative) request from inside the actual addon, so
839
921
  // next try to resolve it from the corresponding logical location in the
840
922
  // app.
841
- return logTransition('fallbackResolve: retry from logical home of app-js file', request, request.rehome((0, path_1.resolve)(logicalLocation.owningEngine.root, logicalLocation.inAppName)));
923
+ return logTransition('fallbackResolve: retry from logical home of app-js file', request,
924
+ // it might look more precise to rehome into logicalLocation.inAppName
925
+ // rather than package.json. But that logical location may not actually
926
+ // exist, and some systems (including node's require.resolve) will be
927
+ // mad about trying to resolve from notional paths that don't really
928
+ // exist.
929
+ request.rehome((0, path_1.resolve)(logicalLocation.owningEngine.root, 'package.json')));
842
930
  }
843
931
  let targetingEngine = this.engineConfig(packageName);
844
932
  if (targetingEngine) {
845
- let appJSMatch = this.searchAppTree(request, targetingEngine, specifier.replace(packageName, '.'));
933
+ let appJSMatch = await this.searchAppTree(request, targetingEngine, request.specifier.replace(packageName, '.'));
846
934
  if (appJSMatch) {
847
935
  return logTransition('fallbackResolve: non-relative appJsMatch', request, appJSMatch);
848
936
  }
849
937
  }
850
- if (pkg.meta['auto-upgraded']) {
851
- // auto-upgraded packages can fall back to attempting to find dependencies at
852
- // runtime. Native v2 packages can only get this behavior in the
853
- // isExplicitlyExternal case above because they need to explicitly ask for
854
- // externals.
855
- return this.external('v1 catch-all fallback', request, specifier);
938
+ // this is falling through with the original specifier which was
939
+ // non-resolvable, which will presumably cause a static build error in stage3.
940
+ return logTransition('fallbackResolve final exit', request);
941
+ }
942
+ restoreRehomedRequest(pkg, request) {
943
+ var _a;
944
+ // meta.originalFromFile gets set when we want to try to rehome a request
945
+ // but then come back to the original location here in the fallback when the
946
+ // rehomed request fails
947
+ let movedPkg = this.packageCache.maybeMoved(pkg);
948
+ if (movedPkg !== pkg) {
949
+ let originalFromFile = (_a = request.meta) === null || _a === void 0 ? void 0 : _a.originalFromFile;
950
+ if (typeof originalFromFile !== 'string') {
951
+ throw new Error(`bug: embroider resolver's meta is not propagating`);
952
+ }
953
+ request = request.rehome(originalFromFile);
954
+ pkg = movedPkg;
955
+ }
956
+ return { pkg, request };
957
+ }
958
+ async relativeFallbackResolve(pkg, request) {
959
+ let withinEngine = this.engineConfig(pkg.name);
960
+ if (withinEngine) {
961
+ // it's a relative import inside an engine (which also means app), which
962
+ // means we may need to satisfy the request via app tree merging.
963
+ let logicalName = engineRelativeName(pkg, (0, path_1.resolve)((0, path_1.dirname)(request.fromFile), request.specifier));
964
+ if (!logicalName) {
965
+ return logTransition('fallbackResolve: relative failure because this file is not externally accessible', request);
966
+ }
967
+ let appJSMatch = await this.searchAppTree(request, withinEngine, logicalName);
968
+ if (appJSMatch) {
969
+ return logTransition('fallbackResolve: relative appJsMatch', request, appJSMatch);
970
+ }
971
+ else {
972
+ return logTransition('fallbackResolve: relative appJs search failure', request);
973
+ }
856
974
  }
857
975
  else {
858
- // native v2 packages don't automatically externalize *everything* the way
859
- // auto-upgraded packages do, but they still externalize known and approved
860
- // ember virtual packages (like @ember/component)
861
- if (shared_internals_1.emberVirtualPackages.has(packageName)) {
862
- return this.external('emberVirtualPackages', request, specifier);
976
+ // nothing else to do for relative imports
977
+ return logTransition('fallbackResolve: relative failure', request);
978
+ }
979
+ }
980
+ maybeFallbackToActiveAddon(request, requestedPackageName) {
981
+ // auto-upgraded packages can fall back to the set of known active addons
982
+ let addon = this.locateActiveAddon(requestedPackageName);
983
+ if (addon) {
984
+ const rehomed = request.rehome(addon.canResolveFromFile);
985
+ if (rehomed !== request) {
986
+ return logTransition(`activeAddons`, request, rehomed);
863
987
  }
864
988
  }
865
- // this is falling through with the original specifier which was
866
- // non-resolvable, which will presumably cause a static build error in stage3.
867
- return logTransition('fallbackResolve final exit', request);
868
989
  }
869
990
  getEntryFromMergeMap(inEngineSpecifier, root) {
870
991
  var _a;
@@ -886,25 +1007,23 @@ class Resolver {
886
1007
  }
887
1008
  }
888
1009
  }
889
- searchAppTree(request, engine, inEngineSpecifier) {
1010
+ async searchAppTree(request, engine, inEngineSpecifier) {
890
1011
  let matched = this.getEntryFromMergeMap(inEngineSpecifier, engine.root);
891
1012
  switch (matched === null || matched === void 0 ? void 0 : matched.entry.type) {
892
1013
  case undefined:
893
1014
  return undefined;
894
1015
  case 'app-only':
895
- return request
896
- .alias(matched.entry['app-js'].localPath)
897
- .rehome((0, path_1.resolve)(matched.entry['app-js'].packageRoot, 'package.json'));
1016
+ return request.alias(matched.entry['app-js'].specifier).rehome(matched.entry['app-js'].fromFile);
898
1017
  case 'fastboot-only':
899
- return request
900
- .alias(matched.entry['fastboot-js'].localPath)
901
- .rehome((0, path_1.resolve)(matched.entry['fastboot-js'].packageRoot, 'package.json'));
1018
+ return request.alias(matched.entry['fastboot-js'].specifier).rehome(matched.entry['fastboot-js'].fromFile);
902
1019
  case 'both':
903
- let foundAppJS = this.nodeResolve(matched.entry['app-js'].localPath, (0, path_1.resolve)(matched.entry['app-js'].packageRoot, 'package.json'));
904
- if (foundAppJS.type !== 'real') {
1020
+ let foundAppJS = await this.resolve(request.alias(matched.entry['app-js'].specifier).rehome(matched.entry['app-js'].fromFile).withMeta({
1021
+ runtimeFallback: false,
1022
+ }));
1023
+ if (foundAppJS.type !== 'found') {
905
1024
  throw new Error(`${matched.entry['app-js'].fromPackageName} declared ${inEngineSpecifier} in packageJSON.ember-addon.app-js, but that module does not exist`);
906
1025
  }
907
- let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)(foundAppJS.filename, 'utf8'), {});
1026
+ let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)(foundAppJS.filename, 'utf8'), { configFile: false });
908
1027
  return request.virtualize((0, virtual_content_1.fastbootSwitch)(matched.matched, (0, path_1.resolve)(engine.root, 'package.json'), names));
909
1028
  }
910
1029
  }
@@ -939,14 +1058,10 @@ class Resolver {
939
1058
  if (engineConfig) {
940
1059
  // we're directly inside an engine, so we're potentially resolvable as a
941
1060
  // global component
942
- // this kind of mapping is not true in general for all packages, but it
943
- // *is* true for all classical engines (which includes apps) since they
944
- // don't support package.json `exports`. As for a future v2 engine or app:
945
- // this whole method is only relevant for implementing packageRules, which
946
- // should only be for classic stuff. v2 packages should do the right
947
- // things from the beginning and not need packageRules about themselves.
948
- let inAppName = (0, shared_internals_2.explicitRelative)(engineConfig.root, filename);
949
- return this.tryReverseComponent(engineConfig.packageName, inAppName);
1061
+ let inAppName = engineRelativeName(owningPackage, filename);
1062
+ if (inAppName) {
1063
+ return this.tryReverseComponent(engineConfig.packageName, inAppName);
1064
+ }
950
1065
  }
951
1066
  let engineInfo = this.reverseSearchAppTree(owningPackage, filename);
952
1067
  if (engineInfo) {
@@ -973,9 +1088,6 @@ __decorate([
973
1088
  __decorate([
974
1089
  (0, typescript_memoize_1.Memoize)()
975
1090
  ], Resolver.prototype, "emberVersionSupportsSeparateTemplates", null);
976
- function isExplicitlyExternal(specifier, fromPkg) {
977
- return Boolean(fromPkg.isV2Addon() && fromPkg.meta['externals'] && fromPkg.meta['externals'].includes(specifier));
978
- }
979
1091
  // we don't want to allow things that resolve only by accident that are likely
980
1092
  // to break in other setups. For example: import your dependencies'
981
1093
  // dependencies, or importing your own name from within a monorepo (which will
@@ -997,4 +1109,10 @@ function reliablyResolvable(pkg, packageName) {
997
1109
  function appImportInAppTree(inPackage, inLogicalPackage, importedPackageName) {
998
1110
  return inPackage !== inLogicalPackage && importedPackageName === inLogicalPackage.name;
999
1111
  }
1112
+ function engineRelativeName(pkg, filename) {
1113
+ let outsideName = (0, reverse_exports_1.externalName)(pkg.packageJSON, (0, shared_internals_2.explicitRelative)(pkg.root, filename));
1114
+ if (outsideName) {
1115
+ return '.' + outsideName.slice(pkg.name.length);
1116
+ }
1117
+ }
1000
1118
  //# sourceMappingURL=module-resolver.js.map