@embroider/core 3.4.7 → 3.4.8-unstable.445e96b
Sign up to get free protection for your applications and to get access to all the features.
- 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 +24 -15
- package/src/module-resolver.js +268 -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 +95 -38
- package/src/virtual-content.js.map +1 -1
- package/src/virtual-test-support-styles.d.ts +4 -0
- package/src/virtual-test-support-styles.js +65 -0
- package/src/virtual-test-support-styles.js.map +1 -0
- 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/src/virtual-vendor-styles.d.ts +4 -0
- package/src/virtual-vendor-styles.js +72 -0
- package/src/virtual-vendor-styles.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,15 @@ 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
|
+
request = this.handleVendorStyles(request);
|
86
|
+
request = this.handleTestSupportStyles(request);
|
85
87
|
request = this.handleRenaming(request);
|
86
88
|
// we expect the specifier to be app relative at this point - must be after handleRenaming
|
87
89
|
request = this.generateFastbootSwitch(request);
|
@@ -96,95 +98,45 @@ class Resolver {
|
|
96
98
|
// that calls your build system's normal module resolver, this does both pre-
|
97
99
|
// and post-resolution adjustments as needed to implement our compatibility
|
98
100
|
// 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);
|
101
|
+
async resolve(request) {
|
102
|
+
request = await this.beforeResolve(request);
|
103
|
+
if (request.resolvedTo) {
|
104
|
+
return request.resolvedTo;
|
105
|
+
}
|
106
|
+
let resolution = await request.defaultResolve();
|
127
107
|
switch (resolution.type) {
|
128
108
|
case 'found':
|
109
|
+
case 'ignored':
|
129
110
|
return resolution;
|
130
111
|
case 'not_found':
|
131
112
|
break;
|
132
113
|
default:
|
133
114
|
throw (0, assert_never_1.default)(resolution);
|
134
115
|
}
|
135
|
-
let nextRequest = this.fallbackResolve(request);
|
116
|
+
let nextRequest = await this.fallbackResolve(request);
|
136
117
|
if (nextRequest === request) {
|
137
118
|
// no additional fallback is available.
|
138
119
|
return resolution;
|
139
120
|
}
|
121
|
+
if (nextRequest.resolvedTo) {
|
122
|
+
return nextRequest.resolvedTo;
|
123
|
+
}
|
140
124
|
if (nextRequest.fromFile === request.fromFile && nextRequest.specifier === request.specifier) {
|
141
125
|
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
126
|
}
|
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
|
127
|
+
if (nextRequest.isVirtual || nextRequest.isNotFound) {
|
128
|
+
// virtual and NotFound requests are terminal, there is no more
|
129
|
+
// beforeResolve or fallbackResolve around them. The defaultResolve is
|
130
|
+
// expected to know how to implement them.
|
131
|
+
return nextRequest.defaultResolve();
|
148
132
|
}
|
149
|
-
return
|
133
|
+
return this.resolve(nextRequest);
|
150
134
|
}
|
151
135
|
// Use standard NodeJS resolving, with our required compatibility rules on
|
152
136
|
// top. This is a convenience method for calling resolveSync with the
|
153
137
|
// 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
|
-
}
|
138
|
+
async nodeResolve(specifier, fromFile) {
|
139
|
+
return (0, node_resolve_1.nodeResolve)(this, specifier, fromFile);
|
188
140
|
}
|
189
141
|
get packageCache() {
|
190
142
|
return shared_internals_2.RewrittenPackageCache.shared('embroider', this.options.appRoot);
|
@@ -201,6 +153,9 @@ class Resolver {
|
|
201
153
|
return owningPackage;
|
202
154
|
}
|
203
155
|
generateFastbootSwitch(request) {
|
156
|
+
if (isTerminal(request)) {
|
157
|
+
return request;
|
158
|
+
}
|
204
159
|
let pkg = this.packageCache.ownerOfFile(request.fromFile);
|
205
160
|
if (!pkg) {
|
206
161
|
return request;
|
@@ -218,7 +173,9 @@ class Resolver {
|
|
218
173
|
let fastbootFile = engineConfig.fastbootFiles[candidate];
|
219
174
|
if (fastbootFile) {
|
220
175
|
if (fastbootFile.shadowedFilename) {
|
221
|
-
let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)((0, path_1.resolve)(pkg.root, fastbootFile.shadowedFilename), 'utf8'), {
|
176
|
+
let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)((0, path_1.resolve)(pkg.root, fastbootFile.shadowedFilename), 'utf8'), {
|
177
|
+
configFile: false,
|
178
|
+
});
|
222
179
|
let switchFile = (0, virtual_content_1.fastbootSwitch)(candidate, (0, path_1.resolve)(pkg.root, 'package.json'), names);
|
223
180
|
if (switchFile === request.fromFile) {
|
224
181
|
return logTransition('internal lookup from fastbootSwitch', request);
|
@@ -237,6 +194,9 @@ class Resolver {
|
|
237
194
|
}
|
238
195
|
handleFastbootSwitch(request) {
|
239
196
|
var _a;
|
197
|
+
if (isTerminal(request)) {
|
198
|
+
return request;
|
199
|
+
}
|
240
200
|
let match = (0, virtual_content_1.decodeFastbootSwitch)(request.fromFile);
|
241
201
|
if (!match) {
|
242
202
|
return request;
|
@@ -275,12 +235,15 @@ class Resolver {
|
|
275
235
|
}
|
276
236
|
let entry = (_a = this.getEntryFromMergeMap(rel, pkg.root)) === null || _a === void 0 ? void 0 : _a.entry;
|
277
237
|
if ((entry === null || entry === void 0 ? void 0 : entry.type) === 'both') {
|
278
|
-
return logTransition('matched addon entry', request, request.alias(entry[section].
|
238
|
+
return logTransition('matched addon entry', request, request.alias(entry[section].specifier).rehome(entry[section].fromFile));
|
279
239
|
}
|
280
240
|
}
|
281
241
|
return logTransition('failed to match in fastboot switch', request);
|
282
242
|
}
|
283
243
|
handleImplicitModules(request) {
|
244
|
+
if (isTerminal(request)) {
|
245
|
+
return request;
|
246
|
+
}
|
284
247
|
let im = (0, virtual_content_1.decodeImplicitModules)(request.specifier);
|
285
248
|
if (!im) {
|
286
249
|
return request;
|
@@ -298,7 +261,42 @@ class Resolver {
|
|
298
261
|
return logTransition(`own implicit modules`, request, request.virtualize((0, path_1.resolve)(pkg.root, `-embroider-${im.type}.js`)));
|
299
262
|
}
|
300
263
|
}
|
301
|
-
|
264
|
+
handleImplicitTestScripts(request) {
|
265
|
+
//TODO move the extra forwardslash handling out into the vite plugin
|
266
|
+
const candidates = [
|
267
|
+
'@embroider/core/test-support.js',
|
268
|
+
'/@embroider/core/test-support.js',
|
269
|
+
'./@embroider/core/test-support.js',
|
270
|
+
];
|
271
|
+
if (!candidates.includes(request.specifier)) {
|
272
|
+
return request;
|
273
|
+
}
|
274
|
+
let pkg = this.packageCache.ownerOfFile(request.fromFile);
|
275
|
+
if ((pkg === null || pkg === void 0 ? void 0 : pkg.root) !== this.options.engines[0].root) {
|
276
|
+
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.`);
|
277
|
+
}
|
278
|
+
return logTransition('test-support', request, request.virtualize((0, path_1.resolve)(pkg.root, '-embroider-test-support.js')));
|
279
|
+
}
|
280
|
+
handleTestSupportStyles(request) {
|
281
|
+
//TODO move the extra forwardslash handling out into the vite plugin
|
282
|
+
const candidates = [
|
283
|
+
'@embroider/core/test-support.css',
|
284
|
+
'/@embroider/core/test-support.css',
|
285
|
+
'./@embroider/core/test-support.css',
|
286
|
+
];
|
287
|
+
if (!candidates.includes(request.specifier)) {
|
288
|
+
return request;
|
289
|
+
}
|
290
|
+
let pkg = this.packageCache.ownerOfFile(request.fromFile);
|
291
|
+
if ((pkg === null || pkg === void 0 ? void 0 : pkg.root) !== this.options.engines[0].root) {
|
292
|
+
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.css. If you think something should be fixed in Embroider, please open an issue on https://github.com/embroider-build/embroider/issues.`);
|
293
|
+
}
|
294
|
+
return logTransition('test-support-styles', request, request.virtualize((0, path_1.resolve)(pkg.root, '-embroider-test-support-styles.css')));
|
295
|
+
}
|
296
|
+
async handleGlobalsCompat(request) {
|
297
|
+
if (isTerminal(request)) {
|
298
|
+
return request;
|
299
|
+
}
|
302
300
|
let match = compatPattern.exec(request.specifier);
|
303
301
|
if (!match) {
|
304
302
|
return request;
|
@@ -322,56 +320,76 @@ class Resolver {
|
|
322
320
|
throw new Error(`bug: unexepected #embroider_compat specifier: ${request.specifier}`);
|
323
321
|
}
|
324
322
|
}
|
323
|
+
handleVendorStyles(request) {
|
324
|
+
//TODO move the extra forwardslash handling out into the vite plugin
|
325
|
+
const candidates = ['@embroider/core/vendor.css', '/@embroider/core/vendor.css', './@embroider/core/vendor.css'];
|
326
|
+
if (!candidates.includes(request.specifier)) {
|
327
|
+
return request;
|
328
|
+
}
|
329
|
+
let pkg = this.packageCache.ownerOfFile(request.fromFile);
|
330
|
+
if ((pkg === null || pkg === void 0 ? void 0 : pkg.root) !== this.options.engines[0].root) {
|
331
|
+
throw new Error(`bug: found an import of ${request.specifier} in ${request.fromFile}, but this is not the top-level Ember app. The top-level Ember app is the only one that has support for @embroider/core/vendor.css. If you think something should be fixed in Embroider, please open an issue on https://github.com/embroider-build/embroider/issues.`);
|
332
|
+
}
|
333
|
+
return logTransition('vendor-styles', request, request.virtualize((0, path_1.resolve)(pkg.root, '-embroider-vendor-styles.css')));
|
334
|
+
}
|
325
335
|
resolveHelper(path, inEngine, request) {
|
326
336
|
let target = this.parseGlobalPath(path, inEngine);
|
327
337
|
return logTransition('resolveHelper', request, request.alias(`${target.packageName}/helpers/${target.memberName}`).rehome((0, path_1.resolve)(inEngine.root, 'package.json')));
|
328
338
|
}
|
329
|
-
resolveComponent(path, inEngine, request) {
|
339
|
+
async resolveComponent(path, inEngine, request) {
|
330
340
|
let target = this.parseGlobalPath(path, inEngine);
|
331
341
|
let hbsModule = null;
|
332
342
|
let jsModule = null;
|
333
343
|
// first, the various places our template might be.
|
334
344
|
for (let candidate of this.componentTemplateCandidates(target.packageName)) {
|
335
|
-
let
|
336
|
-
|
337
|
-
|
345
|
+
let candidateSpecifier = `${target.packageName}${candidate.prefix}${target.memberName}${candidate.suffix}`;
|
346
|
+
let resolution = await this.resolve(request.alias(candidateSpecifier).rehome(target.from).withMeta({
|
347
|
+
runtimeFallback: false,
|
348
|
+
}));
|
349
|
+
if (resolution.type === 'found') {
|
350
|
+
hbsModule = resolution;
|
338
351
|
break;
|
339
352
|
}
|
340
353
|
}
|
341
354
|
// then the various places our javascript might be.
|
342
355
|
for (let candidate of this.componentJSCandidates(target.packageName)) {
|
343
|
-
let
|
356
|
+
let candidateSpecifier = `${target.packageName}${candidate.prefix}${target.memberName}${candidate.suffix}`;
|
357
|
+
let resolution = await this.resolve(request.alias(candidateSpecifier).rehome(target.from).withMeta({
|
358
|
+
runtimeFallback: false,
|
359
|
+
}));
|
344
360
|
// .hbs is a resolvable extension for us, so we need to exclude it here.
|
345
361
|
// It matches as a priority lower than .js, so finding an .hbs means
|
346
362
|
// there's definitely not a .js.
|
347
|
-
if (resolution.type === '
|
348
|
-
jsModule = resolution
|
363
|
+
if (resolution.type === 'found' && !resolution.filename.endsWith('.hbs')) {
|
364
|
+
jsModule = resolution;
|
349
365
|
break;
|
350
366
|
}
|
351
367
|
}
|
352
368
|
if (hbsModule) {
|
353
|
-
return logTransition(`resolveComponent found legacy HBS`, request, request.virtualize((0, virtual_content_1.virtualPairComponent)(hbsModule, jsModule)));
|
369
|
+
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
370
|
}
|
355
371
|
else if (jsModule) {
|
356
|
-
return logTransition(`resolveComponent found only JS`, request, request.
|
372
|
+
return logTransition(`resolving to resolveComponent found only JS`, request, request.resolveTo(jsModule));
|
357
373
|
}
|
358
374
|
else {
|
359
375
|
return logTransition(`resolveComponent failed`, request);
|
360
376
|
}
|
361
377
|
}
|
362
|
-
resolveHelperOrComponent(path, inEngine, request) {
|
378
|
+
async resolveHelperOrComponent(path, inEngine, request) {
|
363
379
|
// resolveHelper just rewrites our request to one that should target the
|
364
380
|
// component, so here to resolve the ambiguity we need to actually resolve
|
365
381
|
// that candidate to see if it works.
|
366
382
|
let helperCandidate = this.resolveHelper(path, inEngine, request);
|
367
|
-
let helperMatch = this.
|
368
|
-
|
369
|
-
|
383
|
+
let helperMatch = await this.resolve(request.alias(helperCandidate.specifier).rehome(helperCandidate.fromFile).withMeta({
|
384
|
+
runtimeFallback: false,
|
385
|
+
}));
|
386
|
+
if (helperMatch.type === 'found') {
|
387
|
+
return logTransition('resolve to ambiguous case matched a helper', request, request.resolveTo(helperMatch));
|
370
388
|
}
|
371
389
|
// unlike resolveHelper, resolveComponent already does pre-resolution in
|
372
390
|
// order to deal with its own internal ambiguity around JS vs HBS vs
|
373
391
|
// colocation.≥
|
374
|
-
let componentMatch = this.resolveComponent(path, inEngine, request);
|
392
|
+
let componentMatch = await this.resolveComponent(path, inEngine, request);
|
375
393
|
if (componentMatch !== request) {
|
376
394
|
return logTransition('ambiguous case matched a cmoponent', request, componentMatch);
|
377
395
|
}
|
@@ -396,6 +414,7 @@ class Resolver {
|
|
396
414
|
}
|
397
415
|
*componentJSCandidates(inPackageName) {
|
398
416
|
yield { prefix: '/components/', suffix: '' };
|
417
|
+
yield { prefix: '/components/', suffix: '/index' };
|
399
418
|
yield { prefix: '/components/', suffix: '/component' };
|
400
419
|
let pods = this.podPrefix(inPackageName);
|
401
420
|
if (pods) {
|
@@ -414,10 +433,10 @@ class Resolver {
|
|
414
433
|
parseGlobalPath(path, inEngine) {
|
415
434
|
let parts = path.split('@');
|
416
435
|
if (parts.length > 1 && parts[0].length > 0) {
|
417
|
-
return { packageName: parts[0], memberName: parts[1], from: (0, path_1.resolve)(inEngine.root, '
|
436
|
+
return { packageName: parts[0], memberName: parts[1], from: (0, path_1.resolve)(inEngine.root, 'package.json') };
|
418
437
|
}
|
419
438
|
else {
|
420
|
-
return { packageName: inEngine.packageName, memberName: path, from: (0, path_1.resolve)(inEngine.root, '
|
439
|
+
return { packageName: inEngine.packageName, memberName: path, from: (0, path_1.resolve)(inEngine.root, 'package.json') };
|
421
440
|
}
|
422
441
|
}
|
423
442
|
engineConfig(packageName) {
|
@@ -449,8 +468,8 @@ class Resolver {
|
|
449
468
|
engineModules.set(inEngineName, {
|
450
469
|
type: 'app-only',
|
451
470
|
'app-js': {
|
452
|
-
|
453
|
-
|
471
|
+
specifier: (0, reverse_exports_1.default)(addon.packageJSON, inAddonName),
|
472
|
+
fromFile: addonConfig.canResolveFromFile,
|
454
473
|
fromPackageName: addon.name,
|
455
474
|
},
|
456
475
|
});
|
@@ -463,8 +482,8 @@ class Resolver {
|
|
463
482
|
engineModules.set(inEngineName, {
|
464
483
|
type: 'both',
|
465
484
|
'app-js': {
|
466
|
-
|
467
|
-
|
485
|
+
specifier: (0, reverse_exports_1.default)(addon.packageJSON, inAddonName),
|
486
|
+
fromFile: addonConfig.canResolveFromFile,
|
468
487
|
fromPackageName: addon.name,
|
469
488
|
},
|
470
489
|
'fastboot-js': prevEntry['fastboot-js'],
|
@@ -488,8 +507,8 @@ class Resolver {
|
|
488
507
|
engineModules.set(inEngineName, {
|
489
508
|
type: 'fastboot-only',
|
490
509
|
'fastboot-js': {
|
491
|
-
|
492
|
-
|
510
|
+
specifier: (0, reverse_exports_1.default)(addon.packageJSON, inAddonName),
|
511
|
+
fromFile: addonConfig.canResolveFromFile,
|
493
512
|
fromPackageName: addon.name,
|
494
513
|
},
|
495
514
|
});
|
@@ -502,8 +521,8 @@ class Resolver {
|
|
502
521
|
engineModules.set(inEngineName, {
|
503
522
|
type: 'both',
|
504
523
|
'fastboot-js': {
|
505
|
-
|
506
|
-
|
524
|
+
specifier: (0, reverse_exports_1.default)(addon.packageJSON, inAddonName),
|
525
|
+
fromFile: addonConfig.canResolveFromFile,
|
507
526
|
fromPackageName: addon.name,
|
508
527
|
},
|
509
528
|
'app-js': prevEntry['app-js'],
|
@@ -525,7 +544,7 @@ class Resolver {
|
|
525
544
|
return owningEngine;
|
526
545
|
}
|
527
546
|
handleRewrittenPackages(request) {
|
528
|
-
if (request
|
547
|
+
if (isTerminal(request)) {
|
529
548
|
return request;
|
530
549
|
}
|
531
550
|
let requestingPkg = this.packageCache.ownerOfFile(request.fromFile);
|
@@ -544,10 +563,6 @@ class Resolver {
|
|
544
563
|
targetPkg = this.packageCache.resolve(packageName, requestingPkg);
|
545
564
|
}
|
546
565
|
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
566
|
if (err.code !== 'MODULE_NOT_FOUND') {
|
552
567
|
throw err;
|
553
568
|
}
|
@@ -563,14 +578,26 @@ class Resolver {
|
|
563
578
|
return logTransition('request targets a moved package', request, this.resolveWithinMovedPackage(request, targetPkg));
|
564
579
|
}
|
565
580
|
else if (originalRequestingPkg !== requestingPkg) {
|
566
|
-
|
567
|
-
|
568
|
-
|
581
|
+
if (targetPkg) {
|
582
|
+
// in this case, the requesting package is moved but its destination is
|
583
|
+
// not, so we need to rehome the request back to the original location.
|
584
|
+
return logTransition('outbound request from moved package', request, request
|
585
|
+
// setting meta here because if this fails, we want the fallback
|
586
|
+
// logic to revert our rehome and continue from the *moved* package.
|
587
|
+
.withMeta({ originalFromFile: request.fromFile })
|
588
|
+
.rehome((0, path_1.resolve)(originalRequestingPkg.root, 'package.json')));
|
589
|
+
}
|
590
|
+
else {
|
591
|
+
// requesting package was moved and we failed to find its target. We
|
592
|
+
// can't let that accidentally succeed in the defaultResolve because we
|
593
|
+
// could escape the moved package system.
|
594
|
+
return logTransition('missing outbound request from moved package', request, request.notFound());
|
595
|
+
}
|
569
596
|
}
|
570
597
|
return request;
|
571
598
|
}
|
572
599
|
handleRenaming(request) {
|
573
|
-
if (request
|
600
|
+
if (isTerminal(request)) {
|
574
601
|
return request;
|
575
602
|
}
|
576
603
|
let packageName = (0, shared_internals_1.packageName)(request.specifier);
|
@@ -603,12 +630,34 @@ class Resolver {
|
|
603
630
|
return logTransition(`renamePackages`, request, request.alias(request.specifier.replace(packageName, this.options.renamePackages[packageName])));
|
604
631
|
}
|
605
632
|
}
|
606
|
-
if (pkg.
|
607
|
-
// we found a self-import
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
633
|
+
if (pkg.name === packageName) {
|
634
|
+
// we found a self-import
|
635
|
+
if (pkg.meta['auto-upgraded']) {
|
636
|
+
// auto-upgraded packages always get automatically adjusted. They never
|
637
|
+
// supported fancy package.json exports features so this direct mapping
|
638
|
+
// to the root is always right.
|
639
|
+
// "my-package/foo" -> "./foo"
|
640
|
+
// "my-package" -> "./" (this can't be just "." because node's require.resolve doesn't reliable support that)
|
641
|
+
let selfImportPath = request.specifier === pkg.name ? './' : request.specifier.replace(pkg.name, '.');
|
642
|
+
return logTransition(`v1 self-import`, request, request.alias(selfImportPath).rehome((0, path_1.resolve)(pkg.root, 'package.json')));
|
643
|
+
}
|
644
|
+
else {
|
645
|
+
// v2 packages are supposed to use package.json `exports` to enable
|
646
|
+
// self-imports, but not all build tools actually follow the spec. This
|
647
|
+
// is a workaround for badly behaved packagers.
|
648
|
+
//
|
649
|
+
// Known upstream bugs this works around:
|
650
|
+
// - https://github.com/vitejs/vite/issues/9731
|
651
|
+
if (pkg.packageJSON.exports) {
|
652
|
+
let found = (0, resolve_exports_1.exports)(pkg.packageJSON, request.specifier, {
|
653
|
+
browser: true,
|
654
|
+
conditions: ['default', 'imports'],
|
655
|
+
});
|
656
|
+
if (found === null || found === void 0 ? void 0 : found[0]) {
|
657
|
+
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')));
|
658
|
+
}
|
659
|
+
}
|
660
|
+
}
|
612
661
|
}
|
613
662
|
return request;
|
614
663
|
}
|
@@ -617,16 +666,17 @@ class Resolver {
|
|
617
666
|
if (pkg.name.startsWith('@')) {
|
618
667
|
levels.push('..');
|
619
668
|
}
|
669
|
+
let originalFromFile = request.fromFile;
|
620
670
|
let newRequest = request.rehome((0, path_1.resolve)(pkg.root, ...levels, 'moved-package-target.js'));
|
621
671
|
if (newRequest === request) {
|
622
672
|
return request;
|
623
673
|
}
|
624
|
-
|
625
|
-
|
626
|
-
});
|
674
|
+
// setting meta because if this fails, we want the fallback to pick up back
|
675
|
+
// in the original requesting package.
|
676
|
+
return newRequest.withMeta({ originalFromFile });
|
627
677
|
}
|
628
678
|
preHandleExternal(request) {
|
629
|
-
if (request
|
679
|
+
if (isTerminal(request)) {
|
630
680
|
return request;
|
631
681
|
}
|
632
682
|
let { specifier, fromFile } = request;
|
@@ -659,7 +709,15 @@ class Resolver {
|
|
659
709
|
// engine
|
660
710
|
let logicalLocation = this.reverseSearchAppTree(pkg, request.fromFile);
|
661
711
|
if (logicalLocation) {
|
662
|
-
return logTransition('beforeResolve: relative import in app-js', request, request
|
712
|
+
return logTransition('beforeResolve: relative import in app-js', request, request
|
713
|
+
.alias('./' + path_1.posix.join((0, path_1.dirname)(logicalLocation.inAppName), request.specifier))
|
714
|
+
// it's important that we're rehoming this to the root of the engine
|
715
|
+
// (which we know really exists), and not to a subdir like
|
716
|
+
// logicalLocation.inAppName (which might not physically exist),
|
717
|
+
// because some environments (including node's require.resolve) will
|
718
|
+
// refuse to do resolution from a notional path that doesn't
|
719
|
+
// physically exist.
|
720
|
+
.rehome((0, path_1.resolve)(logicalLocation.owningEngine.root, 'package.json')));
|
663
721
|
}
|
664
722
|
return request;
|
665
723
|
}
|
@@ -674,11 +732,11 @@ class Resolver {
|
|
674
732
|
if (shared_internals_1.emberVirtualPeerDeps.has(packageName) && !pkg.hasDependency(packageName)) {
|
675
733
|
// addons (whether auto-upgraded or not) may use the app's
|
676
734
|
// emberVirtualPeerDeps, like "@glimmer/component" etc.
|
677
|
-
|
678
|
-
|
735
|
+
let addon = this.locateActiveAddon(packageName);
|
736
|
+
if (!addon) {
|
737
|
+
throw new Error(`${pkg.name} is trying to import the emberVirtualPeerDep "${packageName}", but it seems to be missing`);
|
679
738
|
}
|
680
|
-
|
681
|
-
return logTransition(`emberVirtualPeerDeps in v2 addon`, request, request.rehome(newHome));
|
739
|
+
return logTransition(`emberVirtualPeerDeps`, request, request.rehome(addon.canResolveFromFile));
|
682
740
|
}
|
683
741
|
// if this file is part of an addon's app-js, it's really the logical
|
684
742
|
// package to which it belongs (normally the app) that affects some policy
|
@@ -709,6 +767,22 @@ class Resolver {
|
|
709
767
|
}
|
710
768
|
return request;
|
711
769
|
}
|
770
|
+
locateActiveAddon(packageName) {
|
771
|
+
if (packageName === this.options.modulePrefix) {
|
772
|
+
// the app itself is something that addon's can classically resolve if they know it's name.
|
773
|
+
return {
|
774
|
+
root: this.options.appRoot,
|
775
|
+
canResolveFromFile: (0, path_1.resolve)(this.packageCache.maybeMoved(this.packageCache.get(this.options.appRoot)).root, 'package.json'),
|
776
|
+
};
|
777
|
+
}
|
778
|
+
for (let engine of this.options.engines) {
|
779
|
+
for (let addon of engine.activeAddons) {
|
780
|
+
if (addon.name === packageName) {
|
781
|
+
return addon;
|
782
|
+
}
|
783
|
+
}
|
784
|
+
}
|
785
|
+
}
|
712
786
|
external(label, request, specifier) {
|
713
787
|
if (this.options.amdCompatibility === 'cjs') {
|
714
788
|
let filename = (0, virtual_content_1.virtualExternalCJSModule)(specifier);
|
@@ -741,8 +815,11 @@ class Resolver {
|
|
741
815
|
throw new Error(`Embroider's amdCompatibility option is disabled, but something tried to use it to access "${request.specifier}"`);
|
742
816
|
}
|
743
817
|
}
|
744
|
-
fallbackResolve(request) {
|
818
|
+
async fallbackResolve(request) {
|
745
819
|
var _a, _b, _c;
|
820
|
+
if (request.isVirtual) {
|
821
|
+
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');
|
822
|
+
}
|
746
823
|
if (request.specifier === '@embroider/macros') {
|
747
824
|
// the macros package is always handled directly within babel (not
|
748
825
|
// necessarily as a real resolvable package), so we should not mess with it.
|
@@ -750,8 +827,7 @@ class Resolver {
|
|
750
827
|
// why we need to know about it.
|
751
828
|
return logTransition('fallback early exit', request);
|
752
829
|
}
|
753
|
-
|
754
|
-
if (compatPattern.test(specifier)) {
|
830
|
+
if (compatPattern.test(request.specifier)) {
|
755
831
|
// Some kinds of compat requests get rewritten into other things
|
756
832
|
// deterministically. For example, "#embroider_compat/helpers/whatever"
|
757
833
|
// means only "the-current-engine/helpers/whatever", and if that doesn't
|
@@ -767,39 +843,33 @@ class Resolver {
|
|
767
843
|
// here.
|
768
844
|
return request;
|
769
845
|
}
|
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);
|
846
|
+
let pkg = this.packageCache.ownerOfFile(request.fromFile);
|
777
847
|
if (!pkg) {
|
778
848
|
return logTransition('no identifiable owningPackage', request);
|
779
849
|
}
|
780
|
-
//
|
781
|
-
// to
|
782
|
-
//
|
783
|
-
// isV2Ember()
|
850
|
+
// meta.originalFromFile gets set when we want to try to rehome a request
|
851
|
+
// but then come back to the original location here in the fallback when the
|
852
|
+
// rehomed request fails
|
784
853
|
let movedPkg = this.packageCache.maybeMoved(pkg);
|
785
854
|
if (movedPkg !== pkg) {
|
786
|
-
|
855
|
+
let originalFromFile = (_a = request.meta) === null || _a === void 0 ? void 0 : _a.originalFromFile;
|
856
|
+
if (typeof originalFromFile !== 'string') {
|
787
857
|
throw new Error(`bug: embroider resolver's meta is not propagating`);
|
788
858
|
}
|
789
|
-
|
859
|
+
request = request.rehome(originalFromFile);
|
790
860
|
pkg = movedPkg;
|
791
861
|
}
|
792
862
|
if (!pkg.isV2Ember()) {
|
793
863
|
return logTransition('fallbackResolve: not in an ember package', request);
|
794
864
|
}
|
795
|
-
let packageName = (0, shared_internals_1.packageName)(specifier);
|
865
|
+
let packageName = (0, shared_internals_1.packageName)(request.specifier);
|
796
866
|
if (!packageName) {
|
797
867
|
// this is a relative import
|
798
868
|
let withinEngine = this.engineConfig(pkg.name);
|
799
869
|
if (withinEngine) {
|
800
870
|
// it's a relative import inside an engine (which also means app), which
|
801
871
|
// 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)));
|
872
|
+
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
873
|
if (appJSMatch) {
|
804
874
|
return logTransition('fallbackResolve: relative appJsMatch', request, appJSMatch);
|
805
875
|
}
|
@@ -813,40 +883,49 @@ class Resolver {
|
|
813
883
|
}
|
814
884
|
}
|
815
885
|
// auto-upgraded packages can fall back to the set of known active addons
|
816
|
-
if (pkg.meta['auto-upgraded']
|
817
|
-
|
818
|
-
if (
|
819
|
-
|
886
|
+
if (pkg.meta['auto-upgraded']) {
|
887
|
+
let addon = this.locateActiveAddon(packageName);
|
888
|
+
if (addon) {
|
889
|
+
const rehomed = request.rehome(addon.canResolveFromFile);
|
890
|
+
if (rehomed !== request) {
|
891
|
+
return logTransition(`activeAddons`, request, rehomed);
|
892
|
+
}
|
820
893
|
}
|
821
894
|
}
|
822
|
-
let logicalLocation = this.reverseSearchAppTree(pkg, fromFile);
|
895
|
+
let logicalLocation = this.reverseSearchAppTree(pkg, request.fromFile);
|
823
896
|
if (logicalLocation) {
|
824
897
|
// the requesting file is in an addon's appTree. We didn't succeed in
|
825
898
|
// resolving this (non-relative) request from inside the actual addon, so
|
826
899
|
// next try to resolve it from the corresponding logical location in the
|
827
900
|
// app.
|
828
|
-
return logTransition('fallbackResolve: retry from logical home of app-js file', request,
|
901
|
+
return logTransition('fallbackResolve: retry from logical home of app-js file', request,
|
902
|
+
// it might look more precise to rehome into logicalLocation.inAppName
|
903
|
+
// rather than package.json. But that logical location may not actually
|
904
|
+
// exist, and some systems (including node's require.resolve) will be
|
905
|
+
// mad about trying to resolve from notional paths that don't really
|
906
|
+
// exist.
|
907
|
+
request.rehome((0, path_1.resolve)(logicalLocation.owningEngine.root, 'package.json')));
|
829
908
|
}
|
830
909
|
let targetingEngine = this.engineConfig(packageName);
|
831
910
|
if (targetingEngine) {
|
832
|
-
let appJSMatch = this.searchAppTree(request, targetingEngine, specifier.replace(packageName, '.'));
|
911
|
+
let appJSMatch = await this.searchAppTree(request, targetingEngine, request.specifier.replace(packageName, '.'));
|
833
912
|
if (appJSMatch) {
|
834
913
|
return logTransition('fallbackResolve: non-relative appJsMatch', request, appJSMatch);
|
835
914
|
}
|
836
915
|
}
|
837
|
-
if (pkg.meta['auto-upgraded']) {
|
916
|
+
if (pkg.meta['auto-upgraded'] && ((_c = (_b = request.meta) === null || _b === void 0 ? void 0 : _b.runtimeFallback) !== null && _c !== void 0 ? _c : true)) {
|
838
917
|
// auto-upgraded packages can fall back to attempting to find dependencies at
|
839
918
|
// runtime. Native v2 packages can only get this behavior in the
|
840
919
|
// isExplicitlyExternal case above because they need to explicitly ask for
|
841
920
|
// externals.
|
842
|
-
return this.external('v1 catch-all fallback', request, specifier);
|
921
|
+
return this.external('v1 catch-all fallback', request, request.specifier);
|
843
922
|
}
|
844
923
|
else {
|
845
924
|
// native v2 packages don't automatically externalize *everything* the way
|
846
925
|
// auto-upgraded packages do, but they still externalize known and approved
|
847
926
|
// ember virtual packages (like @ember/component)
|
848
927
|
if (shared_internals_1.emberVirtualPackages.has(packageName)) {
|
849
|
-
return this.external('emberVirtualPackages', request, specifier);
|
928
|
+
return this.external('emberVirtualPackages', request, request.specifier);
|
850
929
|
}
|
851
930
|
}
|
852
931
|
// this is falling through with the original specifier which was
|
@@ -873,25 +952,23 @@ class Resolver {
|
|
873
952
|
}
|
874
953
|
}
|
875
954
|
}
|
876
|
-
searchAppTree(request, engine, inEngineSpecifier) {
|
955
|
+
async searchAppTree(request, engine, inEngineSpecifier) {
|
877
956
|
let matched = this.getEntryFromMergeMap(inEngineSpecifier, engine.root);
|
878
957
|
switch (matched === null || matched === void 0 ? void 0 : matched.entry.type) {
|
879
958
|
case undefined:
|
880
959
|
return undefined;
|
881
960
|
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'));
|
961
|
+
return request.alias(matched.entry['app-js'].specifier).rehome(matched.entry['app-js'].fromFile);
|
885
962
|
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'));
|
963
|
+
return request.alias(matched.entry['fastboot-js'].specifier).rehome(matched.entry['fastboot-js'].fromFile);
|
889
964
|
case 'both':
|
890
|
-
let foundAppJS = this.
|
891
|
-
|
965
|
+
let foundAppJS = await this.resolve(request.alias(matched.entry['app-js'].specifier).rehome(matched.entry['app-js'].fromFile).withMeta({
|
966
|
+
runtimeFallback: false,
|
967
|
+
}));
|
968
|
+
if (foundAppJS.type !== 'found') {
|
892
969
|
throw new Error(`${matched.entry['app-js'].fromPackageName} declared ${inEngineSpecifier} in packageJSON.ember-addon.app-js, but that module does not exist`);
|
893
970
|
}
|
894
|
-
let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)(foundAppJS.filename, 'utf8'), {});
|
971
|
+
let { names } = (0, describe_exports_1.describeExports)((0, fs_1.readFileSync)(foundAppJS.filename, 'utf8'), { configFile: false });
|
895
972
|
return request.virtualize((0, virtual_content_1.fastbootSwitch)(matched.matched, (0, path_1.resolve)(engine.root, 'package.json'), names));
|
896
973
|
}
|
897
974
|
}
|