@embroider/core 3.5.1-unstable.f779011 → 3.5.1

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