@embroider/core 3.4.5 → 3.4.6-unstable.2afc470
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.
- package/package.json +13 -11
- package/src/app-files.d.ts +2 -3
- package/src/app-files.js +1 -1
- package/src/app-files.js.map +1 -1
- package/src/index.d.ts +1 -1
- package/src/index.js.map +1 -1
- package/src/module-resolver.d.ts +22 -15
- package/src/module-resolver.js +238 -191
- package/src/module-resolver.js.map +1 -1
- package/src/node-resolve.d.ts +33 -0
- package/src/node-resolve.js +131 -0
- package/src/node-resolve.js.map +1 -0
- package/src/virtual-content.d.ts +6 -2
- package/src/virtual-content.js +85 -38
- package/src/virtual-content.js.map +1 -1
- package/src/virtual-test-support.d.ts +4 -0
- package/src/virtual-test-support.js +69 -0
- package/src/virtual-test-support.js.map +1 -0
- package/LICENSE +0 -21
package/src/module-resolver.js
CHANGED
@@ -15,63 +15,59 @@ 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
|
18
|
+
const reverse_exports_1 = __importDefault(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");
|
23
25
|
const debug = (0, debug_1.default)('embroider:resolver');
|
26
|
+
// Using a formatter makes this work lazy so nothing happens when we aren't
|
27
|
+
// logging. It is unfortunate that formatters are a globally mutable config and
|
28
|
+
// you can only use single character names, but oh well.
|
29
|
+
debug_1.default.formatters.p = (s) => {
|
30
|
+
let cwd = process.cwd();
|
31
|
+
if (s.startsWith(cwd)) {
|
32
|
+
return s.slice(cwd.length + 1);
|
33
|
+
}
|
34
|
+
return s;
|
35
|
+
};
|
24
36
|
function logTransition(reason, before, after = before) {
|
25
37
|
if (after.isVirtual) {
|
26
|
-
debug(`
|
38
|
+
debug(`[%s:virtualized] %s because %s\n in %p`, before.debugType, before.specifier, reason, before.fromFile);
|
39
|
+
}
|
40
|
+
else if (after.resolvedTo) {
|
41
|
+
debug(`[%s:resolvedTo] %s because %s\n in %p`, before.debugType, before.specifier, reason, before.fromFile);
|
27
42
|
}
|
28
43
|
else if (before.specifier !== after.specifier) {
|
29
44
|
if (before.fromFile !== after.fromFile) {
|
30
|
-
debug(`aliased and rehomed
|
45
|
+
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
46
|
}
|
32
47
|
else {
|
33
|
-
debug(`aliased
|
48
|
+
debug(`[%s:aliased] %s to %s\n because %s`, before.debugType, before.specifier, after.specifier, reason);
|
34
49
|
}
|
35
50
|
}
|
36
51
|
else if (before.fromFile !== after.fromFile) {
|
37
|
-
debug(`rehomed
|
52
|
+
debug(`[%s:rehomed] %s, because %s\n from %p\n to %p`, before.debugType, before.specifier, reason, before.fromFile, after.fromFile);
|
53
|
+
}
|
54
|
+
else if (after.isNotFound) {
|
55
|
+
debug(`[%s:not-found] %s because %s\n in %p`, before.debugType, before.specifier, reason, before.fromFile);
|
38
56
|
}
|
39
57
|
else {
|
40
|
-
debug(`
|
58
|
+
debug(`[%s:unchanged] %s because %s\n in %p`, before.debugType, before.specifier, reason, before.fromFile);
|
41
59
|
}
|
42
60
|
return after;
|
43
61
|
}
|
44
|
-
|
45
|
-
|
46
|
-
constructor(specifier, fromFile, isVirtual, meta) {
|
47
|
-
this.specifier = specifier;
|
48
|
-
this.fromFile = fromFile;
|
49
|
-
this.isVirtual = isVirtual;
|
50
|
-
this.meta = meta;
|
51
|
-
}
|
52
|
-
alias(specifier) {
|
53
|
-
return new NodeModuleRequest(specifier, this.fromFile, false, this.meta);
|
54
|
-
}
|
55
|
-
rehome(fromFile) {
|
56
|
-
if (this.fromFile === fromFile) {
|
57
|
-
return this;
|
58
|
-
}
|
59
|
-
else {
|
60
|
-
return new NodeModuleRequest(this.specifier, fromFile, false, this.meta);
|
61
|
-
}
|
62
|
-
}
|
63
|
-
virtualize(filename) {
|
64
|
-
return new NodeModuleRequest(filename, this.fromFile, true, this.meta);
|
65
|
-
}
|
66
|
-
withMeta(meta) {
|
67
|
-
return new NodeModuleRequest(this.specifier, this.fromFile, this.isVirtual, meta);
|
68
|
-
}
|
62
|
+
function isTerminal(request) {
|
63
|
+
return request.isVirtual || request.isNotFound || Boolean(request.resolvedTo);
|
69
64
|
}
|
65
|
+
const compatPattern = /#embroider_compat\/(?<type>[^\/]+)\/(?<rest>.*)/;
|
70
66
|
class Resolver {
|
71
67
|
constructor(options) {
|
72
68
|
this.options = options;
|
73
69
|
}
|
74
|
-
beforeResolve(request) {
|
70
|
+
async beforeResolve(request) {
|
75
71
|
if (request.specifier === '@embroider/macros') {
|
76
72
|
// the macros package is always handled directly within babel (not
|
77
73
|
// necessarily as a real resolvable package), so we should not mess with it.
|
@@ -79,9 +75,13 @@ class Resolver {
|
|
79
75
|
// why we need to know about it.
|
80
76
|
return logTransition('early exit', request);
|
81
77
|
}
|
78
|
+
if (request.specifier === 'require') {
|
79
|
+
return this.external('early require', request, request.specifier);
|
80
|
+
}
|
82
81
|
request = this.handleFastbootSwitch(request);
|
83
|
-
request = this.handleGlobalsCompat(request);
|
82
|
+
request = await this.handleGlobalsCompat(request);
|
84
83
|
request = this.handleImplicitModules(request);
|
84
|
+
request = this.handleImplicitTestScripts(request);
|
85
85
|
request = this.handleRenaming(request);
|
86
86
|
// we expect the specifier to be app relative at this point - must be after handleRenaming
|
87
87
|
request = this.generateFastbootSwitch(request);
|
@@ -96,95 +96,45 @@ class Resolver {
|
|
96
96
|
// that calls your build system's normal module resolver, this does both pre-
|
97
97
|
// and post-resolution adjustments as needed to implement our compatibility
|
98
98
|
// rules.
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
let
|
105
|
-
let out = gen.next();
|
106
|
-
while (!out.done) {
|
107
|
-
out = gen.next(await out.value);
|
108
|
-
}
|
109
|
-
return out.value;
|
110
|
-
}
|
111
|
-
// synchronous alternative to resolve() above. Because our own internals are
|
112
|
-
// all synchronous, you can use this if your defaultResolve function is
|
113
|
-
// synchronous.
|
114
|
-
resolveSync(request, defaultResolve) {
|
115
|
-
let gen = this.internalResolve(request, defaultResolve);
|
116
|
-
let out = gen.next();
|
117
|
-
while (!out.done) {
|
118
|
-
out = gen.next(out.value);
|
119
|
-
}
|
120
|
-
return out.value;
|
121
|
-
}
|
122
|
-
// Our core implementation is a generator so it can power both resolve() and
|
123
|
-
// resolveSync()
|
124
|
-
*internalResolve(request, defaultResolve) {
|
125
|
-
request = this.beforeResolve(request);
|
126
|
-
let resolution = yield defaultResolve(request);
|
99
|
+
async resolve(request) {
|
100
|
+
request = await this.beforeResolve(request);
|
101
|
+
if (request.resolvedTo) {
|
102
|
+
return request.resolvedTo;
|
103
|
+
}
|
104
|
+
let resolution = await request.defaultResolve();
|
127
105
|
switch (resolution.type) {
|
128
106
|
case 'found':
|
107
|
+
case 'ignored':
|
129
108
|
return resolution;
|
130
109
|
case 'not_found':
|
131
110
|
break;
|
132
111
|
default:
|
133
112
|
throw (0, assert_never_1.default)(resolution);
|
134
113
|
}
|
135
|
-
let nextRequest = this.fallbackResolve(request);
|
114
|
+
let nextRequest = await this.fallbackResolve(request);
|
136
115
|
if (nextRequest === request) {
|
137
116
|
// no additional fallback is available.
|
138
117
|
return resolution;
|
139
118
|
}
|
119
|
+
if (nextRequest.resolvedTo) {
|
120
|
+
return nextRequest.resolvedTo;
|
121
|
+
}
|
140
122
|
if (nextRequest.fromFile === request.fromFile && nextRequest.specifier === request.specifier) {
|
141
123
|
throw new Error('Bug Discovered! New request is not === original request but has the same fromFile and specifier. This will likely create a loop.');
|
142
124
|
}
|
143
|
-
if (nextRequest.isVirtual) {
|
144
|
-
// virtual requests are terminal, there is no more
|
145
|
-
// fallbackResolve around them. The defaultResolve is
|
146
|
-
// to implement them.
|
147
|
-
return
|
125
|
+
if (nextRequest.isVirtual || nextRequest.isNotFound) {
|
126
|
+
// virtual and NotFound requests are terminal, there is no more
|
127
|
+
// beforeResolve or fallbackResolve around them. The defaultResolve is
|
128
|
+
// expected to know how to implement them.
|
129
|
+
return nextRequest.defaultResolve();
|
148
130
|
}
|
149
|
-
return
|
131
|
+
return this.resolve(nextRequest);
|
150
132
|
}
|
151
133
|
// Use standard NodeJS resolving, with our required compatibility rules on
|
152
134
|
// top. This is a convenience method for calling resolveSync with the
|
153
135
|
// defaultResolve already configured to be "do the normal node thing".
|
154
|
-
nodeResolve(specifier, fromFile) {
|
155
|
-
|
156
|
-
if (request.isVirtual) {
|
157
|
-
return {
|
158
|
-
type: 'found',
|
159
|
-
result: {
|
160
|
-
type: 'virtual',
|
161
|
-
content: (0, virtual_content_1.virtualContent)(request.specifier, this),
|
162
|
-
filename: request.specifier,
|
163
|
-
},
|
164
|
-
};
|
165
|
-
}
|
166
|
-
try {
|
167
|
-
let filename = resolve_1.default.sync(request.specifier, {
|
168
|
-
basedir: (0, path_1.dirname)(request.fromFile),
|
169
|
-
extensions: this.options.resolvableExtensions,
|
170
|
-
});
|
171
|
-
return { type: 'found', result: { type: 'real', filename } };
|
172
|
-
}
|
173
|
-
catch (err) {
|
174
|
-
if (err.code !== 'MODULE_NOT_FOUND') {
|
175
|
-
throw err;
|
176
|
-
}
|
177
|
-
return { type: 'not_found', err };
|
178
|
-
}
|
179
|
-
});
|
180
|
-
switch (resolution.type) {
|
181
|
-
case 'not_found':
|
182
|
-
return resolution;
|
183
|
-
case 'found':
|
184
|
-
return resolution.result;
|
185
|
-
default:
|
186
|
-
throw (0, assert_never_1.default)(resolution);
|
187
|
-
}
|
136
|
+
async nodeResolve(specifier, fromFile) {
|
137
|
+
return (0, node_resolve_1.nodeResolve)(this, specifier, fromFile);
|
188
138
|
}
|
189
139
|
get packageCache() {
|
190
140
|
return shared_internals_2.RewrittenPackageCache.shared('embroider', this.options.appRoot);
|
@@ -201,6 +151,9 @@ class Resolver {
|
|
201
151
|
return owningPackage;
|
202
152
|
}
|
203
153
|
generateFastbootSwitch(request) {
|
154
|
+
if (isTerminal(request)) {
|
155
|
+
return request;
|
156
|
+
}
|
204
157
|
let pkg = this.packageCache.ownerOfFile(request.fromFile);
|
205
158
|
if (!pkg) {
|
206
159
|
return request;
|
@@ -218,7 +171,9 @@ class Resolver {
|
|
218
171
|
let fastbootFile = engineConfig.fastbootFiles[candidate];
|
219
172
|
if (fastbootFile) {
|
220
173
|
if (fastbootFile.shadowedFilename) {
|
221
|
-
let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)((0, path_1.resolve)(pkg.root, fastbootFile.shadowedFilename), 'utf8'), {
|
174
|
+
let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)((0, path_1.resolve)(pkg.root, fastbootFile.shadowedFilename), 'utf8'), {
|
175
|
+
configFile: false,
|
176
|
+
});
|
222
177
|
let switchFile = (0, virtual_content_1.fastbootSwitch)(candidate, (0, path_1.resolve)(pkg.root, 'package.json'), names);
|
223
178
|
if (switchFile === request.fromFile) {
|
224
179
|
return logTransition('internal lookup from fastbootSwitch', request);
|
@@ -237,6 +192,9 @@ class Resolver {
|
|
237
192
|
}
|
238
193
|
handleFastbootSwitch(request) {
|
239
194
|
var _a;
|
195
|
+
if (isTerminal(request)) {
|
196
|
+
return request;
|
197
|
+
}
|
240
198
|
let match = (0, virtual_content_1.decodeFastbootSwitch)(request.fromFile);
|
241
199
|
if (!match) {
|
242
200
|
return request;
|
@@ -275,12 +233,15 @@ class Resolver {
|
|
275
233
|
}
|
276
234
|
let entry = (_a = this.getEntryFromMergeMap(rel, pkg.root)) === null || _a === void 0 ? void 0 : _a.entry;
|
277
235
|
if ((entry === null || entry === void 0 ? void 0 : entry.type) === 'both') {
|
278
|
-
return logTransition('matched addon entry', request, request.alias(entry[section].
|
236
|
+
return logTransition('matched addon entry', request, request.alias(entry[section].specifier).rehome(entry[section].fromFile));
|
279
237
|
}
|
280
238
|
}
|
281
239
|
return logTransition('failed to match in fastboot switch', request);
|
282
240
|
}
|
283
241
|
handleImplicitModules(request) {
|
242
|
+
if (isTerminal(request)) {
|
243
|
+
return request;
|
244
|
+
}
|
284
245
|
let im = (0, virtual_content_1.decodeImplicitModules)(request.specifier);
|
285
246
|
if (!im) {
|
286
247
|
return request;
|
@@ -298,7 +259,26 @@ class Resolver {
|
|
298
259
|
return logTransition(`own implicit modules`, request, request.virtualize((0, path_1.resolve)(pkg.root, `-embroider-${im.type}.js`)));
|
299
260
|
}
|
300
261
|
}
|
301
|
-
|
262
|
+
handleImplicitTestScripts(request) {
|
263
|
+
//TODO move the extra forwardslash handling out into the vite plugin
|
264
|
+
const candidates = [
|
265
|
+
'@embroider/core/test-support.js',
|
266
|
+
'/@embroider/core/test-support.js',
|
267
|
+
'./@embroider/core/test-support.js',
|
268
|
+
];
|
269
|
+
if (!candidates.includes(request.specifier)) {
|
270
|
+
return request;
|
271
|
+
}
|
272
|
+
let pkg = this.packageCache.ownerOfFile(request.fromFile);
|
273
|
+
if ((pkg === null || pkg === void 0 ? void 0 : pkg.root) !== this.options.engines[0].root) {
|
274
|
+
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/core/test-support.js. If you think something should be fixed in Embroider, please open an issue on https://github.com/embroider-build/embroider/issues.`);
|
275
|
+
}
|
276
|
+
return logTransition('test-support', request, request.virtualize((0, path_1.resolve)(pkg.root, '-embroider-test-support.js')));
|
277
|
+
}
|
278
|
+
async handleGlobalsCompat(request) {
|
279
|
+
if (isTerminal(request)) {
|
280
|
+
return request;
|
281
|
+
}
|
302
282
|
let match = compatPattern.exec(request.specifier);
|
303
283
|
if (!match) {
|
304
284
|
return request;
|
@@ -326,52 +306,60 @@ class Resolver {
|
|
326
306
|
let target = this.parseGlobalPath(path, inEngine);
|
327
307
|
return logTransition('resolveHelper', request, request.alias(`${target.packageName}/helpers/${target.memberName}`).rehome((0, path_1.resolve)(inEngine.root, 'package.json')));
|
328
308
|
}
|
329
|
-
resolveComponent(path, inEngine, request) {
|
309
|
+
async resolveComponent(path, inEngine, request) {
|
330
310
|
let target = this.parseGlobalPath(path, inEngine);
|
331
311
|
let hbsModule = null;
|
332
312
|
let jsModule = null;
|
333
313
|
// first, the various places our template might be.
|
334
314
|
for (let candidate of this.componentTemplateCandidates(target.packageName)) {
|
335
|
-
let
|
336
|
-
|
337
|
-
|
315
|
+
let candidateSpecifier = `${target.packageName}${candidate.prefix}${target.memberName}${candidate.suffix}`;
|
316
|
+
let resolution = await this.resolve(request.alias(candidateSpecifier).rehome(target.from).withMeta({
|
317
|
+
runtimeFallback: false,
|
318
|
+
}));
|
319
|
+
if (resolution.type === 'found') {
|
320
|
+
hbsModule = resolution;
|
338
321
|
break;
|
339
322
|
}
|
340
323
|
}
|
341
324
|
// then the various places our javascript might be.
|
342
325
|
for (let candidate of this.componentJSCandidates(target.packageName)) {
|
343
|
-
let
|
326
|
+
let candidateSpecifier = `${target.packageName}${candidate.prefix}${target.memberName}${candidate.suffix}`;
|
327
|
+
let resolution = await this.resolve(request.alias(candidateSpecifier).rehome(target.from).withMeta({
|
328
|
+
runtimeFallback: false,
|
329
|
+
}));
|
344
330
|
// .hbs is a resolvable extension for us, so we need to exclude it here.
|
345
331
|
// It matches as a priority lower than .js, so finding an .hbs means
|
346
332
|
// there's definitely not a .js.
|
347
|
-
if (resolution.type === '
|
348
|
-
jsModule = resolution
|
333
|
+
if (resolution.type === 'found' && !resolution.filename.endsWith('.hbs')) {
|
334
|
+
jsModule = resolution;
|
349
335
|
break;
|
350
336
|
}
|
351
337
|
}
|
352
338
|
if (hbsModule) {
|
353
|
-
return logTransition(`resolveComponent found legacy HBS`, request, request.virtualize((0, virtual_content_1.virtualPairComponent)(hbsModule, jsModule)));
|
339
|
+
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)));
|
354
340
|
}
|
355
341
|
else if (jsModule) {
|
356
|
-
return logTransition(`resolveComponent found only JS`, request, request.
|
342
|
+
return logTransition(`resolving to resolveComponent found only JS`, request, request.resolveTo(jsModule));
|
357
343
|
}
|
358
344
|
else {
|
359
345
|
return logTransition(`resolveComponent failed`, request);
|
360
346
|
}
|
361
347
|
}
|
362
|
-
resolveHelperOrComponent(path, inEngine, request) {
|
348
|
+
async resolveHelperOrComponent(path, inEngine, request) {
|
363
349
|
// resolveHelper just rewrites our request to one that should target the
|
364
350
|
// component, so here to resolve the ambiguity we need to actually resolve
|
365
351
|
// that candidate to see if it works.
|
366
352
|
let helperCandidate = this.resolveHelper(path, inEngine, request);
|
367
|
-
let helperMatch = this.
|
368
|
-
|
369
|
-
|
353
|
+
let helperMatch = await this.resolve(request.alias(helperCandidate.specifier).rehome(helperCandidate.fromFile).withMeta({
|
354
|
+
runtimeFallback: false,
|
355
|
+
}));
|
356
|
+
if (helperMatch.type === 'found') {
|
357
|
+
return logTransition('resolve to ambiguous case matched a helper', request, request.resolveTo(helperMatch));
|
370
358
|
}
|
371
359
|
// unlike resolveHelper, resolveComponent already does pre-resolution in
|
372
360
|
// order to deal with its own internal ambiguity around JS vs HBS vs
|
373
361
|
// colocation.≥
|
374
|
-
let componentMatch = this.resolveComponent(path, inEngine, request);
|
362
|
+
let componentMatch = await this.resolveComponent(path, inEngine, request);
|
375
363
|
if (componentMatch !== request) {
|
376
364
|
return logTransition('ambiguous case matched a cmoponent', request, componentMatch);
|
377
365
|
}
|
@@ -396,6 +384,7 @@ class Resolver {
|
|
396
384
|
}
|
397
385
|
*componentJSCandidates(inPackageName) {
|
398
386
|
yield { prefix: '/components/', suffix: '' };
|
387
|
+
yield { prefix: '/components/', suffix: '/index' };
|
399
388
|
yield { prefix: '/components/', suffix: '/component' };
|
400
389
|
let pods = this.podPrefix(inPackageName);
|
401
390
|
if (pods) {
|
@@ -414,10 +403,10 @@ class Resolver {
|
|
414
403
|
parseGlobalPath(path, inEngine) {
|
415
404
|
let parts = path.split('@');
|
416
405
|
if (parts.length > 1 && parts[0].length > 0) {
|
417
|
-
return { packageName: parts[0], memberName: parts[1], from: (0, path_1.resolve)(inEngine.root, '
|
406
|
+
return { packageName: parts[0], memberName: parts[1], from: (0, path_1.resolve)(inEngine.root, 'package.json') };
|
418
407
|
}
|
419
408
|
else {
|
420
|
-
return { packageName: inEngine.packageName, memberName: path, from: (0, path_1.resolve)(inEngine.root, '
|
409
|
+
return { packageName: inEngine.packageName, memberName: path, from: (0, path_1.resolve)(inEngine.root, 'package.json') };
|
421
410
|
}
|
422
411
|
}
|
423
412
|
engineConfig(packageName) {
|
@@ -449,8 +438,8 @@ class Resolver {
|
|
449
438
|
engineModules.set(inEngineName, {
|
450
439
|
type: 'app-only',
|
451
440
|
'app-js': {
|
452
|
-
|
453
|
-
|
441
|
+
specifier: (0, reverse_exports_1.default)(addon.packageJSON, inAddonName),
|
442
|
+
fromFile: addonConfig.canResolveFromFile,
|
454
443
|
fromPackageName: addon.name,
|
455
444
|
},
|
456
445
|
});
|
@@ -463,8 +452,8 @@ class Resolver {
|
|
463
452
|
engineModules.set(inEngineName, {
|
464
453
|
type: 'both',
|
465
454
|
'app-js': {
|
466
|
-
|
467
|
-
|
455
|
+
specifier: (0, reverse_exports_1.default)(addon.packageJSON, inAddonName),
|
456
|
+
fromFile: addonConfig.canResolveFromFile,
|
468
457
|
fromPackageName: addon.name,
|
469
458
|
},
|
470
459
|
'fastboot-js': prevEntry['fastboot-js'],
|
@@ -488,8 +477,8 @@ class Resolver {
|
|
488
477
|
engineModules.set(inEngineName, {
|
489
478
|
type: 'fastboot-only',
|
490
479
|
'fastboot-js': {
|
491
|
-
|
492
|
-
|
480
|
+
specifier: (0, reverse_exports_1.default)(addon.packageJSON, inAddonName),
|
481
|
+
fromFile: addonConfig.canResolveFromFile,
|
493
482
|
fromPackageName: addon.name,
|
494
483
|
},
|
495
484
|
});
|
@@ -502,8 +491,8 @@ class Resolver {
|
|
502
491
|
engineModules.set(inEngineName, {
|
503
492
|
type: 'both',
|
504
493
|
'fastboot-js': {
|
505
|
-
|
506
|
-
|
494
|
+
specifier: (0, reverse_exports_1.default)(addon.packageJSON, inAddonName),
|
495
|
+
fromFile: addonConfig.canResolveFromFile,
|
507
496
|
fromPackageName: addon.name,
|
508
497
|
},
|
509
498
|
'app-js': prevEntry['app-js'],
|
@@ -525,7 +514,7 @@ class Resolver {
|
|
525
514
|
return owningEngine;
|
526
515
|
}
|
527
516
|
handleRewrittenPackages(request) {
|
528
|
-
if (request
|
517
|
+
if (isTerminal(request)) {
|
529
518
|
return request;
|
530
519
|
}
|
531
520
|
let requestingPkg = this.packageCache.ownerOfFile(request.fromFile);
|
@@ -544,10 +533,6 @@ class Resolver {
|
|
544
533
|
targetPkg = this.packageCache.resolve(packageName, requestingPkg);
|
545
534
|
}
|
546
535
|
catch (err) {
|
547
|
-
// this is not the place to report resolution failures. If the thing
|
548
|
-
// doesn't resolve, we're just not interested in redirecting it for
|
549
|
-
// backward-compat, that's all. The rest of the system will take care of
|
550
|
-
// reporting a failure to resolve (or handling it a different way)
|
551
536
|
if (err.code !== 'MODULE_NOT_FOUND') {
|
552
537
|
throw err;
|
553
538
|
}
|
@@ -563,14 +548,26 @@ class Resolver {
|
|
563
548
|
return logTransition('request targets a moved package', request, this.resolveWithinMovedPackage(request, targetPkg));
|
564
549
|
}
|
565
550
|
else if (originalRequestingPkg !== requestingPkg) {
|
566
|
-
|
567
|
-
|
568
|
-
|
551
|
+
if (targetPkg) {
|
552
|
+
// in this case, the requesting package is moved but its destination is
|
553
|
+
// not, so we need to rehome the request back to the original location.
|
554
|
+
return logTransition('outbound request from moved package', request, request
|
555
|
+
// setting meta here because if this fails, we want the fallback
|
556
|
+
// logic to revert our rehome and continue from the *moved* package.
|
557
|
+
.withMeta({ originalFromFile: request.fromFile })
|
558
|
+
.rehome((0, path_1.resolve)(originalRequestingPkg.root, 'package.json')));
|
559
|
+
}
|
560
|
+
else {
|
561
|
+
// requesting package was moved and we failed to find its target. We
|
562
|
+
// can't let that accidentally succeed in the defaultResolve because we
|
563
|
+
// could escape the moved package system.
|
564
|
+
return logTransition('missing outbound request from moved package', request, request.notFound());
|
565
|
+
}
|
569
566
|
}
|
570
567
|
return request;
|
571
568
|
}
|
572
569
|
handleRenaming(request) {
|
573
|
-
if (request
|
570
|
+
if (isTerminal(request)) {
|
574
571
|
return request;
|
575
572
|
}
|
576
573
|
let packageName = (0, shared_internals_1.packageName)(request.specifier);
|
@@ -603,12 +600,34 @@ class Resolver {
|
|
603
600
|
return logTransition(`renamePackages`, request, request.alias(request.specifier.replace(packageName, this.options.renamePackages[packageName])));
|
604
601
|
}
|
605
602
|
}
|
606
|
-
if (pkg.
|
607
|
-
// we found a self-import
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
603
|
+
if (pkg.name === packageName) {
|
604
|
+
// we found a self-import
|
605
|
+
if (pkg.meta['auto-upgraded']) {
|
606
|
+
// auto-upgraded packages always get automatically adjusted. They never
|
607
|
+
// supported fancy package.json exports features so this direct mapping
|
608
|
+
// to the root is always right.
|
609
|
+
// "my-package/foo" -> "./foo"
|
610
|
+
// "my-package" -> "./" (this can't be just "." because node's require.resolve doesn't reliable support that)
|
611
|
+
let selfImportPath = request.specifier === pkg.name ? './' : request.specifier.replace(pkg.name, '.');
|
612
|
+
return logTransition(`v1 self-import`, request, request.alias(selfImportPath).rehome((0, path_1.resolve)(pkg.root, 'package.json')));
|
613
|
+
}
|
614
|
+
else {
|
615
|
+
// v2 packages are supposed to use package.json `exports` to enable
|
616
|
+
// self-imports, but not all build tools actually follow the spec. This
|
617
|
+
// is a workaround for badly behaved packagers.
|
618
|
+
//
|
619
|
+
// Known upstream bugs this works around:
|
620
|
+
// - https://github.com/vitejs/vite/issues/9731
|
621
|
+
if (pkg.packageJSON.exports) {
|
622
|
+
let found = (0, resolve_exports_1.exports)(pkg.packageJSON, request.specifier, {
|
623
|
+
browser: true,
|
624
|
+
conditions: ['default', 'imports'],
|
625
|
+
});
|
626
|
+
if (found === null || found === void 0 ? void 0 : found[0]) {
|
627
|
+
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')));
|
628
|
+
}
|
629
|
+
}
|
630
|
+
}
|
612
631
|
}
|
613
632
|
return request;
|
614
633
|
}
|
@@ -617,16 +636,17 @@ class Resolver {
|
|
617
636
|
if (pkg.name.startsWith('@')) {
|
618
637
|
levels.push('..');
|
619
638
|
}
|
639
|
+
let originalFromFile = request.fromFile;
|
620
640
|
let newRequest = request.rehome((0, path_1.resolve)(pkg.root, ...levels, 'moved-package-target.js'));
|
621
641
|
if (newRequest === request) {
|
622
642
|
return request;
|
623
643
|
}
|
624
|
-
|
625
|
-
|
626
|
-
});
|
644
|
+
// setting meta because if this fails, we want the fallback to pick up back
|
645
|
+
// in the original requesting package.
|
646
|
+
return newRequest.withMeta({ originalFromFile });
|
627
647
|
}
|
628
648
|
preHandleExternal(request) {
|
629
|
-
if (request
|
649
|
+
if (isTerminal(request)) {
|
630
650
|
return request;
|
631
651
|
}
|
632
652
|
let { specifier, fromFile } = request;
|
@@ -659,7 +679,15 @@ class Resolver {
|
|
659
679
|
// engine
|
660
680
|
let logicalLocation = this.reverseSearchAppTree(pkg, request.fromFile);
|
661
681
|
if (logicalLocation) {
|
662
|
-
return logTransition('beforeResolve: relative import in app-js', request, request
|
682
|
+
return logTransition('beforeResolve: relative import in app-js', request, request
|
683
|
+
.alias('./' + path_1.posix.join((0, path_1.dirname)(logicalLocation.inAppName), request.specifier))
|
684
|
+
// it's important that we're rehoming this to the root of the engine
|
685
|
+
// (which we know really exists), and not to a subdir like
|
686
|
+
// logicalLocation.inAppName (which might not physically exist),
|
687
|
+
// because some environments (including node's require.resolve) will
|
688
|
+
// refuse to do resolution from a notional path that doesn't
|
689
|
+
// physically exist.
|
690
|
+
.rehome((0, path_1.resolve)(logicalLocation.owningEngine.root, 'package.json')));
|
663
691
|
}
|
664
692
|
return request;
|
665
693
|
}
|
@@ -674,11 +702,11 @@ class Resolver {
|
|
674
702
|
if (shared_internals_1.emberVirtualPeerDeps.has(packageName) && !pkg.hasDependency(packageName)) {
|
675
703
|
// addons (whether auto-upgraded or not) may use the app's
|
676
704
|
// emberVirtualPeerDeps, like "@glimmer/component" etc.
|
677
|
-
|
678
|
-
|
705
|
+
let addon = this.locateActiveAddon(packageName);
|
706
|
+
if (!addon) {
|
707
|
+
throw new Error(`${pkg.name} is trying to import the emberVirtualPeerDep "${packageName}", but it seems to be missing`);
|
679
708
|
}
|
680
|
-
|
681
|
-
return logTransition(`emberVirtualPeerDeps in v2 addon`, request, request.rehome(newHome));
|
709
|
+
return logTransition(`emberVirtualPeerDeps`, request, request.rehome(addon.canResolveFromFile));
|
682
710
|
}
|
683
711
|
// if this file is part of an addon's app-js, it's really the logical
|
684
712
|
// package to which it belongs (normally the app) that affects some policy
|
@@ -709,6 +737,22 @@ class Resolver {
|
|
709
737
|
}
|
710
738
|
return request;
|
711
739
|
}
|
740
|
+
locateActiveAddon(packageName) {
|
741
|
+
if (packageName === this.options.modulePrefix) {
|
742
|
+
// the app itself is something that addon's can classically resolve if they know it's name.
|
743
|
+
return {
|
744
|
+
root: this.options.appRoot,
|
745
|
+
canResolveFromFile: (0, path_1.resolve)(this.packageCache.maybeMoved(this.packageCache.get(this.options.appRoot)).root, 'package.json'),
|
746
|
+
};
|
747
|
+
}
|
748
|
+
for (let engine of this.options.engines) {
|
749
|
+
for (let addon of engine.activeAddons) {
|
750
|
+
if (addon.name === packageName) {
|
751
|
+
return addon;
|
752
|
+
}
|
753
|
+
}
|
754
|
+
}
|
755
|
+
}
|
712
756
|
external(label, request, specifier) {
|
713
757
|
if (this.options.amdCompatibility === 'cjs') {
|
714
758
|
let filename = (0, virtual_content_1.virtualExternalCJSModule)(specifier);
|
@@ -741,8 +785,11 @@ class Resolver {
|
|
741
785
|
throw new Error(`Embroider's amdCompatibility option is disabled, but something tried to use it to access "${request.specifier}"`);
|
742
786
|
}
|
743
787
|
}
|
744
|
-
fallbackResolve(request) {
|
788
|
+
async fallbackResolve(request) {
|
745
789
|
var _a, _b, _c;
|
790
|
+
if (request.isVirtual) {
|
791
|
+
throw new Error('Build tool bug detected! Fallback resolve should never see a virtual request. It is expected that the defaultResolve for your bundler has already resolved this request');
|
792
|
+
}
|
746
793
|
if (request.specifier === '@embroider/macros') {
|
747
794
|
// the macros package is always handled directly within babel (not
|
748
795
|
// necessarily as a real resolvable package), so we should not mess with it.
|
@@ -750,8 +797,7 @@ class Resolver {
|
|
750
797
|
// why we need to know about it.
|
751
798
|
return logTransition('fallback early exit', request);
|
752
799
|
}
|
753
|
-
|
754
|
-
if (compatPattern.test(specifier)) {
|
800
|
+
if (compatPattern.test(request.specifier)) {
|
755
801
|
// Some kinds of compat requests get rewritten into other things
|
756
802
|
// deterministically. For example, "#embroider_compat/helpers/whatever"
|
757
803
|
// means only "the-current-engine/helpers/whatever", and if that doesn't
|
@@ -767,39 +813,33 @@ class Resolver {
|
|
767
813
|
// here.
|
768
814
|
return request;
|
769
815
|
}
|
770
|
-
|
771
|
-
if (!((_a = request.meta) === null || _a === void 0 ? void 0 : _a.resolvedWithinPackage)) {
|
772
|
-
throw new Error(`bug: embroider resolver's meta is not propagating`);
|
773
|
-
}
|
774
|
-
fromFile = (0, path_1.resolve)((_b = request.meta) === null || _b === void 0 ? void 0 : _b.resolvedWithinPackage, 'package.json');
|
775
|
-
}
|
776
|
-
let pkg = this.packageCache.ownerOfFile(fromFile);
|
816
|
+
let pkg = this.packageCache.ownerOfFile(request.fromFile);
|
777
817
|
if (!pkg) {
|
778
818
|
return logTransition('no identifiable owningPackage', request);
|
779
819
|
}
|
780
|
-
//
|
781
|
-
// to
|
782
|
-
//
|
783
|
-
// isV2Ember()
|
820
|
+
// meta.originalFromFile gets set when we want to try to rehome a request
|
821
|
+
// but then come back to the original location here in the fallback when the
|
822
|
+
// rehomed request fails
|
784
823
|
let movedPkg = this.packageCache.maybeMoved(pkg);
|
785
824
|
if (movedPkg !== pkg) {
|
786
|
-
|
825
|
+
let originalFromFile = (_a = request.meta) === null || _a === void 0 ? void 0 : _a.originalFromFile;
|
826
|
+
if (typeof originalFromFile !== 'string') {
|
787
827
|
throw new Error(`bug: embroider resolver's meta is not propagating`);
|
788
828
|
}
|
789
|
-
|
829
|
+
request = request.rehome(originalFromFile);
|
790
830
|
pkg = movedPkg;
|
791
831
|
}
|
792
832
|
if (!pkg.isV2Ember()) {
|
793
833
|
return logTransition('fallbackResolve: not in an ember package', request);
|
794
834
|
}
|
795
|
-
let packageName = (0, shared_internals_1.packageName)(specifier);
|
835
|
+
let packageName = (0, shared_internals_1.packageName)(request.specifier);
|
796
836
|
if (!packageName) {
|
797
837
|
// this is a relative import
|
798
838
|
let withinEngine = this.engineConfig(pkg.name);
|
799
839
|
if (withinEngine) {
|
800
840
|
// it's a relative import inside an engine (which also means app), which
|
801
841
|
// means we may need to satisfy the request via app tree merging.
|
802
|
-
let appJSMatch = this.searchAppTree(request, withinEngine, (0, shared_internals_2.explicitRelative)(pkg.root, (0, path_1.resolve)((0, path_1.dirname)(fromFile), specifier)));
|
842
|
+
let appJSMatch = await this.searchAppTree(request, withinEngine, (0, shared_internals_2.explicitRelative)(pkg.root, (0, path_1.resolve)((0, path_1.dirname)(request.fromFile), request.specifier)));
|
803
843
|
if (appJSMatch) {
|
804
844
|
return logTransition('fallbackResolve: relative appJsMatch', request, appJSMatch);
|
805
845
|
}
|
@@ -813,40 +853,49 @@ class Resolver {
|
|
813
853
|
}
|
814
854
|
}
|
815
855
|
// auto-upgraded packages can fall back to the set of known active addons
|
816
|
-
if (pkg.meta['auto-upgraded']
|
817
|
-
|
818
|
-
if (
|
819
|
-
|
856
|
+
if (pkg.meta['auto-upgraded']) {
|
857
|
+
let addon = this.locateActiveAddon(packageName);
|
858
|
+
if (addon) {
|
859
|
+
const rehomed = request.rehome(addon.canResolveFromFile);
|
860
|
+
if (rehomed !== request) {
|
861
|
+
return logTransition(`activeAddons`, request, rehomed);
|
862
|
+
}
|
820
863
|
}
|
821
864
|
}
|
822
|
-
let logicalLocation = this.reverseSearchAppTree(pkg, fromFile);
|
865
|
+
let logicalLocation = this.reverseSearchAppTree(pkg, request.fromFile);
|
823
866
|
if (logicalLocation) {
|
824
867
|
// the requesting file is in an addon's appTree. We didn't succeed in
|
825
868
|
// resolving this (non-relative) request from inside the actual addon, so
|
826
869
|
// next try to resolve it from the corresponding logical location in the
|
827
870
|
// app.
|
828
|
-
return logTransition('fallbackResolve: retry from logical home of app-js file', request,
|
871
|
+
return logTransition('fallbackResolve: retry from logical home of app-js file', request,
|
872
|
+
// it might look more precise to rehome into logicalLocation.inAppName
|
873
|
+
// rather than package.json. But that logical location may not actually
|
874
|
+
// exist, and some systems (including node's require.resolve) will be
|
875
|
+
// mad about trying to resolve from notional paths that don't really
|
876
|
+
// exist.
|
877
|
+
request.rehome((0, path_1.resolve)(logicalLocation.owningEngine.root, 'package.json')));
|
829
878
|
}
|
830
879
|
let targetingEngine = this.engineConfig(packageName);
|
831
880
|
if (targetingEngine) {
|
832
|
-
let appJSMatch = this.searchAppTree(request, targetingEngine, specifier.replace(packageName, '.'));
|
881
|
+
let appJSMatch = await this.searchAppTree(request, targetingEngine, request.specifier.replace(packageName, '.'));
|
833
882
|
if (appJSMatch) {
|
834
883
|
return logTransition('fallbackResolve: non-relative appJsMatch', request, appJSMatch);
|
835
884
|
}
|
836
885
|
}
|
837
|
-
if (pkg.meta['auto-upgraded']) {
|
886
|
+
if (pkg.meta['auto-upgraded'] && ((_c = (_b = request.meta) === null || _b === void 0 ? void 0 : _b.runtimeFallback) !== null && _c !== void 0 ? _c : true)) {
|
838
887
|
// auto-upgraded packages can fall back to attempting to find dependencies at
|
839
888
|
// runtime. Native v2 packages can only get this behavior in the
|
840
889
|
// isExplicitlyExternal case above because they need to explicitly ask for
|
841
890
|
// externals.
|
842
|
-
return this.external('v1 catch-all fallback', request, specifier);
|
891
|
+
return this.external('v1 catch-all fallback', request, request.specifier);
|
843
892
|
}
|
844
893
|
else {
|
845
894
|
// native v2 packages don't automatically externalize *everything* the way
|
846
895
|
// auto-upgraded packages do, but they still externalize known and approved
|
847
896
|
// ember virtual packages (like @ember/component)
|
848
897
|
if (shared_internals_1.emberVirtualPackages.has(packageName)) {
|
849
|
-
return this.external('emberVirtualPackages', request, specifier);
|
898
|
+
return this.external('emberVirtualPackages', request, request.specifier);
|
850
899
|
}
|
851
900
|
}
|
852
901
|
// this is falling through with the original specifier which was
|
@@ -873,25 +922,23 @@ class Resolver {
|
|
873
922
|
}
|
874
923
|
}
|
875
924
|
}
|
876
|
-
searchAppTree(request, engine, inEngineSpecifier) {
|
925
|
+
async searchAppTree(request, engine, inEngineSpecifier) {
|
877
926
|
let matched = this.getEntryFromMergeMap(inEngineSpecifier, engine.root);
|
878
927
|
switch (matched === null || matched === void 0 ? void 0 : matched.entry.type) {
|
879
928
|
case undefined:
|
880
929
|
return undefined;
|
881
930
|
case 'app-only':
|
882
|
-
return request
|
883
|
-
.alias(matched.entry['app-js'].localPath)
|
884
|
-
.rehome((0, path_1.resolve)(matched.entry['app-js'].packageRoot, 'package.json'));
|
931
|
+
return request.alias(matched.entry['app-js'].specifier).rehome(matched.entry['app-js'].fromFile);
|
885
932
|
case 'fastboot-only':
|
886
|
-
return request
|
887
|
-
.alias(matched.entry['fastboot-js'].localPath)
|
888
|
-
.rehome((0, path_1.resolve)(matched.entry['fastboot-js'].packageRoot, 'package.json'));
|
933
|
+
return request.alias(matched.entry['fastboot-js'].specifier).rehome(matched.entry['fastboot-js'].fromFile);
|
889
934
|
case 'both':
|
890
|
-
let foundAppJS = this.
|
891
|
-
|
935
|
+
let foundAppJS = await this.resolve(request.alias(matched.entry['app-js'].specifier).rehome(matched.entry['app-js'].fromFile).withMeta({
|
936
|
+
runtimeFallback: false,
|
937
|
+
}));
|
938
|
+
if (foundAppJS.type !== 'found') {
|
892
939
|
throw new Error(`${matched.entry['app-js'].fromPackageName} declared ${inEngineSpecifier} in packageJSON.ember-addon.app-js, but that module does not exist`);
|
893
940
|
}
|
894
|
-
let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)(foundAppJS.filename, 'utf8'), {});
|
941
|
+
let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)(foundAppJS.filename, 'utf8'), { configFile: false });
|
895
942
|
return request.virtualize((0, virtual_content_1.fastbootSwitch)(matched.matched, (0, path_1.resolve)(engine.root, 'package.json'), names));
|
896
943
|
}
|
897
944
|
}
|