@lwrjs/loader 0.10.0-alpha.2 → 0.10.0-alpha.20
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/build/assets/prod/lwr-error-shim.js +2 -1
- package/build/assets/prod/lwr-loader-shim-legacy.bundle.js +636 -256
- package/build/assets/prod/lwr-loader-shim-legacy.bundle.min.js +6 -2
- package/build/assets/prod/lwr-loader-shim-legacy.js +150 -55
- package/build/assets/prod/lwr-loader-shim.bundle.js +583 -259
- package/build/assets/prod/lwr-loader-shim.bundle.min.js +6 -2
- package/build/assets/prod/lwr-loader-shim.js +149 -55
- package/build/bundle/prod/lwr/esmLoader/esmLoader.js +2 -1
- package/build/cjs/index.cjs +1 -1
- package/build/cjs/modules/lwr/esmLoader/importResolver.cjs +17 -0
- package/build/cjs/modules/lwr/esmLoader/importResolverLegacy.cjs +17 -0
- package/build/cjs/modules/lwr/loader/constants/constants.cjs +1 -1
- package/build/cjs/modules/lwr/loader/errors/reportError.cjs +1 -0
- package/build/cjs/modules/lwr/loader/hooks/moduleInvalidation.cjs +1 -0
- package/build/cjs/modules/lwr/loader/hooks/resolveAndLoadHook.cjs +3 -1
- package/build/cjs/modules/lwr/loader/moduleRegistry/importMetadataResolver.cjs +2 -0
- package/build/cjs/modules/lwr/loader/moduleRegistry/moduleRegistry.cjs +2 -0
- package/build/cjs/modules/lwr/loaderLegacy/constants/constants.cjs +1 -1
- package/build/cjs/modules/lwr/loaderLegacy/errors/reportError.cjs +1 -0
- package/build/cjs/modules/lwr/loaderLegacy/hooks/moduleInvalidation.cjs +1 -0
- package/build/cjs/modules/lwr/loaderLegacy/hooks/resolveAndLoadHook.cjs +3 -1
- package/build/cjs/modules/lwr/loaderLegacy/importMap/importMapResolver.cjs +1 -0
- package/build/cjs/modules/lwr/loaderLegacy/importResolver/importResolver.cjs +17 -0
- package/build/cjs/modules/lwr/loaderLegacy/moduleRegistry/moduleRegistry.cjs +3 -0
- package/build/index.d.ts +1 -1
- package/build/index.js +1 -1
- package/build/modules/lwr/esmLoader/esmLoader.js +45 -15
- package/build/modules/lwr/loader/loader.js +433 -203
- package/build/modules/lwr/loaderLegacy/loaderLegacy.js +485 -200
- package/package.json +16 -9
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: MIT
|
|
5
5
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
6
6
|
*/
|
|
7
|
-
/* LWR Legacy Module Loader v0.10.0-alpha.
|
|
7
|
+
/* LWR Legacy Module Loader v0.10.0-alpha.20 */
|
|
8
8
|
const templateRegex = /\{([0-9]+)\}/g;
|
|
9
9
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
10
|
function templateString(template, args) {
|
|
@@ -18,17 +18,26 @@ function generateErrorMessage(errorInfo, args) {
|
|
|
18
18
|
const message = Array.isArray(args) ? templateString(errorInfo.message, args) : errorInfo.message;
|
|
19
19
|
return `LWR${errorInfo.code}: ${message}`;
|
|
20
20
|
}
|
|
21
|
+
|
|
21
22
|
class LoaderError extends Error {
|
|
22
23
|
constructor(errorInfo, errorArgs) {
|
|
23
24
|
super();
|
|
24
25
|
this.message = generateErrorMessage(errorInfo, errorArgs);
|
|
25
26
|
}
|
|
26
27
|
}
|
|
28
|
+
|
|
27
29
|
function invariant(condition, errorInfo) {
|
|
28
30
|
if (!condition) {
|
|
29
31
|
throw new LoaderError(errorInfo);
|
|
30
32
|
}
|
|
31
33
|
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
32
41
|
const MISSING_NAME = Object.freeze({
|
|
33
42
|
code: 3000,
|
|
34
43
|
message: 'A module name is required.',
|
|
@@ -109,6 +118,7 @@ const FAIL_HOOK_LOAD = Object.freeze({
|
|
|
109
118
|
level: 0,
|
|
110
119
|
message: 'Error loading "{0}" from hook',
|
|
111
120
|
});
|
|
121
|
+
|
|
112
122
|
/* importMap errors */
|
|
113
123
|
const BAD_IMPORT_MAP = Object.freeze({
|
|
114
124
|
code: 3011,
|
|
@@ -118,7 +128,9 @@ const BAD_IMPORT_MAP = Object.freeze({
|
|
|
118
128
|
|
|
119
129
|
/* eslint-disable lwr/no-unguarded-apis */
|
|
120
130
|
const hasDocument = typeof document !== 'undefined';
|
|
131
|
+
|
|
121
132
|
const hasSetTimeout = typeof setTimeout === 'function';
|
|
133
|
+
|
|
122
134
|
const hasConsole = typeof console !== 'undefined';
|
|
123
135
|
/* eslint-enable lwr/no-unguarded-apis */
|
|
124
136
|
|
|
@@ -126,7 +138,7 @@ function getBaseUrl() {
|
|
|
126
138
|
let baseUrl = undefined;
|
|
127
139
|
if (hasDocument) {
|
|
128
140
|
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
129
|
-
const baseEl = document.querySelector('base[href]');
|
|
141
|
+
const baseEl = document.querySelector('base[href]') ;
|
|
130
142
|
baseUrl = baseEl && baseEl.href;
|
|
131
143
|
}
|
|
132
144
|
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
@@ -138,8 +150,10 @@ function getBaseUrl() {
|
|
|
138
150
|
baseUrl = baseUrl.slice(0, lastSepIndex + 1);
|
|
139
151
|
}
|
|
140
152
|
}
|
|
153
|
+
|
|
141
154
|
return baseUrl;
|
|
142
155
|
}
|
|
156
|
+
|
|
143
157
|
/**
|
|
144
158
|
* Check if a string is a URL based on Common Internet Scheme Syntax
|
|
145
159
|
* https://www.ietf.org/rfc/rfc1738.txt
|
|
@@ -166,24 +180,26 @@ function getBaseUrl() {
|
|
|
166
180
|
function isUrl(url) {
|
|
167
181
|
return url.indexOf('://') !== -1;
|
|
168
182
|
}
|
|
183
|
+
|
|
169
184
|
// Borrowed and adapted from https://github.com/systemjs/systemjs/blob/master/src/common.js
|
|
170
185
|
// Resolves the first path segment relative to the second/parent URL
|
|
171
186
|
// eg: resolveIfNotPlainOrUrl('../test', 'http://www.site.com/one/two') => 'http://www.site.com/test'
|
|
172
187
|
// eg: resolveIfNotPlainOrUrl('./x/y/z', 'https://my.com/segment')).toBe('https://my.com/x/y/z')
|
|
173
188
|
function resolveIfNotPlainOrUrl(relUrl, parentUrl) {
|
|
174
189
|
const backslashRegEx = /\\/g;
|
|
175
|
-
if (relUrl.indexOf('\\') !== -1)
|
|
176
|
-
relUrl = relUrl.replace(backslashRegEx, '/');
|
|
190
|
+
if (relUrl.indexOf('\\') !== -1) relUrl = relUrl.replace(backslashRegEx, '/');
|
|
177
191
|
// protocol-relative
|
|
178
192
|
if (relUrl[0] === '/' && relUrl[1] === '/') {
|
|
179
193
|
return parentUrl.slice(0, parentUrl.indexOf(':') + 1) + relUrl;
|
|
180
194
|
}
|
|
181
195
|
// relative-url
|
|
182
|
-
else if (
|
|
183
|
-
(relUrl[
|
|
184
|
-
(relUrl[1] === '
|
|
185
|
-
|
|
186
|
-
|
|
196
|
+
else if (
|
|
197
|
+
(relUrl[0] === '.' &&
|
|
198
|
+
(relUrl[1] === '/' ||
|
|
199
|
+
(relUrl[1] === '.' && (relUrl[2] === '/' || (relUrl.length === 2 && (relUrl += '/')))) ||
|
|
200
|
+
(relUrl.length === 1 && (relUrl += '/')))) ||
|
|
201
|
+
relUrl[0] === '/'
|
|
202
|
+
) {
|
|
187
203
|
const parentProtocol = parentUrl.slice(0, parentUrl.indexOf(':') + 1);
|
|
188
204
|
let pathname;
|
|
189
205
|
if (parentUrl[parentProtocol.length + 1] === '/') {
|
|
@@ -191,21 +207,23 @@ function resolveIfNotPlainOrUrl(relUrl, parentUrl) {
|
|
|
191
207
|
if (parentProtocol !== 'file:') {
|
|
192
208
|
pathname = parentUrl.slice(parentProtocol.length + 2);
|
|
193
209
|
pathname = pathname.slice(pathname.indexOf('/') + 1);
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
210
|
+
} else {
|
|
196
211
|
pathname = parentUrl.slice(8);
|
|
197
212
|
}
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
213
|
+
} else {
|
|
200
214
|
// resolving to :/ so pathname is the /... part
|
|
201
|
-
pathname = parentUrl.slice(
|
|
215
|
+
pathname = parentUrl.slice(
|
|
216
|
+
parentProtocol.length + (parentUrl[parentProtocol.length] === '/' ? 1 : 0),
|
|
217
|
+
);
|
|
202
218
|
}
|
|
203
|
-
|
|
204
|
-
|
|
219
|
+
|
|
220
|
+
if (relUrl[0] === '/') return parentUrl.slice(0, parentUrl.length - pathname.length - 1) + relUrl;
|
|
221
|
+
|
|
205
222
|
// join together and split for removal of .. and . segments
|
|
206
223
|
// looping the string instead of anything fancy for perf reasons
|
|
207
224
|
// '../../../../../z' resolved to 'x/y' is just 'z'
|
|
208
225
|
const segmented = pathname.slice(0, pathname.lastIndexOf('/') + 1) + relUrl;
|
|
226
|
+
|
|
209
227
|
const output = [];
|
|
210
228
|
let segmentIndex = -1;
|
|
211
229
|
for (let i = 0; i < segmented.length; i++) {
|
|
@@ -216,6 +234,7 @@ function resolveIfNotPlainOrUrl(relUrl, parentUrl) {
|
|
|
216
234
|
segmentIndex = -1;
|
|
217
235
|
}
|
|
218
236
|
}
|
|
237
|
+
|
|
219
238
|
// new segment - check if it is relative
|
|
220
239
|
else if (segmented[i] === '.') {
|
|
221
240
|
// ../ segment
|
|
@@ -226,8 +245,7 @@ function resolveIfNotPlainOrUrl(relUrl, parentUrl) {
|
|
|
226
245
|
// ./ segment
|
|
227
246
|
else if (segmented[i + 1] === '/' || i + 1 === segmented.length) {
|
|
228
247
|
i += 1;
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
248
|
+
} else {
|
|
231
249
|
// the start of a new segment as below
|
|
232
250
|
segmentIndex = i;
|
|
233
251
|
}
|
|
@@ -238,13 +256,14 @@ function resolveIfNotPlainOrUrl(relUrl, parentUrl) {
|
|
|
238
256
|
}
|
|
239
257
|
}
|
|
240
258
|
// finish reading out the last segment
|
|
241
|
-
if (segmentIndex !== -1)
|
|
242
|
-
output.push(segmented.slice(segmentIndex));
|
|
259
|
+
if (segmentIndex !== -1) output.push(segmented.slice(segmentIndex));
|
|
243
260
|
return parentUrl.slice(0, parentUrl.length - pathname.length) + output.join('');
|
|
244
261
|
}
|
|
245
262
|
}
|
|
263
|
+
|
|
246
264
|
function resolveUrl(relUrl, parentUrl) {
|
|
247
|
-
const resolvedUrl =
|
|
265
|
+
const resolvedUrl =
|
|
266
|
+
resolveIfNotPlainOrUrl(relUrl, parentUrl) ||
|
|
248
267
|
(isUrl(relUrl) ? relUrl : resolveIfNotPlainOrUrl('./' + relUrl, parentUrl));
|
|
249
268
|
return resolvedUrl;
|
|
250
269
|
}
|
|
@@ -257,6 +276,7 @@ function createScript(url) {
|
|
|
257
276
|
script.src = url;
|
|
258
277
|
return script;
|
|
259
278
|
}
|
|
279
|
+
|
|
260
280
|
let lastWindowError$1, lastWindowErrorUrl;
|
|
261
281
|
function loadModuleDef(url) {
|
|
262
282
|
return new Promise(function (resolve, reject) {
|
|
@@ -270,8 +290,7 @@ function loadModuleDef(url) {
|
|
|
270
290
|
document.head.removeChild(script);
|
|
271
291
|
if (lastWindowErrorUrl === url) {
|
|
272
292
|
reject(lastWindowError$1);
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
293
|
+
} else {
|
|
275
294
|
resolve();
|
|
276
295
|
}
|
|
277
296
|
});
|
|
@@ -280,6 +299,7 @@ function loadModuleDef(url) {
|
|
|
280
299
|
}
|
|
281
300
|
});
|
|
282
301
|
}
|
|
302
|
+
|
|
283
303
|
if (hasDocument) {
|
|
284
304
|
// When a script is executed, runtime errors are on the global/window scope which are NOT caught by the script's onerror handler.
|
|
285
305
|
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
@@ -289,32 +309,76 @@ if (hasDocument) {
|
|
|
289
309
|
});
|
|
290
310
|
}
|
|
291
311
|
|
|
292
|
-
const MODULE_LOAD_TIMEOUT_TIMER =
|
|
312
|
+
const MODULE_LOAD_TIMEOUT_TIMER = 60 * 1000; // 1m
|
|
313
|
+
|
|
314
|
+
/*!
|
|
315
|
+
* Copyright (C) 2023 salesforce.com, inc.
|
|
316
|
+
*/
|
|
317
|
+
// @ts-ignore: Prevent cannot find name 'trustedTypes' error.
|
|
318
|
+
const SUPPORTS_TRUSTED_TYPES = typeof trustedTypes !== 'undefined';
|
|
319
|
+
function createTrustedTypesPolicy(name, options) {
|
|
320
|
+
// @ts-ignore: Prevent cannot find name 'trustedTypes' error.
|
|
321
|
+
return trustedTypes.createPolicy(name, options);
|
|
322
|
+
}
|
|
323
|
+
function createFallbackPolicy(_name, options) {
|
|
324
|
+
return options;
|
|
325
|
+
}
|
|
326
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types
|
|
327
|
+
const createPolicy = SUPPORTS_TRUSTED_TYPES ? createTrustedTypesPolicy : createFallbackPolicy;
|
|
328
|
+
const policyOptions = {
|
|
329
|
+
createHTML(value) {
|
|
330
|
+
return value;
|
|
331
|
+
},
|
|
332
|
+
createScript(value) {
|
|
333
|
+
return value;
|
|
334
|
+
},
|
|
335
|
+
createScriptURL(value) {
|
|
336
|
+
return value;
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
const trusted = createPolicy('trusted', policyOptions);
|
|
340
|
+
/*! version: 0.19.4 */
|
|
293
341
|
|
|
294
342
|
/* global console,process */
|
|
343
|
+
|
|
344
|
+
|
|
295
345
|
let lastWindowError;
|
|
296
346
|
if (hasDocument) {
|
|
297
347
|
globalThis.addEventListener('error', (evt) => {
|
|
298
348
|
lastWindowError = evt.error;
|
|
299
349
|
});
|
|
300
350
|
}
|
|
351
|
+
|
|
301
352
|
if (process.env.NODE_ENV !== 'production') {
|
|
302
353
|
if (!hasSetTimeout && hasConsole) {
|
|
303
354
|
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
304
355
|
console.warn('setTimeout API is not available, watchdog timer on load hook will not be set');
|
|
305
356
|
}
|
|
306
357
|
}
|
|
358
|
+
|
|
307
359
|
function isCustomResponse(response) {
|
|
308
|
-
return (
|
|
309
|
-
|
|
360
|
+
return (
|
|
361
|
+
Object.prototype.hasOwnProperty.call(response, 'data') &&
|
|
362
|
+
!Object.prototype.hasOwnProperty.call(response, 'blob')
|
|
363
|
+
);
|
|
310
364
|
}
|
|
311
|
-
function isFetchResponse(
|
|
365
|
+
function isFetchResponse(
|
|
366
|
+
response,
|
|
367
|
+
) {
|
|
312
368
|
// if it quacks like a duck...
|
|
313
|
-
return typeof response.blob === 'function';
|
|
369
|
+
return typeof (response ).blob === 'function';
|
|
314
370
|
}
|
|
315
|
-
|
|
316
|
-
|
|
371
|
+
|
|
372
|
+
function isResponseAPromise(
|
|
373
|
+
response
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
,
|
|
378
|
+
) {
|
|
379
|
+
return !!(response && (response ).then);
|
|
317
380
|
}
|
|
381
|
+
|
|
318
382
|
async function evaluateLoadHookResponse(response, id) {
|
|
319
383
|
return Promise.resolve().then(async () => {
|
|
320
384
|
if (!response.status) {
|
|
@@ -323,36 +387,41 @@ async function evaluateLoadHookResponse(response, id) {
|
|
|
323
387
|
if (response.status !== 200) {
|
|
324
388
|
throw new LoaderError(HTTP_FAIL_LOAD, [id, `${response.status}`]);
|
|
325
389
|
}
|
|
390
|
+
|
|
326
391
|
const isResponse = isFetchResponse(response);
|
|
327
392
|
let code;
|
|
328
393
|
if (isCustomResponse(response)) {
|
|
329
394
|
code = response.data;
|
|
330
|
-
}
|
|
331
|
-
else if (isResponse) {
|
|
395
|
+
} else if (isResponse) {
|
|
332
396
|
// handle fetch response
|
|
333
|
-
code = await response.text();
|
|
334
|
-
}
|
|
335
|
-
else {
|
|
397
|
+
code = await (response ).text();
|
|
398
|
+
} else {
|
|
336
399
|
throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
|
|
337
400
|
}
|
|
401
|
+
|
|
338
402
|
if (!code) {
|
|
339
403
|
throw new LoaderError(FAIL_LOAD, [id]);
|
|
340
404
|
}
|
|
405
|
+
|
|
341
406
|
code = `${code}\n//# sourceURL=${id}`; // append sourceURL for debugging
|
|
342
407
|
try {
|
|
343
408
|
// TODO eval source maps for debugging
|
|
344
|
-
eval(code);
|
|
345
|
-
}
|
|
346
|
-
catch (e) {
|
|
409
|
+
eval(trusted.createScript(code));
|
|
410
|
+
} catch (e) {
|
|
347
411
|
throw new LoaderError(FAIL_LOAD, [id]);
|
|
348
412
|
}
|
|
413
|
+
|
|
349
414
|
if (lastWindowError) {
|
|
350
415
|
throw new LoaderError(FAIL_LOAD, [id]);
|
|
351
416
|
}
|
|
352
417
|
return true;
|
|
353
418
|
});
|
|
354
419
|
}
|
|
355
|
-
|
|
420
|
+
|
|
421
|
+
async function evaluateLoadHook(
|
|
422
|
+
id,
|
|
423
|
+
hookPromise,
|
|
424
|
+
) {
|
|
356
425
|
if (!hasSetTimeout) {
|
|
357
426
|
return hookPromise;
|
|
358
427
|
}
|
|
@@ -364,26 +433,28 @@ async function evaluateLoadHook(id, hookPromise) {
|
|
|
364
433
|
}, MODULE_LOAD_TIMEOUT_TIMER);
|
|
365
434
|
hookPromise
|
|
366
435
|
.then((response) => {
|
|
367
|
-
|
|
368
|
-
|
|
436
|
+
resolve(response);
|
|
437
|
+
})
|
|
369
438
|
.catch(() => {
|
|
370
|
-
|
|
371
|
-
|
|
439
|
+
reject(new LoaderError(FAIL_HOOK_LOAD, [id]));
|
|
440
|
+
})
|
|
372
441
|
.finally(() => {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
442
|
+
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
443
|
+
clearTimeout(timer);
|
|
444
|
+
});
|
|
376
445
|
});
|
|
377
446
|
}
|
|
378
447
|
|
|
379
448
|
function reportError(error) {
|
|
380
449
|
// TODO eventually this should be configurable instrumentation to send this somewhere
|
|
381
450
|
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
382
|
-
if (hasConsole)
|
|
383
|
-
console.error(error);
|
|
451
|
+
if (hasConsole) console.error(error);
|
|
384
452
|
}
|
|
385
453
|
|
|
386
|
-
function evaluateHandleStaleModuleHooks(
|
|
454
|
+
function evaluateHandleStaleModuleHooks(
|
|
455
|
+
handleStaleModuleHooks,
|
|
456
|
+
hookArgs,
|
|
457
|
+
) {
|
|
387
458
|
const { name, oldHash, newHash } = hookArgs;
|
|
388
459
|
// keep evaluating hooks if return value is null
|
|
389
460
|
for (let i = 0; i < handleStaleModuleHooks.length; i++) {
|
|
@@ -393,8 +464,7 @@ function evaluateHandleStaleModuleHooks(handleStaleModuleHooks, hookArgs) {
|
|
|
393
464
|
if (hookResult !== null) {
|
|
394
465
|
break;
|
|
395
466
|
}
|
|
396
|
-
}
|
|
397
|
-
catch (e) {
|
|
467
|
+
} catch (e) {
|
|
398
468
|
reportError(new LoaderError(STALE_HOOK_ERROR));
|
|
399
469
|
}
|
|
400
470
|
}
|
|
@@ -409,32 +479,82 @@ const MODULE_FETCH = `${LOADER_PREFIX}module.fetch`;
|
|
|
409
479
|
const MODULE_ERROR = `${LOADER_PREFIX}module.error`;
|
|
410
480
|
|
|
411
481
|
/* global console,process */
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
412
534
|
class ModuleRegistry {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
// The evaluated module registry where the module identifier (name or URL?) is the key
|
|
417
|
-
this.moduleRegistry = new Map();
|
|
418
|
-
// Aliases of modules in the registry
|
|
419
|
-
this.aliases = new Map();
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
constructor(config) {ModuleRegistry.prototype.__init.call(this);ModuleRegistry.prototype.__init2.call(this);ModuleRegistry.prototype.__init3.call(this);
|
|
420
538
|
this.baseUrl = config.baseUrl || '';
|
|
421
539
|
this.profiler = config.profiler;
|
|
422
540
|
}
|
|
541
|
+
|
|
423
542
|
async load(id, importer) {
|
|
424
543
|
const resolvedId = await this.resolve(id, importer);
|
|
425
544
|
const moduleRecord = this.getModuleRecord(resolvedId, id);
|
|
426
545
|
if (moduleRecord.evaluated) {
|
|
427
546
|
return moduleRecord.module;
|
|
428
|
-
}
|
|
429
|
-
else {
|
|
547
|
+
} else {
|
|
430
548
|
if (!moduleRecord.evaluationPromise) {
|
|
431
549
|
moduleRecord.evaluationPromise = this.topLevelEvaluation(moduleRecord);
|
|
432
550
|
}
|
|
433
551
|
return moduleRecord.evaluationPromise;
|
|
434
552
|
}
|
|
435
553
|
}
|
|
554
|
+
|
|
436
555
|
async resolve(id, importer) {
|
|
437
556
|
const parentUrl = this.baseUrl; // only support baseUrl for now
|
|
557
|
+
|
|
438
558
|
let resolved;
|
|
439
559
|
let aliasedId = id;
|
|
440
560
|
const resolveHooks = this.resolveHook;
|
|
@@ -447,6 +567,7 @@ class ModuleRegistry {
|
|
|
447
567
|
// eslint-disable-next-line no-await-in-loop
|
|
448
568
|
result = isResponseAPromise(response) ? await response : response;
|
|
449
569
|
}
|
|
570
|
+
|
|
450
571
|
// if result is not null, attempt resolution
|
|
451
572
|
if (result !== null) {
|
|
452
573
|
if (typeof result === 'string') {
|
|
@@ -457,6 +578,7 @@ class ModuleRegistry {
|
|
|
457
578
|
aliasedId = result; // the next hook will receive the new id
|
|
458
579
|
continue;
|
|
459
580
|
}
|
|
581
|
+
|
|
460
582
|
resolved =
|
|
461
583
|
result && result.url && (resolveIfNotPlainOrUrl(result.url, parentUrl) || result.url);
|
|
462
584
|
if (!resolved) {
|
|
@@ -466,34 +588,38 @@ class ModuleRegistry {
|
|
|
466
588
|
break;
|
|
467
589
|
}
|
|
468
590
|
}
|
|
591
|
+
|
|
469
592
|
if (aliasedId !== id) {
|
|
470
593
|
// resolved module id is the aliased module if it has already been defined
|
|
471
594
|
if (!resolved && this.namedDefineRegistry.has(aliasedId)) {
|
|
472
595
|
return aliasedId;
|
|
473
|
-
}
|
|
474
|
-
else {
|
|
596
|
+
} else {
|
|
475
597
|
id = aliasedId;
|
|
476
598
|
}
|
|
477
599
|
}
|
|
478
600
|
}
|
|
601
|
+
|
|
479
602
|
if (!resolved) {
|
|
480
603
|
const resolvedOrPlain = resolveIfNotPlainOrUrl(id, parentUrl) || id;
|
|
604
|
+
|
|
481
605
|
// if module registry already has named module the resolved id is the plain id
|
|
482
606
|
if (this.moduleRegistry.has(resolvedOrPlain)) {
|
|
483
607
|
return resolvedOrPlain;
|
|
484
608
|
}
|
|
609
|
+
|
|
485
610
|
if (this.resolver) {
|
|
486
611
|
resolved = this.resolver.resolve(resolvedOrPlain, parentUrl);
|
|
487
612
|
// return the plain id if it is already defined && the resolvedUrl is NOT already in the module registry
|
|
488
|
-
if (
|
|
489
|
-
this.namedDefineRegistry.
|
|
613
|
+
if (
|
|
614
|
+
this.namedDefineRegistry.has(resolvedOrPlain) &&
|
|
615
|
+
this.namedDefineRegistry.get(resolvedOrPlain).defined
|
|
616
|
+
) {
|
|
490
617
|
const record = this.moduleRegistry.get(resolved);
|
|
491
618
|
if (!record || !this.aliases.has(resolvedOrPlain)) {
|
|
492
619
|
return resolvedOrPlain;
|
|
493
620
|
}
|
|
494
621
|
}
|
|
495
|
-
}
|
|
496
|
-
else {
|
|
622
|
+
} else {
|
|
497
623
|
resolved = resolvedOrPlain;
|
|
498
624
|
}
|
|
499
625
|
}
|
|
@@ -501,6 +627,7 @@ class ModuleRegistry {
|
|
|
501
627
|
if (this.namedDefineRegistry.has(id)) {
|
|
502
628
|
return id;
|
|
503
629
|
}
|
|
630
|
+
|
|
504
631
|
throw new LoaderError(UNRESOLVED, [id]);
|
|
505
632
|
}
|
|
506
633
|
if (importer && isUrl(resolved)) {
|
|
@@ -508,10 +635,17 @@ class ModuleRegistry {
|
|
|
508
635
|
}
|
|
509
636
|
return resolved;
|
|
510
637
|
}
|
|
638
|
+
|
|
511
639
|
has(id) {
|
|
512
640
|
return this.moduleRegistry.has(id);
|
|
513
641
|
}
|
|
514
|
-
|
|
642
|
+
|
|
643
|
+
define(
|
|
644
|
+
name,
|
|
645
|
+
dependencies,
|
|
646
|
+
exporter,
|
|
647
|
+
signatures,
|
|
648
|
+
) {
|
|
515
649
|
const mod = this.namedDefineRegistry.get(name);
|
|
516
650
|
// Don't allow redefining a module.
|
|
517
651
|
if (mod && mod.defined) {
|
|
@@ -522,6 +656,7 @@ class ModuleRegistry {
|
|
|
522
656
|
this.lastDefine = mod;
|
|
523
657
|
return;
|
|
524
658
|
}
|
|
659
|
+
|
|
525
660
|
const moduleDef = {
|
|
526
661
|
name,
|
|
527
662
|
dependencies,
|
|
@@ -533,9 +668,11 @@ class ModuleRegistry {
|
|
|
533
668
|
// if module is "external", resolve the external promise to notify any dependees
|
|
534
669
|
mod.external.resolveExternal(moduleDef);
|
|
535
670
|
}
|
|
671
|
+
|
|
536
672
|
this.profiler.logOperationStart({ id: MODULE_DEFINE, specifier: name });
|
|
537
673
|
this.namedDefineRegistry.set(name, moduleDef);
|
|
538
674
|
this.lastDefine = moduleDef;
|
|
675
|
+
|
|
539
676
|
// Check signatures of dependencies against those in the namedDefineRegistry
|
|
540
677
|
if (signatures.hashes) {
|
|
541
678
|
Object.entries(signatures.hashes).forEach(([dep, sig]) => {
|
|
@@ -543,6 +680,7 @@ class ModuleRegistry {
|
|
|
543
680
|
});
|
|
544
681
|
}
|
|
545
682
|
}
|
|
683
|
+
|
|
546
684
|
/**
|
|
547
685
|
* Marks modules as "externally" loaded/provided, so that the loader does not attempt to fetch them.
|
|
548
686
|
*
|
|
@@ -555,6 +693,7 @@ class ModuleRegistry {
|
|
|
555
693
|
let timer;
|
|
556
694
|
const moduleDefPromise = new Promise((resolve, reject) => {
|
|
557
695
|
resolveExternal = resolve;
|
|
696
|
+
|
|
558
697
|
// watch the external for timeout
|
|
559
698
|
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
560
699
|
timer = setTimeout(() => {
|
|
@@ -572,15 +711,15 @@ class ModuleRegistry {
|
|
|
572
711
|
moduleDefPromise,
|
|
573
712
|
},
|
|
574
713
|
};
|
|
575
|
-
this.namedDefineRegistry.set(id, moduleDef);
|
|
576
|
-
}
|
|
577
|
-
else if (process.env.NODE_ENV !== 'production' && hasConsole) {
|
|
714
|
+
this.namedDefineRegistry.set(id, moduleDef );
|
|
715
|
+
} else if (process.env.NODE_ENV !== 'production' && hasConsole) {
|
|
578
716
|
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
579
717
|
console.warn(MODULE_ALREADY_LOADED.message, id);
|
|
580
718
|
}
|
|
581
719
|
});
|
|
582
720
|
}
|
|
583
|
-
|
|
721
|
+
|
|
722
|
+
checkModuleSignature(name, signature) {
|
|
584
723
|
const moduleDef = this.namedDefineRegistry.get(name);
|
|
585
724
|
if (!moduleDef) {
|
|
586
725
|
// Placeholder module definition entry for saving known signature
|
|
@@ -591,9 +730,10 @@ class ModuleRegistry {
|
|
|
591
730
|
},
|
|
592
731
|
defined: false,
|
|
593
732
|
};
|
|
594
|
-
this.namedDefineRegistry.set(name, modDef);
|
|
733
|
+
this.namedDefineRegistry.set(name, modDef );
|
|
595
734
|
return;
|
|
596
735
|
}
|
|
736
|
+
|
|
597
737
|
const currentSig = moduleDef.signatures ? moduleDef.signatures.ownHash : undefined;
|
|
598
738
|
if (currentSig && signature !== currentSig) {
|
|
599
739
|
const handleStaleModuleHooks = this.handleStaleModuleHook;
|
|
@@ -603,25 +743,43 @@ class ModuleRegistry {
|
|
|
603
743
|
oldHash: currentSig,
|
|
604
744
|
newHash: signature,
|
|
605
745
|
});
|
|
606
|
-
}
|
|
607
|
-
else {
|
|
746
|
+
} else {
|
|
608
747
|
if (process.env.NODE_ENV !== 'production' && hasConsole) {
|
|
609
748
|
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
610
|
-
console.warn(
|
|
749
|
+
console.warn(
|
|
750
|
+
`stale module detected ${name}, current sig:${currentSig}, new sig:${signature}`,
|
|
751
|
+
);
|
|
611
752
|
}
|
|
612
753
|
}
|
|
613
754
|
}
|
|
614
755
|
}
|
|
756
|
+
|
|
757
|
+
|
|
615
758
|
setImportResolver(resolver) {
|
|
616
759
|
this.resolver = resolver;
|
|
617
760
|
}
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
// A registry for named AMD defines containing the *metadata* of AMD module
|
|
765
|
+
__init() {this.namedDefineRegistry = new Map();}
|
|
766
|
+
|
|
767
|
+
// The evaluated module registry where the module identifier (name or URL?) is the key
|
|
768
|
+
__init2() {this.moduleRegistry = new Map();}
|
|
769
|
+
|
|
770
|
+
// Aliases of modules in the registry
|
|
771
|
+
__init3() {this.aliases = new Map();}
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
|
|
618
775
|
// Returns an existing module record by the resolvedId or aliased id
|
|
619
|
-
|
|
776
|
+
getExistingModuleRecord(resolvedId, aliasId) {
|
|
620
777
|
const moduleRecord = this.moduleRegistry.get(resolvedId);
|
|
621
778
|
if (moduleRecord) {
|
|
622
779
|
this.storeModuleAlias(aliasId, resolvedId);
|
|
623
780
|
return moduleRecord;
|
|
624
781
|
}
|
|
782
|
+
|
|
625
783
|
// Check if this is a known alias
|
|
626
784
|
if (resolvedId !== aliasId) {
|
|
627
785
|
const alias = this.aliases.get(aliasId);
|
|
@@ -634,13 +792,15 @@ class ModuleRegistry {
|
|
|
634
792
|
}
|
|
635
793
|
return moduleRecord;
|
|
636
794
|
}
|
|
637
|
-
|
|
795
|
+
|
|
796
|
+
getModuleRecord(resolvedId, id) {
|
|
638
797
|
// Look for an existing record
|
|
639
798
|
const existingRecord = this.getExistingModuleRecord(resolvedId, id);
|
|
640
799
|
if (existingRecord) {
|
|
641
800
|
// return existing
|
|
642
801
|
return existingRecord;
|
|
643
802
|
}
|
|
803
|
+
|
|
644
804
|
// Create a new Module Record
|
|
645
805
|
const instantiation = this.getModuleDef(resolvedId, id);
|
|
646
806
|
const dependencyRecords = instantiation.then((moduleDef) => {
|
|
@@ -648,15 +808,17 @@ class ModuleRegistry {
|
|
|
648
808
|
// get dep and filter out exports
|
|
649
809
|
const filtered = dependencies
|
|
650
810
|
.map((dep) => {
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
.filter((depRecord) => depRecord !== undefined);
|
|
811
|
+
if (dep === 'exports') {
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
invariant(dep !== 'require', NO_AMD_REQUIRE);
|
|
815
|
+
return this.getModuleDependencyRecord.call(this, dep);
|
|
816
|
+
})
|
|
817
|
+
.filter((depRecord) => depRecord !== undefined) ;
|
|
818
|
+
|
|
658
819
|
return Promise.all(filtered);
|
|
659
820
|
});
|
|
821
|
+
|
|
660
822
|
const newModuleRecord = {
|
|
661
823
|
id: resolvedId,
|
|
662
824
|
module: Object.create(null),
|
|
@@ -669,12 +831,12 @@ class ModuleRegistry {
|
|
|
669
831
|
this.storeModuleAlias(id, resolvedId);
|
|
670
832
|
return newModuleRecord;
|
|
671
833
|
}
|
|
672
|
-
|
|
834
|
+
|
|
835
|
+
storeModuleAlias(aliasId, resolvedId) {
|
|
673
836
|
if (aliasId !== resolvedId) {
|
|
674
837
|
if (!this.aliases.has(aliasId)) {
|
|
675
838
|
this.aliases.set(aliasId, resolvedId);
|
|
676
|
-
}
|
|
677
|
-
else if (hasConsole) {
|
|
839
|
+
} else if (hasConsole) {
|
|
678
840
|
// Warn the user if they were not aliasing to the resolvedId
|
|
679
841
|
const currentResolvedId = this.aliases.get(aliasId);
|
|
680
842
|
if (currentResolvedId !== resolvedId) {
|
|
@@ -684,17 +846,23 @@ class ModuleRegistry {
|
|
|
684
846
|
}
|
|
685
847
|
}
|
|
686
848
|
}
|
|
687
|
-
|
|
849
|
+
|
|
850
|
+
async getModuleDependencyRecord(dependency) {
|
|
688
851
|
const resolvedDepId = await this.resolve(dependency);
|
|
689
852
|
return this.getModuleRecord(resolvedDepId, dependency);
|
|
690
853
|
}
|
|
854
|
+
|
|
691
855
|
// execute the "top-level code" (the code outside of functions) of a module
|
|
692
|
-
|
|
856
|
+
async topLevelEvaluation(moduleRecord) {
|
|
693
857
|
await this.instantiateAll(moduleRecord, {});
|
|
694
858
|
return this.evaluateModule(moduleRecord, {});
|
|
695
859
|
}
|
|
860
|
+
|
|
696
861
|
// Returns a promise when a module and all of it's dependencies have finished instantiation
|
|
697
|
-
|
|
862
|
+
async instantiateAll(
|
|
863
|
+
moduleRecord,
|
|
864
|
+
instantiatedMap,
|
|
865
|
+
) {
|
|
698
866
|
if (!instantiatedMap[moduleRecord.id]) {
|
|
699
867
|
instantiatedMap[moduleRecord.id] = true;
|
|
700
868
|
const dependencyModuleRecords = await moduleRecord.dependencyRecords;
|
|
@@ -707,46 +875,61 @@ class ModuleRegistry {
|
|
|
707
875
|
}
|
|
708
876
|
}
|
|
709
877
|
}
|
|
710
|
-
|
|
878
|
+
|
|
879
|
+
async evaluateModule(
|
|
880
|
+
moduleRecord,
|
|
881
|
+
evaluationMap,
|
|
882
|
+
) {
|
|
711
883
|
const dependencyModuleRecords = await moduleRecord.dependencyRecords;
|
|
712
884
|
if (dependencyModuleRecords.length > 0) {
|
|
713
885
|
evaluationMap[moduleRecord.id] = true;
|
|
714
886
|
// evaluate dependencies first
|
|
715
887
|
await this.evaluateModuleDependencies(dependencyModuleRecords, evaluationMap);
|
|
716
888
|
}
|
|
889
|
+
|
|
717
890
|
const { exporter, dependencies } = await moduleRecord.instantiation;
|
|
718
891
|
// The exports object automatically gets filled in by the exporter evaluation
|
|
719
892
|
const exports = {};
|
|
720
|
-
const depsMapped = await Promise.all(
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
893
|
+
const depsMapped = await Promise.all(
|
|
894
|
+
dependencies.map(async (dep) => {
|
|
895
|
+
if (dep === 'exports') {
|
|
896
|
+
return exports;
|
|
897
|
+
}
|
|
898
|
+
const resolvedDepId = await this.resolve(dep);
|
|
899
|
+
|
|
900
|
+
const moduleRecord = this.moduleRegistry.get(resolvedDepId) ;
|
|
901
|
+
if (!moduleRecord) {
|
|
902
|
+
throw new LoaderError(FAILED_DEP, [resolvedDepId]);
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
const module = moduleRecord.module;
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* Circular dependencies are handled properly when named exports are used,
|
|
909
|
+
* however, for default exports there is a bug: https://github.com/rollup/rollup/issues/3384
|
|
910
|
+
*
|
|
911
|
+
* The workaround below applies for circular dependencies (!moduleRecord.evaluated)
|
|
912
|
+
*/
|
|
913
|
+
if (!moduleRecord.evaluated) {
|
|
914
|
+
return this.getCircularDependencyWrapper(module);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
if (module) {
|
|
918
|
+
return module.__defaultInterop ? module.default : module;
|
|
919
|
+
}
|
|
920
|
+
|
|
727
921
|
throw new LoaderError(FAILED_DEP, [resolvedDepId]);
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
* Circular dependencies are handled properly when named exports are used,
|
|
732
|
-
* however, for default exports there is a bug: https://github.com/rollup/rollup/issues/3384
|
|
733
|
-
*
|
|
734
|
-
* The workaround below applies for circular dependencies (!moduleRecord.evaluated)
|
|
735
|
-
*/
|
|
736
|
-
if (!moduleRecord.evaluated) {
|
|
737
|
-
return this.getCircularDependencyWrapper(module);
|
|
738
|
-
}
|
|
739
|
-
if (module) {
|
|
740
|
-
return module.__defaultInterop ? module.default : module;
|
|
741
|
-
}
|
|
742
|
-
throw new LoaderError(FAILED_DEP, [resolvedDepId]);
|
|
743
|
-
}));
|
|
922
|
+
}),
|
|
923
|
+
);
|
|
924
|
+
|
|
744
925
|
// W-10029836 - In the case where we could be instantiating multiple graphs at the same time lets make sure the module have not already been evaluated
|
|
745
926
|
if (moduleRecord.evaluated) {
|
|
746
927
|
return moduleRecord.module;
|
|
747
928
|
}
|
|
929
|
+
|
|
748
930
|
// evaluates the module function
|
|
749
931
|
let moduleDefault = exporter(...depsMapped);
|
|
932
|
+
|
|
750
933
|
// value is returned from exporter, then we are not using named exports
|
|
751
934
|
if (moduleDefault !== undefined) {
|
|
752
935
|
moduleDefault = { default: moduleDefault };
|
|
@@ -762,7 +945,9 @@ class ModuleRegistry {
|
|
|
762
945
|
Object.defineProperty(exports, '__useDefault', { value: true });
|
|
763
946
|
}
|
|
764
947
|
}
|
|
948
|
+
|
|
765
949
|
const moduleExports = moduleDefault || exports;
|
|
950
|
+
|
|
766
951
|
// update the module record
|
|
767
952
|
// copy over enumerable public methods to module
|
|
768
953
|
for (const key in moduleExports) {
|
|
@@ -776,6 +961,7 @@ class ModuleRegistry {
|
|
|
776
961
|
},
|
|
777
962
|
});
|
|
778
963
|
}
|
|
964
|
+
|
|
779
965
|
// copy non-enumerable to module
|
|
780
966
|
if (moduleExports.__useDefault) {
|
|
781
967
|
Object.defineProperty(moduleRecord.module, '__useDefault', { value: true });
|
|
@@ -786,27 +972,36 @@ class ModuleRegistry {
|
|
|
786
972
|
if (moduleExports.__esModule) {
|
|
787
973
|
Object.defineProperty(moduleRecord.module, '__esModule', { value: true });
|
|
788
974
|
}
|
|
975
|
+
|
|
789
976
|
moduleRecord.evaluated = true;
|
|
790
977
|
Object.freeze(moduleRecord.module);
|
|
791
978
|
return moduleRecord.module;
|
|
792
979
|
}
|
|
980
|
+
|
|
793
981
|
// Determines if named exports module has only default export
|
|
794
|
-
|
|
795
|
-
return (
|
|
982
|
+
isNamedExportDefaultOnly(exports) {
|
|
983
|
+
return (
|
|
984
|
+
exports !== undefined &&
|
|
796
985
|
Object.getOwnPropertyNames(exports).length === 2 &&
|
|
797
986
|
Object.prototype.hasOwnProperty.call(exports, 'default') &&
|
|
798
|
-
Object.prototype.hasOwnProperty.call(exports, '__esModule')
|
|
987
|
+
Object.prototype.hasOwnProperty.call(exports, '__esModule')
|
|
988
|
+
);
|
|
799
989
|
}
|
|
990
|
+
|
|
800
991
|
// Wrap the dependency in a function that can be called and detected by __circular__ property.
|
|
801
992
|
// The LWC engine checks for __circular__ to detect circular dependencies.
|
|
802
|
-
|
|
993
|
+
getCircularDependencyWrapper(module) {
|
|
803
994
|
const tmp = () => {
|
|
804
995
|
return module.__useDefault || module.__defaultInterop ? module.default : module;
|
|
805
996
|
};
|
|
806
997
|
tmp.__circular__ = true;
|
|
807
998
|
return tmp;
|
|
808
999
|
}
|
|
809
|
-
|
|
1000
|
+
|
|
1001
|
+
async evaluateModuleDependencies(
|
|
1002
|
+
dependencyModuleRecords,
|
|
1003
|
+
evaluationMap,
|
|
1004
|
+
) {
|
|
810
1005
|
for (let i = 0; i < dependencyModuleRecords.length; i++) {
|
|
811
1006
|
const depRecord = dependencyModuleRecords[i];
|
|
812
1007
|
if (!depRecord.evaluated && !evaluationMap[depRecord.id]) {
|
|
@@ -816,15 +1011,17 @@ class ModuleRegistry {
|
|
|
816
1011
|
}
|
|
817
1012
|
}
|
|
818
1013
|
}
|
|
819
|
-
|
|
1014
|
+
|
|
1015
|
+
async getModuleDef(resolvedId, originalId) {
|
|
820
1016
|
// reset lastDefine
|
|
821
1017
|
this.lastDefine = undefined;
|
|
1018
|
+
|
|
822
1019
|
// the module name can be the resolved ID or the original ID if neither are URL's.
|
|
823
1020
|
const moduleName = !isUrl(resolvedId)
|
|
824
1021
|
? resolvedId
|
|
825
1022
|
: originalId !== resolvedId
|
|
826
|
-
|
|
827
|
-
|
|
1023
|
+
? originalId
|
|
1024
|
+
: undefined;
|
|
828
1025
|
let moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
|
|
829
1026
|
if (moduleDef && moduleDef.external) {
|
|
830
1027
|
return moduleDef.external.moduleDefPromise;
|
|
@@ -837,76 +1034,84 @@ class ModuleRegistry {
|
|
|
837
1034
|
this.profiler.logOperationStart({ id: MODULE_FETCH, specifier });
|
|
838
1035
|
return Promise.resolve()
|
|
839
1036
|
.then(async () => {
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
1037
|
+
const loadHooks = this.loadHook;
|
|
1038
|
+
if (loadHooks) {
|
|
1039
|
+
for (let i = 0; i < loadHooks.length; i++) {
|
|
1040
|
+
const loadHook = loadHooks[i];
|
|
1041
|
+
const response = loadHook(resolvedId, parentUrl);
|
|
1042
|
+
const result = (
|
|
1043
|
+
isResponseAPromise(response)
|
|
1044
|
+
? // eslint-disable-next-line no-await-in-loop
|
|
1045
|
+
await evaluateLoadHook(resolvedId, response)
|
|
1046
|
+
: response
|
|
1047
|
+
) ;
|
|
1048
|
+
if (result === undefined) {
|
|
1049
|
+
throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
|
|
1050
|
+
}
|
|
1051
|
+
if (result && result !== null) {
|
|
1052
|
+
return evaluateLoadHookResponse(result, resolvedId);
|
|
1053
|
+
}
|
|
854
1054
|
}
|
|
855
1055
|
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
})
|
|
1056
|
+
return false;
|
|
1057
|
+
})
|
|
859
1058
|
.then((result) => {
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
1059
|
+
if (result !== true && hasDocument) {
|
|
1060
|
+
return loadModuleDef(resolvedId);
|
|
1061
|
+
}
|
|
1062
|
+
})
|
|
864
1063
|
.then(() => {
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
moduleDef
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1064
|
+
// Attempt to retrieve the module definition by name first
|
|
1065
|
+
moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
|
|
1066
|
+
|
|
1067
|
+
// Fallback to the last loader.define call
|
|
1068
|
+
if (!moduleDef) {
|
|
1069
|
+
moduleDef = this.lastDefine;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
// This should not happen
|
|
1073
|
+
if (!moduleDef) {
|
|
1074
|
+
throw new LoaderError(FAIL_INSTANTIATE, [resolvedId]);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
this.profiler.logOperationEnd({ id: MODULE_FETCH, specifier });
|
|
1078
|
+
return moduleDef;
|
|
1079
|
+
})
|
|
878
1080
|
.catch((e) => {
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
1081
|
+
this.profiler.logOperationStart({ id: MODULE_ERROR, specifier });
|
|
1082
|
+
throw e;
|
|
1083
|
+
});
|
|
882
1084
|
}
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
|
|
883
1088
|
addLoaderPlugin(hooks) {
|
|
884
1089
|
if (typeof hooks !== 'object') {
|
|
885
1090
|
throw new LoaderError(INVALID_HOOK);
|
|
886
1091
|
}
|
|
887
1092
|
const { loadModule: loadHook, resolveModule: resolveHook } = hooks;
|
|
1093
|
+
|
|
888
1094
|
if (resolveHook) {
|
|
889
1095
|
if (this.resolveHook) {
|
|
890
1096
|
this.resolveHook.push(resolveHook);
|
|
891
|
-
}
|
|
892
|
-
else {
|
|
1097
|
+
} else {
|
|
893
1098
|
this.resolveHook = [resolveHook];
|
|
894
1099
|
}
|
|
895
1100
|
}
|
|
896
1101
|
if (loadHook) {
|
|
897
1102
|
if (this.loadHook) {
|
|
898
1103
|
this.loadHook.push(loadHook);
|
|
899
|
-
}
|
|
900
|
-
else {
|
|
1104
|
+
} else {
|
|
901
1105
|
this.loadHook = [loadHook];
|
|
902
1106
|
}
|
|
903
1107
|
}
|
|
904
1108
|
}
|
|
1109
|
+
|
|
1110
|
+
|
|
905
1111
|
registerHandleStaleModuleHook(handleStaleModule) {
|
|
906
1112
|
if (this.handleStaleModuleHook) {
|
|
907
1113
|
this.handleStaleModuleHook.push(handleStaleModule);
|
|
908
|
-
}
|
|
909
|
-
else {
|
|
1114
|
+
} else {
|
|
910
1115
|
this.handleStaleModuleHook = [handleStaleModule];
|
|
911
1116
|
}
|
|
912
1117
|
}
|
|
@@ -938,6 +1143,19 @@ function targetWarning(match, target, msg) {
|
|
|
938
1143
|
*
|
|
939
1144
|
* This implementation is adapted from https://github.com/systemjs/systemjs/blob/master/src/features/import-map.js
|
|
940
1145
|
*/
|
|
1146
|
+
|
|
1147
|
+
// Spec based import map object https://github.com/WICG/import-maps
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
|
|
941
1159
|
// Resolves an import map package entry
|
|
942
1160
|
function applyPackages(id, packages, defaultUri) {
|
|
943
1161
|
const pkgName = getMatch(id, packages);
|
|
@@ -948,9 +1166,9 @@ function applyPackages(id, packages, defaultUri) {
|
|
|
948
1166
|
}
|
|
949
1167
|
if (id.length > pkgName.length && pkg[pkg.length - 1] !== '/') {
|
|
950
1168
|
targetWarning(pkgName, pkg, "should have a trailing '/'");
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
|
|
1169
|
+
} else {
|
|
1170
|
+
const isPackage =
|
|
1171
|
+
id.length > pkgName.length &&
|
|
954
1172
|
pkg[pkg.length - 1] === '/' &&
|
|
955
1173
|
pkg.lastIndexOf(pkgName) === pkg.length - pkgName.length;
|
|
956
1174
|
if (isPackage) {
|
|
@@ -959,8 +1177,7 @@ function applyPackages(id, packages, defaultUri) {
|
|
|
959
1177
|
}
|
|
960
1178
|
return pkg + id.slice(pkgName.length);
|
|
961
1179
|
}
|
|
962
|
-
}
|
|
963
|
-
else if (defaultUri) {
|
|
1180
|
+
} else if (defaultUri) {
|
|
964
1181
|
// When a specifier's URI cannot be resolved via the imports, fallback to "default".
|
|
965
1182
|
// -> https://rfcs.lwc.dev/rfcs/lwr/0000-import-metadata#json-schema
|
|
966
1183
|
// However, if `id` is already a fully resolved url,
|
|
@@ -971,8 +1188,13 @@ function applyPackages(id, packages, defaultUri) {
|
|
|
971
1188
|
}
|
|
972
1189
|
}
|
|
973
1190
|
}
|
|
1191
|
+
|
|
974
1192
|
// Resolves an entry in the import map
|
|
975
|
-
function resolveImportMapEntry(
|
|
1193
|
+
function resolveImportMapEntry(
|
|
1194
|
+
importMap,
|
|
1195
|
+
resolvedOrPlain,
|
|
1196
|
+
parentUrl,
|
|
1197
|
+
) {
|
|
976
1198
|
if (!importMap.scopes) {
|
|
977
1199
|
importMap.scopes = {};
|
|
978
1200
|
}
|
|
@@ -988,12 +1210,21 @@ function resolveImportMapEntry(importMap, resolvedOrPlain, parentUrl) {
|
|
|
988
1210
|
}
|
|
989
1211
|
scopeUrl = getMatch(scopeUrl.slice(0, scopeUrl.lastIndexOf('/')), scopes);
|
|
990
1212
|
}
|
|
991
|
-
return (
|
|
1213
|
+
return (
|
|
1214
|
+
applyPackages(resolvedOrPlain, importMap.imports, importMap.default) ||
|
|
992
1215
|
(isUrl(resolvedOrPlain) && resolvedOrPlain) ||
|
|
993
|
-
undefined
|
|
1216
|
+
undefined
|
|
1217
|
+
);
|
|
994
1218
|
}
|
|
1219
|
+
|
|
995
1220
|
// In place transformation of the ImportMap object
|
|
996
|
-
function resolveAndComposePackages(
|
|
1221
|
+
function resolveAndComposePackages(
|
|
1222
|
+
packages,
|
|
1223
|
+
outPackages,
|
|
1224
|
+
baseUrl,
|
|
1225
|
+
parentMap,
|
|
1226
|
+
parentUrl,
|
|
1227
|
+
) {
|
|
997
1228
|
for (const p in packages) {
|
|
998
1229
|
const resolvedLhs = resolveIfNotPlainOrUrl(p, baseUrl) || p;
|
|
999
1230
|
const rhs = packages[p];
|
|
@@ -1001,42 +1232,62 @@ function resolveAndComposePackages(packages, outPackages, baseUrl, parentMap, pa
|
|
|
1001
1232
|
if (typeof rhs !== 'string') {
|
|
1002
1233
|
continue;
|
|
1003
1234
|
}
|
|
1004
|
-
const mapped = resolveImportMapEntry(
|
|
1235
|
+
const mapped = resolveImportMapEntry(
|
|
1236
|
+
parentMap,
|
|
1237
|
+
resolveIfNotPlainOrUrl(rhs, baseUrl) || rhs,
|
|
1238
|
+
parentUrl,
|
|
1239
|
+
);
|
|
1005
1240
|
if (!mapped) {
|
|
1006
1241
|
targetWarning(p, rhs, 'bare specifier did not resolve');
|
|
1007
|
-
}
|
|
1008
|
-
else {
|
|
1242
|
+
} else {
|
|
1009
1243
|
outPackages[resolvedLhs] = mapped;
|
|
1010
1244
|
}
|
|
1011
1245
|
}
|
|
1012
1246
|
}
|
|
1247
|
+
|
|
1013
1248
|
// Composes a single import map object given a child and parent import map
|
|
1014
|
-
function resolveAndComposeImportMap(
|
|
1249
|
+
function resolveAndComposeImportMap(
|
|
1250
|
+
json,
|
|
1251
|
+
baseUrl,
|
|
1252
|
+
parentMap = { imports: {}, scopes: {} },
|
|
1253
|
+
) {
|
|
1015
1254
|
const outMap = {
|
|
1016
1255
|
imports: Object.assign({}, parentMap.imports),
|
|
1017
1256
|
scopes: Object.assign({}, parentMap.scopes),
|
|
1018
1257
|
default: json.default,
|
|
1019
1258
|
};
|
|
1259
|
+
|
|
1020
1260
|
if (json.imports) {
|
|
1021
1261
|
resolveAndComposePackages(json.imports, outMap.imports, baseUrl, parentMap);
|
|
1022
1262
|
}
|
|
1263
|
+
|
|
1023
1264
|
if (json.scopes) {
|
|
1024
1265
|
for (const s in json.scopes) {
|
|
1025
1266
|
const resolvedScope = resolveUrl(s, baseUrl);
|
|
1026
|
-
resolveAndComposePackages(
|
|
1267
|
+
resolveAndComposePackages(
|
|
1268
|
+
json.scopes[s],
|
|
1269
|
+
outMap.scopes[resolvedScope] || (outMap.scopes[resolvedScope] = {}),
|
|
1270
|
+
baseUrl,
|
|
1271
|
+
parentMap,
|
|
1272
|
+
resolvedScope,
|
|
1273
|
+
);
|
|
1027
1274
|
}
|
|
1028
1275
|
}
|
|
1276
|
+
|
|
1029
1277
|
if (json.default) {
|
|
1030
1278
|
outMap.default = resolveIfNotPlainOrUrl(json.default, baseUrl);
|
|
1031
1279
|
}
|
|
1280
|
+
|
|
1032
1281
|
return outMap;
|
|
1033
1282
|
}
|
|
1034
1283
|
|
|
1035
1284
|
/* spec based import map resolver */
|
|
1036
|
-
class ImportMapResolver
|
|
1285
|
+
class ImportMapResolver {
|
|
1286
|
+
|
|
1037
1287
|
constructor(importMap) {
|
|
1038
1288
|
this.importMap = importMap;
|
|
1039
1289
|
}
|
|
1290
|
+
|
|
1040
1291
|
resolve(resolvedOrPlain, parentUrl) {
|
|
1041
1292
|
return resolveImportMapEntry(this.importMap, resolvedOrPlain, parentUrl);
|
|
1042
1293
|
}
|
|
@@ -1047,26 +1298,33 @@ class ImportMapResolver {
|
|
|
1047
1298
|
*
|
|
1048
1299
|
* This implementation is adapted from https://github.com/systemjs/systemjs/blob/master/src/features/import-map.js
|
|
1049
1300
|
*/
|
|
1301
|
+
|
|
1050
1302
|
const IMPORTMAP_SCRIPT_TYPE = 'lwr-importmap';
|
|
1303
|
+
|
|
1051
1304
|
// iterates on the any <script type="${IMPORTMAP_SCRIPT_TYPE}", invoking the given callback for each
|
|
1052
|
-
function iterateDocumentImportMaps(
|
|
1305
|
+
function iterateDocumentImportMaps(
|
|
1306
|
+
callBack,
|
|
1307
|
+
extraSelector,
|
|
1308
|
+
) {
|
|
1053
1309
|
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
1054
1310
|
const nodeList = document.querySelectorAll(`script[type="${IMPORTMAP_SCRIPT_TYPE}"]` + extraSelector);
|
|
1055
1311
|
const filtered = Array.from(nodeList).filter((node) => {
|
|
1056
|
-
if (node.src) {
|
|
1312
|
+
if ((node ).src) {
|
|
1057
1313
|
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
1058
|
-
if (hasConsole)
|
|
1059
|
-
console.warn('LWR does not support import maps from script src');
|
|
1314
|
+
if (hasConsole) console.warn('LWR does not support import maps from script src');
|
|
1060
1315
|
return false;
|
|
1061
1316
|
}
|
|
1062
1317
|
return true;
|
|
1063
1318
|
});
|
|
1319
|
+
|
|
1064
1320
|
Array.prototype.forEach.call(filtered, callBack);
|
|
1065
1321
|
}
|
|
1322
|
+
|
|
1066
1323
|
// retrives the import map text from a <script type="${IMPORTMAP_SCRIPT_TYPE}"
|
|
1067
1324
|
async function getImportMapFromScript(script) {
|
|
1068
1325
|
return Promise.resolve(script.innerHTML);
|
|
1069
1326
|
}
|
|
1327
|
+
|
|
1070
1328
|
// get importMap from <script type="lwr-importmap">
|
|
1071
1329
|
async function evaluateImportMaps(baseUrl) {
|
|
1072
1330
|
let importMap = { imports: {}, scopes: {} };
|
|
@@ -1078,23 +1336,27 @@ async function evaluateImportMaps(baseUrl) {
|
|
|
1078
1336
|
if (!baseUrl) {
|
|
1079
1337
|
throw new LoaderError(NO_BASE_URL);
|
|
1080
1338
|
}
|
|
1339
|
+
|
|
1081
1340
|
iterateDocumentImportMaps((script) => {
|
|
1082
1341
|
importMapPromise = importMapPromise
|
|
1083
1342
|
.then(() => {
|
|
1084
|
-
|
|
1085
|
-
|
|
1343
|
+
return getImportMapFromScript(script);
|
|
1344
|
+
})
|
|
1086
1345
|
.then((importMapTxt) => {
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
}
|
|
1093
|
-
})
|
|
1346
|
+
try {
|
|
1347
|
+
return JSON.parse(importMapTxt);
|
|
1348
|
+
} catch (e) {
|
|
1349
|
+
throw new LoaderError(BAD_IMPORT_MAP);
|
|
1350
|
+
}
|
|
1351
|
+
})
|
|
1094
1352
|
.then((jsonImportMap) => {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1353
|
+
importMap = resolveAndComposeImportMap(
|
|
1354
|
+
jsonImportMap,
|
|
1355
|
+
script.src || (baseUrl ),
|
|
1356
|
+
importMap,
|
|
1357
|
+
);
|
|
1358
|
+
return importMap;
|
|
1359
|
+
});
|
|
1098
1360
|
}, '');
|
|
1099
1361
|
}
|
|
1100
1362
|
return importMapPromise;
|
|
@@ -1104,6 +1366,10 @@ async function evaluateImportMaps(baseUrl) {
|
|
|
1104
1366
|
* The LWR loader is inspired and borrows from the algorithms and native browser principles of https://github.com/systemjs/systemjs
|
|
1105
1367
|
*/
|
|
1106
1368
|
class Loader {
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
|
|
1107
1373
|
constructor(config) {
|
|
1108
1374
|
config = config || {};
|
|
1109
1375
|
let baseUrl = config.baseUrl;
|
|
@@ -1119,6 +1385,7 @@ class Loader {
|
|
|
1119
1385
|
throw new LoaderError(NO_BASE_URL);
|
|
1120
1386
|
}
|
|
1121
1387
|
this.baseUrl = baseUrl;
|
|
1388
|
+
|
|
1122
1389
|
if (!profiler) {
|
|
1123
1390
|
// default noop profiler
|
|
1124
1391
|
profiler = {
|
|
@@ -1130,7 +1397,9 @@ class Loader {
|
|
|
1130
1397
|
},
|
|
1131
1398
|
};
|
|
1132
1399
|
}
|
|
1400
|
+
|
|
1133
1401
|
this.registry = new ModuleRegistry({ baseUrl, profiler });
|
|
1402
|
+
|
|
1134
1403
|
// TODO: https://github.com/salesforce-experience-platform-emu/lwr/issues/1087
|
|
1135
1404
|
this.services = Object.freeze({
|
|
1136
1405
|
addLoaderPlugin: this.registry.addLoaderPlugin.bind(this.registry),
|
|
@@ -1138,6 +1407,7 @@ class Loader {
|
|
|
1138
1407
|
appMetadata: config.appMetadata,
|
|
1139
1408
|
});
|
|
1140
1409
|
}
|
|
1410
|
+
|
|
1141
1411
|
/**
|
|
1142
1412
|
* Defines/registers a single named AMD module definition.
|
|
1143
1413
|
*
|
|
@@ -1147,21 +1417,31 @@ class Loader {
|
|
|
1147
1417
|
* @param {ModuleDefinitionSignatures} signatures Object containing the module signature and the signatures of its dependencies
|
|
1148
1418
|
* @return {void}
|
|
1149
1419
|
*/
|
|
1150
|
-
define(
|
|
1420
|
+
define(
|
|
1421
|
+
name,
|
|
1422
|
+
dependencies,
|
|
1423
|
+
execute,
|
|
1424
|
+
signatures,
|
|
1425
|
+
) {
|
|
1151
1426
|
invariant(typeof name === 'string', MISSING_NAME);
|
|
1152
1427
|
let ctor = execute;
|
|
1153
1428
|
let deps = dependencies;
|
|
1154
1429
|
let sigs = signatures;
|
|
1430
|
+
|
|
1155
1431
|
// Convert no dependencies form `define('name', function(){}, {});` to: `define('name', [], function(){}, {})`
|
|
1156
1432
|
if (typeof deps === 'function') {
|
|
1157
1433
|
ctor = dependencies;
|
|
1158
1434
|
deps = [];
|
|
1159
1435
|
sigs = execute;
|
|
1160
1436
|
}
|
|
1437
|
+
|
|
1161
1438
|
sigs = sigs || {};
|
|
1439
|
+
|
|
1162
1440
|
invariant(Array.isArray(deps), INVALID_DEPS);
|
|
1163
|
-
|
|
1441
|
+
|
|
1442
|
+
this.registry.define(name, deps, ctor , sigs );
|
|
1164
1443
|
}
|
|
1444
|
+
|
|
1165
1445
|
/**
|
|
1166
1446
|
* Retrieves/loads a module, returning it from the registry if it exists and fetching it if it doesn't.
|
|
1167
1447
|
*
|
|
@@ -1173,6 +1453,7 @@ class Loader {
|
|
|
1173
1453
|
async load(id, importer) {
|
|
1174
1454
|
return this.registry.load(id, importer);
|
|
1175
1455
|
}
|
|
1456
|
+
|
|
1176
1457
|
/**
|
|
1177
1458
|
* Checks if a Module exists in the registry. Note, returns false even if the ModuleDefinition exists but the Module has not been instantiated yet (executed).
|
|
1178
1459
|
*
|
|
@@ -1182,6 +1463,7 @@ class Loader {
|
|
|
1182
1463
|
has(id) {
|
|
1183
1464
|
return this.registry.has(id);
|
|
1184
1465
|
}
|
|
1466
|
+
|
|
1185
1467
|
/**
|
|
1186
1468
|
* Resolves the module identifier or URL. Returns the module identifier if the moduleDefinition exists, or the full resolved URL if a URL is given.
|
|
1187
1469
|
*
|
|
@@ -1193,13 +1475,14 @@ class Loader {
|
|
|
1193
1475
|
async resolve(id, importer) {
|
|
1194
1476
|
return this.registry.resolve(id, importer);
|
|
1195
1477
|
}
|
|
1478
|
+
|
|
1479
|
+
|
|
1196
1480
|
async registerImportMappings(mappings) {
|
|
1197
1481
|
let importMap;
|
|
1198
1482
|
if (!mappings) {
|
|
1199
1483
|
// If no mappings given, check for lwr-importmap on the document
|
|
1200
1484
|
importMap = await evaluateImportMaps(this.baseUrl);
|
|
1201
|
-
}
|
|
1202
|
-
else {
|
|
1485
|
+
} else {
|
|
1203
1486
|
// merge the new mappings with the base import map - note this goes against
|
|
1204
1487
|
// import maps spec if we do this after resolving any imports
|
|
1205
1488
|
importMap = resolveAndComposeImportMap(mappings, this.baseUrl, this.parentImportMap);
|
|
@@ -1210,6 +1493,7 @@ class Loader {
|
|
|
1210
1493
|
this.registry.setImportResolver(importMapResolver);
|
|
1211
1494
|
}
|
|
1212
1495
|
}
|
|
1496
|
+
|
|
1213
1497
|
/**
|
|
1214
1498
|
* Marks modules as "externally" loaded/provided (e.g. preloaded), so that the loader does not attempt to load them.
|
|
1215
1499
|
*
|
|
@@ -1221,3 +1505,4 @@ class Loader {
|
|
|
1221
1505
|
}
|
|
1222
1506
|
|
|
1223
1507
|
export { Loader };
|
|
1508
|
+
//# sourceMappingURL=loaderLegacy.js.map
|