@lwrjs/everywhere 0.9.0-alpha.9 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +1 -1
  2. package/build/__generated_site_amd_modules__/1/application/amd/l/en-US/ai/amd-bootstrap/configuration/ci/-/-/s/9c07e4a986679d89bf69e66fe60ce615/config.js +10 -0
  3. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/@lwrjs/app-service/amd-bootstrap/module/amd/v/0_9_0/s/c40e6caf07454ce13961de8ca76ab7f0/@lwrjs_app-service_amd-bootstrap_module_amd.js +18 -0
  4. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwc/v/2_38_1/s/8cf6b94d9c0b398c70c97fdca2759caa/lwc.js +8934 -0
  5. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/everywhereAmd/v/0_9_0/s/c538071acf5bde58e816967a14c465c3/lwr_everywhereAmd.js +66 -0
  6. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/init/v/0_9_0/s/206e6e0af6f019fdfd86d87d56331bc2/lwr_init.js +97 -0
  7. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/loader/v/{0_9_0-alpha_9/s/07df3ed331f5f6b3c21336c94dac7c0b → 0_9_0/s/37491c0be6765e2cd302cf146e9d624a}/lwr_loader.js +362 -137
  8. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/metrics/v/0_9_0/s/3426e42c3e22ce07ab2adc62c4c523a0/lwr_metrics.js +66 -0
  9. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/profiler/v/0_9_0/s/e25f3b0b8b5c096acebf847d0a83ea62/lwr_profiler.js +68 -0
  10. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/vault/v/0_9_0/s/c92abd8c1fec2d7eff62e4b097abbe14/lwr_vault.js +21 -0
  11. package/build/__generated_site_amd_modules__/1/resource/amd/lwr-error-shim.js/v/{0_9_0-alpha_9 → 0_9_0/lwr-error-shim.js} +1 -1
  12. package/build/__generated_site_amd_modules__/1/resource/amd/lwr-loader-shim.bundle.js/v/0_9_0/lwr-loader-shim.bundle.js +1547 -0
  13. package/build/assets/amd/lwr-everywhere-debug.js +39 -27
  14. package/build/assets/amd/lwr-everywhere-min.js +1 -1
  15. package/build/assets/amd/lwr-everywhere.js +39 -27
  16. package/build/assets/core/lwr-everywhere-debug.js +36 -24
  17. package/build/assets/core/lwr-everywhere-min.js +1 -1
  18. package/build/assets/core/lwr-everywhere.js +36 -24
  19. package/build/assets/esm/lwr-everywhere-debug.js +1 -1
  20. package/build/assets/esm/lwr-everywhere-min.js +1 -1
  21. package/build/assets/esm/lwr-everywhere.js +1 -1
  22. package/build/modules/@salesforce/lds-default-luvio/lds-default-luvio.js +11 -7
  23. package/build/modules/lwr/everywhere/everywhere.js +6 -7
  24. package/build/modules/lwr/everywhereAmd/everywhereAmd.js +9 -11
  25. package/build/modules/lwr/everywhereEsm/everywhereEsm.js +1 -2
  26. package/build/modules/lwr/host/host.js +23 -27
  27. package/build/modules/lwr/setupLDS/network.js +9 -17
  28. package/build/modules/lwr/setupLDS/setupLDS.js +6 -4
  29. package/build/modules/lwr/setupNodeLDS/network.js +9 -17
  30. package/build/modules/lwr/setupNodeLDS/setupNodeLDS.js +3 -1
  31. package/build/modules/lwr/vault/vault.js +3 -1
  32. package/package.json +11 -8
  33. package/build/__generated_site_amd_modules__/1/application/amd/l/en-US/ai/amd-bootstrap/configuration/ci/-/-/s/102a7c627b0f61cba691a7fa94d6a856/config.js +0 -10
  34. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/@lwrjs/app-service/amd-bootstrap/module/amd/v/0_9_0-alpha_9/s/c40e6caf07454ce13961de8ca76ab7f0/@lwrjs_app-service_amd-bootstrap_module_amd.js +0 -14
  35. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwc/v/2_33_0/s/90a5f16131da45cef1653112862ca9dc/lwc.js +0 -7090
  36. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/everywhereAmd/v/0_9_0-alpha_9/s/c538071acf5bde58e816967a14c465c3/lwr_everywhereAmd.js +0 -48
  37. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/init/v/0_9_0-alpha_9/s/6258bcb20cc2d5d6a9f3c5a6f9d0acaf/lwr_init.js +0 -58
  38. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/metrics/v/0_9_0-alpha_9/s/dfbc827104d50ff7d16b59c9d0e06aca/lwr_metrics.js +0 -56
  39. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/profiler/v/0_9_0-alpha_9/s/5a10236d8c52bc9f6dee22875cd7016d/lwr_profiler.js +0 -51
  40. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/vault/v/0_9_0-alpha_9/s/c92abd8c1fec2d7eff62e4b097abbe14/lwr_vault.js +0 -13
  41. package/build/__generated_site_amd_modules__/1/resource/amd/lwr-loader-shim.js/v/0_9_0-alpha_9 +0 -311
  42. package/build/__generated_site_amd_modules__/en-US/index.html +0 -26
  43. package/build/__generated_site_amd_modules__/index.html +0 -26
@@ -0,0 +1,1547 @@
1
+ /**
2
+ * Copyright (c) 2021, salesforce.com, inc.
3
+ * All rights reserved.
4
+ * SPDX-License-Identifier: MIT
5
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6
+ */
7
+ /* LWR Module Loader Shim v0.9.0 */
8
+ (function () {
9
+ 'use strict';
10
+
11
+ // Bootstrap / shim
12
+ const BOOTSTRAP_PREFIX = 'lwr.bootstrap.';
13
+ const BOOTSTRAP_ERROR = `${BOOTSTRAP_PREFIX}error`;
14
+
15
+ var Phase;
16
+ (function (Phase) {
17
+ Phase[Phase["Start"] = 0] = "Start";
18
+ Phase[Phase["End"] = 1] = "End";
19
+ })(Phase || (Phase = {}));
20
+ // Attach a custom dispatcher
21
+ let customDispatcher;
22
+ function attachDispatcher(dispatcher) {
23
+ customDispatcher = dispatcher;
24
+ }
25
+
26
+ // Check if the Performance API is available
27
+ // e.g. JSDom (used in Jest) doesn't implement these
28
+ const perf = globalThis.performance;
29
+ const isPerfSupported = typeof perf !== 'undefined' && typeof perf.mark === 'function' && typeof perf.clearMarks === 'function' && typeof perf.measure === 'function' && typeof perf.clearMeasures === 'function';
30
+
31
+ // For marking request metrics
32
+ // Fallback to the Performance API if there is no custom dispatcher
33
+ function logOperationStart({
34
+ id,
35
+ specifier
36
+ }) {
37
+ if (customDispatcher) {
38
+ customDispatcher({
39
+ id,
40
+ phase: Phase.Start,
41
+ specifier
42
+ });
43
+ } else if (isPerfSupported) {
44
+ perf.mark(id + (specifier ? `.${specifier}` : ''));
45
+ }
46
+ }
47
+
48
+ // For measuring duration metrics
49
+ // Fallback to the Performance API if there is no custom dispatcher
50
+ /* istanbul ignore next */
51
+ function logOperationEnd({
52
+ id,
53
+ specifier
54
+ }) {
55
+ if (customDispatcher) {
56
+ customDispatcher({
57
+ id,
58
+ phase: Phase.End,
59
+ specifier
60
+ });
61
+ } else if (isPerfSupported) {
62
+ const suffix = specifier ? `.${specifier}` : '';
63
+ const markName = id + suffix;
64
+ const measureName = `${id}.duration${suffix}`;
65
+ perf.measure(measureName, markName);
66
+
67
+ // Clear the created mark and measure to avoid filling the performance entry buffer
68
+ // Even if they get deleted, existing PerformanceObservers preserve copies of the entries
69
+ perf.clearMarks(markName);
70
+ perf.clearMeasures(measureName);
71
+ }
72
+ }
73
+
74
+ function createLoader(name, definition, config, externalModules) {
75
+ if (!definition || typeof definition[2] !== 'function') {
76
+ throw new Error(`Expected loader with specifier "${name}" to be a module`);
77
+ }
78
+ // Create a Loader instance
79
+ const exports = {};
80
+ definition[2].call(null, exports);
81
+ const { Loader } = exports;
82
+ const loader = new Loader(config);
83
+ if (externalModules && externalModules.length) {
84
+ loader.registerExternalModules(externalModules);
85
+ }
86
+ // Define the loader module with public API: { define, load, services }
87
+ const exporter = (exports) => {
88
+ Object.assign(exports, {
89
+ define: loader.define.bind(loader),
90
+ load: loader.load.bind(loader),
91
+ services: loader.services,
92
+ });
93
+ };
94
+ loader.define(name, ['exports'], exporter);
95
+ return loader;
96
+ }
97
+
98
+ const REQUIRED_MODULES_TIMEOUT = 300 * 1000;
99
+
100
+ // Check for errors with autoBoot and customInit
101
+ function validatePreInit(autoBoot, customInit) {
102
+ // If autoBoot === false, there must be a customInit hook
103
+ if (!autoBoot && !customInit) {
104
+ throw new Error('The customInit hook is required when autoBoot is false');
105
+ }
106
+ // If autoBoot === true, there must NOT be a customInit hook
107
+ if (autoBoot && customInit) {
108
+ throw new Error('The customInit hook must not be defined when autoBoot is true');
109
+ }
110
+ }
111
+ // Process the customInit hook
112
+ function customInit(config, initializeApp, define, onBootstrapError) {
113
+ // Validate config
114
+ const { autoBoot, customInit } = config;
115
+ validatePreInit(autoBoot, customInit);
116
+ // Set up arguments and call the customInit hook, if available
117
+ if (customInit) {
118
+ const lwr = {
119
+ initializeApp,
120
+ define,
121
+ onBootstrapError,
122
+ attachDispatcher,
123
+ };
124
+ customInit(lwr, config);
125
+ }
126
+ }
127
+
128
+ /* global document */
129
+ /* eslint-disable lwr/no-unguarded-apis */
130
+ const hasSetTimeout = typeof setTimeout === 'function';
131
+ const hasConsole = typeof console !== 'undefined';
132
+ /* eslint-enable lwr/no-unguarded-apis */
133
+ class LoaderShim {
134
+ constructor(global) {
135
+ this.defineCache = {};
136
+ this.orderedDefs = [];
137
+ // Start watchdog timer
138
+ if (hasSetTimeout) {
139
+ this.watchdogTimerId = this.startWatchdogTimer();
140
+ }
141
+ // Parse configuration
142
+ this.global = global;
143
+ this.config = global.LWR;
144
+ this.loaderSpecifier = 'lwr/loader/v/0_9_0';
145
+ // Set up error handler
146
+ this.errorHandler = this.config.onError;
147
+ // Set up the temporary LWR.define function and customInit hook
148
+ const tempDefine = this.tempDefine.bind(this);
149
+ global.LWR.define = tempDefine;
150
+ this.bootReady = this.config.autoBoot;
151
+ try {
152
+ this.createProfilerModule(this.config);
153
+ customInit(Object.freeze(this.config), this.postCustomInit.bind(this), tempDefine, (e) => {
154
+ // customInit handlers can overwrite
155
+ // the error handler with onBootstrapError
156
+ this.errorHandler = e;
157
+ });
158
+ }
159
+ catch (e) {
160
+ this.enterErrorState(e);
161
+ }
162
+ }
163
+ // Return true if the app can be initialized
164
+ canInit() {
165
+ // Initialize the app if:
166
+ // - bootReady: autoBoot is on OR customInit has finished
167
+ // - all required modules are defined
168
+ const allDefined = this.config.requiredModules.every((m) => this.orderedDefs.includes(m));
169
+ return this.bootReady && allDefined;
170
+ }
171
+ /**
172
+ * Create a temporary LWR.define() function which captures all
173
+ * calls that occur BEFORE the full loader module is available
174
+ *
175
+ * Each call to LWR.define() is stored in 2 ways:
176
+ * - in a map as [moduleName, arguments] pairs
177
+ * - each moduleName is pushed onto an array, to preserve
178
+ * the order in which the modules were defined
179
+ */
180
+ tempDefine(...args) {
181
+ // Cache the incoming module
182
+ const moduleName = args[0];
183
+ this.defineCache[moduleName] = args;
184
+ this.orderedDefs.push(moduleName);
185
+ if (this.canInit()) {
186
+ if (hasSetTimeout) {
187
+ // requiredModules are defined, clear watchdog timer
188
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
189
+ clearTimeout(this.watchdogTimerId);
190
+ }
191
+ this.initApp();
192
+ }
193
+ }
194
+ // Called by the customInit hook via lwr.initializeApp()
195
+ postCustomInit() {
196
+ this.bootReady = true;
197
+ if (this.canInit()) {
198
+ this.initApp();
199
+ }
200
+ }
201
+ // Create the loader and initialize the application
202
+ initApp() {
203
+ try {
204
+ const loaderConfig = {
205
+ endpoints: this.config.endpoints,
206
+ baseUrl: this.config.baseUrl,
207
+ profiler: { logOperationStart, logOperationEnd },
208
+ // TODO: can be removed following https://github.com/salesforce-experience-platform-emu/lwr/issues/1087
209
+ appMetadata: {
210
+ appId: this.config.appId,
211
+ bootstrapModule: this.config.bootstrapModule,
212
+ rootComponent: this.config.rootComponent,
213
+ rootComponents: this.config.rootComponents,
214
+ },
215
+ };
216
+ const loader = createLoader(this.loaderSpecifier, this.defineCache[this.loaderSpecifier], loaderConfig, this.config.preloadModules);
217
+ this.mountApp(loader);
218
+ }
219
+ catch (e) {
220
+ this.enterErrorState(e);
221
+ }
222
+ }
223
+ waitForDOMContentLoaded() {
224
+ // eslint-disable-next-line lwr/no-unguarded-apis
225
+ if (typeof document === undefined) {
226
+ return Promise.resolve();
227
+ }
228
+ // Resolve if document is already "ready" https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
229
+ // eslint-disable-next-line lwr/no-unguarded-apis
230
+ if (document.readyState === 'interactive' || document.readyState === 'complete') {
231
+ return Promise.resolve();
232
+ }
233
+ return new Promise((resolve) => {
234
+ // eslint-disable-next-line lwr/no-unguarded-apis
235
+ document.addEventListener('DOMContentLoaded', () => {
236
+ resolve();
237
+ });
238
+ });
239
+ }
240
+ // Create a module out of the profiler
241
+ // Note: The profiler is also available as a module through lwc module resolution (see package.json)
242
+ createProfilerModule(globalLWR) {
243
+ const exporter = (exports) => {
244
+ Object.assign(exports, { logOperationStart, logOperationEnd });
245
+ };
246
+ globalLWR.define('lwr/profiler/v/0_9_0', ['exports'], exporter);
247
+ }
248
+ // Set up the application globals, import map, root custom element...
249
+ mountApp(loader) {
250
+ const { bootstrapModule, rootComponent, rootComponents, ssrProps, endpoints, imports, index } = this.config;
251
+ // Set global LWR.define to loader.define
252
+ this.global.LWR = Object.freeze({
253
+ define: loader.define.bind(loader),
254
+ rootComponent,
255
+ rootComponents,
256
+ ssrProps,
257
+ endpoints,
258
+ imports: imports || {},
259
+ index: index || {},
260
+ });
261
+ // Redefine all modules in the temporary cache
262
+ this.orderedDefs.forEach((specifier) => {
263
+ if (specifier !== this.loaderSpecifier) {
264
+ loader.define(...this.defineCache[specifier]);
265
+ }
266
+ });
267
+ // by default, app initialization is gated on waiting for document to be parsed (via DOMContentLoaded)
268
+ const { disableInitDefer } = this.config;
269
+ // Load the import mappings and application bootstrap module
270
+ loader
271
+ .registerImportMappings({ imports, index }, [bootstrapModule, rootComponent])
272
+ .then(() => {
273
+ if (!disableInitDefer) {
274
+ return this.waitForDOMContentLoaded();
275
+ }
276
+ })
277
+ .then(() => loader.load(bootstrapModule))
278
+ .catch((reason) => {
279
+ this.enterErrorState(new Error(`Application ${rootComponent || bootstrapModule} could not be loaded: ${reason}`));
280
+ });
281
+ }
282
+ // Trigger bootstrap error state, and call error handler if registered
283
+ enterErrorState(error) {
284
+ logOperationStart({ id: BOOTSTRAP_ERROR });
285
+ if (this.errorHandler) {
286
+ this.errorHandler(error);
287
+ }
288
+ else {
289
+ if (hasConsole) {
290
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
291
+ console.error(`An error occurred during LWR bootstrap. ${error.message}`, error.stack);
292
+ }
293
+ }
294
+ }
295
+ // eslint-disable-next-line no-undef, lwr/no-unguarded-apis
296
+ startWatchdogTimer() {
297
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
298
+ return setTimeout(() => {
299
+ this.enterErrorState(new Error('Failed to load required modules - timed out'));
300
+ }, REQUIRED_MODULES_TIMEOUT);
301
+ }
302
+ }
303
+
304
+ // The loader module is ALWAYS required
305
+ const GLOBAL = globalThis;
306
+ GLOBAL.LWR.requiredModules = GLOBAL.LWR.requiredModules || [];
307
+ if (GLOBAL.LWR.requiredModules.indexOf('lwr/loader/v/0_9_0') < 0) {
308
+ GLOBAL.LWR.requiredModules.push('lwr/loader/v/0_9_0');
309
+ }
310
+ new LoaderShim(GLOBAL);
311
+
312
+ }());
313
+
314
+ LWR.define('lwr/loader/v/0_9_0', ['exports'], function (exports) { 'use strict';
315
+
316
+ const templateRegex = /\{([0-9]+)\}/g;
317
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
318
+ function templateString(template, args) {
319
+ return template.replace(templateRegex, (_, index) => {
320
+ return args[index];
321
+ });
322
+ }
323
+
324
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
325
+ function generateErrorMessage(errorInfo, args) {
326
+ const message = Array.isArray(args) ? templateString(errorInfo.message, args) : errorInfo.message;
327
+ return `LWR${errorInfo.code}: ${message}`;
328
+ }
329
+ class LoaderError extends Error {
330
+ constructor(errorInfo, errorArgs) {
331
+ super();
332
+ this.message = generateErrorMessage(errorInfo, errorArgs);
333
+ }
334
+ }
335
+ function invariant(condition, errorInfo) {
336
+ if (!condition) {
337
+ throw new LoaderError(errorInfo);
338
+ }
339
+ }
340
+ const MISSING_NAME = Object.freeze({
341
+ code: 3000,
342
+ message: 'A module name is required.',
343
+ level: 0,
344
+ });
345
+ const FAIL_INSTANTIATE = Object.freeze({
346
+ code: 3004,
347
+ message: 'Failed to instantiate module: {0}',
348
+ level: 0,
349
+ });
350
+ const NO_AMD_REQUIRE = Object.freeze({
351
+ code: 3005,
352
+ message: 'AMD require not supported.',
353
+ level: 0,
354
+ });
355
+ const FAILED_DEP = Object.freeze({
356
+ code: 3006,
357
+ level: 0,
358
+ message: 'Failed to load dependency: {0}',
359
+ });
360
+ const INVALID_DEPS = Object.freeze({
361
+ code: 3007,
362
+ message: 'Unexpected value received for dependencies argument; expected an array.',
363
+ level: 0,
364
+ });
365
+ const FAIL_LOAD = Object.freeze({
366
+ code: 3008,
367
+ level: 0,
368
+ message: 'Error loading {0}',
369
+ });
370
+ const UNRESOLVED = Object.freeze({
371
+ code: 3009,
372
+ level: 0,
373
+ message: 'Unable to resolve bare specifier: {0}',
374
+ });
375
+ const NO_BASE_URL = Object.freeze({
376
+ code: 3010,
377
+ level: 0,
378
+ message: 'baseUrl not set',
379
+ });
380
+ Object.freeze({
381
+ code: 3011,
382
+ level: 0,
383
+ message: 'Cannot set a loader service multiple times',
384
+ });
385
+ const INVALID_HOOK = Object.freeze({
386
+ code: 3012,
387
+ level: 0,
388
+ message: 'Invalid hook received',
389
+ });
390
+ const INVALID_LOADER_SERVICE_RESPONSE = Object.freeze({
391
+ code: 3013,
392
+ level: 0,
393
+ message: 'Invalid response received from hook',
394
+ });
395
+ const MODULE_LOAD_TIMEOUT = Object.freeze({
396
+ code: 3014,
397
+ level: 0,
398
+ message: 'Error loading {0} - timed out',
399
+ });
400
+ const HTTP_FAIL_LOAD = Object.freeze({
401
+ code: 3015,
402
+ level: 0,
403
+ message: 'Error loading {0}, status code {1}',
404
+ });
405
+ const STALE_HOOK_ERROR = Object.freeze({
406
+ code: 3016,
407
+ level: 0,
408
+ message: 'An error occurred handling module conflict',
409
+ });
410
+ const MODULE_ALREADY_LOADED = Object.freeze({
411
+ code: 3017,
412
+ level: 0,
413
+ message: 'Marking module(s) as externally loaded, but they are already loaded:',
414
+ });
415
+ const FAIL_HOOK_LOAD = Object.freeze({
416
+ code: 3018,
417
+ level: 0,
418
+ message: 'Error loading "{0}" from hook',
419
+ });
420
+ const NO_MAPPING_URL = Object.freeze({
421
+ code: 3019,
422
+ level: 0,
423
+ message: 'Mapping endpoint not set',
424
+ });
425
+ const BAD_IMPORT_METADATA = Object.freeze({
426
+ code: 3020,
427
+ level: 0,
428
+ message: 'Invalid import metadata: {0} {1}',
429
+ });
430
+ /* importMap errors */
431
+ Object.freeze({
432
+ code: 3011,
433
+ level: 0,
434
+ message: 'import map is not valid',
435
+ });
436
+
437
+ /* eslint-disable lwr/no-unguarded-apis */
438
+ const hasDocument = typeof document !== 'undefined';
439
+ const hasSetTimeout = typeof setTimeout === 'function';
440
+ const hasConsole = typeof console !== 'undefined';
441
+ /* eslint-enable lwr/no-unguarded-apis */
442
+
443
+ function getBaseUrl() {
444
+ let baseUrl = undefined;
445
+ if (hasDocument) {
446
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
447
+ const baseEl = document.querySelector('base[href]');
448
+ baseUrl = baseEl && baseEl.href;
449
+ }
450
+ // eslint-disable-next-line lwr/no-unguarded-apis
451
+ if (!baseUrl && typeof location !== 'undefined') {
452
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
453
+ baseUrl = location.href.split('#')[0].split('?')[0];
454
+ const lastSepIndex = baseUrl.lastIndexOf('/');
455
+ if (lastSepIndex !== -1) {
456
+ baseUrl = baseUrl.slice(0, lastSepIndex + 1);
457
+ }
458
+ }
459
+ return baseUrl;
460
+ }
461
+ /**
462
+ * Check if a string is a URL based on Common Internet Scheme Syntax
463
+ * https://www.ietf.org/rfc/rfc1738.txt
464
+ *
465
+ * URL Format:
466
+ * <scheme>:<scheme-specific-part>
467
+ * Common Internet Scheme Syntax:
468
+ * The scheme specific part starts with a double slash('//')
469
+ *
470
+ * A valid URL has a colon that is followed by a double slash.
471
+ *
472
+ * @param url - the url that is being checked
473
+ * @returns boolean
474
+ *
475
+ * @example Valid URLs
476
+ * 'https://salesforce.com'
477
+ * 'http://localhost:3000'
478
+ *
479
+ * @example Invalid URLs
480
+ * 'salesforce.com'
481
+ * 'localhost:3000'
482
+ * '@salesforce/label/type:namespace:name'
483
+ */
484
+ function isUrl(url) {
485
+ return url.indexOf('://') !== -1;
486
+ }
487
+ // Borrowed and adapted from https://github.com/systemjs/systemjs/blob/master/src/common.js
488
+ // Resolves the first path segment relative to the second/parent URL
489
+ // eg: resolveIfNotPlainOrUrl('../test', 'http://www.site.com/one/two') => 'http://www.site.com/test'
490
+ // eg: resolveIfNotPlainOrUrl('./x/y/z', 'https://my.com/segment')).toBe('https://my.com/x/y/z')
491
+ function resolveIfNotPlainOrUrl(relUrl, parentUrl) {
492
+ const backslashRegEx = /\\/g;
493
+ if (relUrl.indexOf('\\') !== -1)
494
+ relUrl = relUrl.replace(backslashRegEx, '/');
495
+ // protocol-relative
496
+ if (relUrl[0] === '/' && relUrl[1] === '/') {
497
+ return parentUrl.slice(0, parentUrl.indexOf(':') + 1) + relUrl;
498
+ }
499
+ // relative-url
500
+ else if ((relUrl[0] === '.' &&
501
+ (relUrl[1] === '/' ||
502
+ (relUrl[1] === '.' && (relUrl[2] === '/' || (relUrl.length === 2 && (relUrl += '/')))) ||
503
+ (relUrl.length === 1 && (relUrl += '/')))) ||
504
+ relUrl[0] === '/') {
505
+ const parentProtocol = parentUrl.slice(0, parentUrl.indexOf(':') + 1);
506
+ let pathname;
507
+ if (parentUrl[parentProtocol.length + 1] === '/') {
508
+ // resolving to a :// so we need to read out the auth and host
509
+ if (parentProtocol !== 'file:') {
510
+ pathname = parentUrl.slice(parentProtocol.length + 2);
511
+ pathname = pathname.slice(pathname.indexOf('/') + 1);
512
+ }
513
+ else {
514
+ pathname = parentUrl.slice(8);
515
+ }
516
+ }
517
+ else {
518
+ // resolving to :/ so pathname is the /... part
519
+ pathname = parentUrl.slice(parentProtocol.length + (parentUrl[parentProtocol.length] === '/' ? 1 : 0));
520
+ }
521
+ if (relUrl[0] === '/')
522
+ return parentUrl.slice(0, parentUrl.length - pathname.length - 1) + relUrl;
523
+ // join together and split for removal of .. and . segments
524
+ // looping the string instead of anything fancy for perf reasons
525
+ // '../../../../../z' resolved to 'x/y' is just 'z'
526
+ const segmented = pathname.slice(0, pathname.lastIndexOf('/') + 1) + relUrl;
527
+ const output = [];
528
+ let segmentIndex = -1;
529
+ for (let i = 0; i < segmented.length; i++) {
530
+ // busy reading a segment - only terminate on '/'
531
+ if (segmentIndex !== -1) {
532
+ if (segmented[i] === '/') {
533
+ output.push(segmented.slice(segmentIndex, i + 1));
534
+ segmentIndex = -1;
535
+ }
536
+ }
537
+ // new segment - check if it is relative
538
+ else if (segmented[i] === '.') {
539
+ // ../ segment
540
+ if (segmented[i + 1] === '.' && (segmented[i + 2] === '/' || i + 2 === segmented.length)) {
541
+ output.pop();
542
+ i += 2;
543
+ }
544
+ // ./ segment
545
+ else if (segmented[i + 1] === '/' || i + 1 === segmented.length) {
546
+ i += 1;
547
+ }
548
+ else {
549
+ // the start of a new segment as below
550
+ segmentIndex = i;
551
+ }
552
+ }
553
+ // it is the start of a new segment
554
+ else {
555
+ segmentIndex = i;
556
+ }
557
+ }
558
+ // finish reading out the last segment
559
+ if (segmentIndex !== -1)
560
+ output.push(segmented.slice(segmentIndex));
561
+ return parentUrl.slice(0, parentUrl.length - pathname.length) + output.join('');
562
+ }
563
+ }
564
+ function resolveUrl(relUrl, parentUrl) {
565
+ const resolvedUrl = resolveIfNotPlainOrUrl(relUrl, parentUrl) ||
566
+ (isUrl(relUrl) ? relUrl : resolveIfNotPlainOrUrl('./' + relUrl, parentUrl));
567
+ return resolvedUrl;
568
+ }
569
+
570
+ function createScript(url) {
571
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
572
+ const script = document.createElement('script');
573
+ script.async = true;
574
+ script.crossOrigin = 'anonymous';
575
+ script.src = url;
576
+ return script;
577
+ }
578
+ let lastWindowError$1, lastWindowErrorUrl;
579
+ function loadModuleDef(url) {
580
+ return new Promise(function (resolve, reject) {
581
+ if (hasDocument) {
582
+ /* eslint-disable lwr/no-unguarded-apis, no-undef */
583
+ const script = createScript(url);
584
+ script.addEventListener('error', () => {
585
+ reject(new LoaderError(FAIL_LOAD, [url]));
586
+ });
587
+ script.addEventListener('load', () => {
588
+ document.head.removeChild(script);
589
+ if (lastWindowErrorUrl === url) {
590
+ reject(lastWindowError$1);
591
+ }
592
+ else {
593
+ resolve();
594
+ }
595
+ });
596
+ document.head.appendChild(script);
597
+ /* eslint-enable lwr/no-unguarded-apis, no-undef */
598
+ }
599
+ });
600
+ }
601
+ if (hasDocument) {
602
+ // When a script is executed, runtime errors are on the global/window scope which are NOT caught by the script's onerror handler.
603
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
604
+ window.addEventListener('error', (evt) => {
605
+ lastWindowErrorUrl = evt.filename;
606
+ lastWindowError$1 = evt.error;
607
+ });
608
+ }
609
+
610
+ // Bootstrap / shim
611
+
612
+ // Loader: modules
613
+ const LOADER_PREFIX = 'lwr.loader.';
614
+ const MODULE_DEFINE = `${LOADER_PREFIX}module.define`;
615
+ const MODULE_FETCH = `${LOADER_PREFIX}module.fetch`;
616
+ const MODULE_ERROR = `${LOADER_PREFIX}module.error`;
617
+
618
+ // Loader: mappings
619
+ const MAPPINGS_FETCH = `${LOADER_PREFIX}mappings.fetch`;
620
+ const MAPPINGS_ERROR = `${LOADER_PREFIX}mappings.error`;
621
+
622
+ /* spec based import map resolver */
623
+ class ImportMetadataResolver {
624
+ constructor(config, invalidationCallback) {
625
+ // Default to empty mappings
626
+ this.importURICache = new Map();
627
+ this.pendingURICache = new Map();
628
+ this.loadMappingHooks = [];
629
+ this.config = config;
630
+ this.invalidationCallback = invalidationCallback;
631
+ }
632
+ addLoadMappingHook(hook) {
633
+ this.loadMappingHooks.push(hook);
634
+ }
635
+ getMappingEndpoint() {
636
+ return this.config.endpoints && this.config.endpoints.uris
637
+ ? this.config.endpoints.uris.mapping
638
+ : undefined;
639
+ }
640
+ getModifiersAsUrlParams() {
641
+ const modifiers = this.config.endpoints ? this.config.endpoints.modifiers : undefined;
642
+ if (!modifiers) {
643
+ // No modifiers return an empty string to append to the URL
644
+ return '';
645
+ }
646
+ else {
647
+ const qs = Object.keys(modifiers)
648
+ .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(modifiers[key])}`)
649
+ .join('&');
650
+ return `?${qs}`;
651
+ }
652
+ }
653
+ buildMappingUrl(specifier) {
654
+ const mappingEndpoint = this.getMappingEndpoint();
655
+ const specifiers = encodeURIComponent(specifier);
656
+ const modifiers = this.getModifiersAsUrlParams();
657
+ return `${mappingEndpoint}${specifiers}${modifiers}`;
658
+ }
659
+ getBaseUrl() {
660
+ return this.config.baseUrl;
661
+ }
662
+ registerImportMappings(newImportMetadata, rootSpecifiers) {
663
+ if (!rootSpecifiers || rootSpecifiers.length === 0) {
664
+ const imports = newImportMetadata ? JSON.stringify(newImportMetadata) : 'undefined';
665
+ throw new LoaderError(BAD_IMPORT_METADATA, [imports, rootSpecifiers ? '[]' : 'undefined']);
666
+ }
667
+ if (!newImportMetadata) {
668
+ throw new LoaderError(BAD_IMPORT_METADATA, ['undefined', JSON.stringify(rootSpecifiers)]);
669
+ }
670
+ if (!newImportMetadata.imports || Object.keys(newImportMetadata.imports).length === 0) {
671
+ throw new LoaderError(BAD_IMPORT_METADATA, [
672
+ JSON.stringify(newImportMetadata),
673
+ JSON.stringify(rootSpecifiers),
674
+ ]);
675
+ }
676
+ const index = newImportMetadata.index || {};
677
+ for (const [uri, specifiers] of Object.entries(newImportMetadata.imports)) {
678
+ specifiers.forEach((specifier) => {
679
+ const indexValue = index[specifier];
680
+ const existing = this.importURICache.get(specifier);
681
+ if (!existing) {
682
+ this.saveImportURIRecord(specifier, uri, indexValue, rootSpecifiers.includes(specifier));
683
+ }
684
+ else {
685
+ const identity = indexValue || uri;
686
+ const existingIdentity = existing.identity || existing.uri;
687
+ if (existingIdentity !== identity) {
688
+ this.invalidationCallback({
689
+ name: specifier,
690
+ oldUrl: existingIdentity,
691
+ newUrl: identity,
692
+ });
693
+ }
694
+ }
695
+ });
696
+ }
697
+ }
698
+ // Get URL from the local cache or return undefiend
699
+ getURI(specifier) {
700
+ return this.importURICache.has(specifier)
701
+ ? resolveUrl(this.importURICache.get(specifier).uri, this.getBaseUrl())
702
+ : undefined;
703
+ }
704
+ resolveLocal(specifier) {
705
+ const uri = this.getURI(specifier);
706
+ if (uri) {
707
+ return uri;
708
+ }
709
+ else if (isUrl(specifier) || specifier.startsWith('/')) {
710
+ return specifier;
711
+ }
712
+ return undefined;
713
+ }
714
+ /**
715
+ * Resolves a the URI for a specified module. It will return the value in this order:
716
+ *
717
+ * 1) Mapping from local URI cache
718
+ * 2) The URI if a specifier is already an absolute URI
719
+ * 3) Mapping fetched from a registered loader hook
720
+ * 4)
721
+ * @param specifier
722
+ * @returns module URI
723
+ */
724
+ async resolve(specifier) {
725
+ let uri = this.getURI(specifier);
726
+ if (uri) {
727
+ return uri;
728
+ }
729
+ else if (isUrl(specifier) || specifier.startsWith('/')) {
730
+ return specifier;
731
+ }
732
+ else {
733
+ const pending = this.pendingURICache.get(specifier);
734
+ if (pending) {
735
+ return pending;
736
+ }
737
+ this.config.profiler.logOperationStart({ id: MAPPINGS_FETCH, specifier });
738
+ const fetchMappingService = this.hasMappingHooks()
739
+ ? this.evaluateMappingHooks
740
+ : this.fetchNewMappings;
741
+ const promise = fetchMappingService
742
+ .bind(this)(specifier)
743
+ .then((importMetadata) => {
744
+ if (!importMetadata || !importMetadata.imports) {
745
+ throw new LoaderError(UNRESOLVED, [specifier]);
746
+ }
747
+ this.registerImportMappings(importMetadata, [specifier]);
748
+ uri = this.getURI(specifier);
749
+ if (!uri) {
750
+ throw new LoaderError(UNRESOLVED, [specifier]);
751
+ }
752
+ this.config.profiler.logOperationEnd({ id: MAPPINGS_FETCH, specifier });
753
+ return uri;
754
+ })
755
+ .finally(() => {
756
+ this.pendingURICache.delete(specifier);
757
+ });
758
+ this.pendingURICache.set(specifier, promise);
759
+ return promise;
760
+ }
761
+ }
762
+ hasMappingHooks() {
763
+ return this.loadMappingHooks.length > 0;
764
+ }
765
+ /**
766
+ * Evaluates mapping hooks. Returns first match. If all hooks return null call the mapping service.
767
+ * @param specifier Request module identifier
768
+ * @returns Import Metadata from the module root
769
+ */
770
+ async evaluateMappingHooks(specifier) {
771
+ // Check with any registered loadMappingHooks
772
+ const loadMappingHooks = this.loadMappingHooks;
773
+ if (loadMappingHooks.length) {
774
+ const knownModules = Array.from(this.importURICache.keys());
775
+ for (let i = 0; i < loadMappingHooks.length; i++) {
776
+ const loadMappingHook = loadMappingHooks[i];
777
+ // eslint-disable-next-line no-await-in-loop
778
+ const response = await loadMappingHook(specifier, { knownModules });
779
+ // undefined (but not null) is considered an un expected response so we will stop processing hooks here and throw an error
780
+ if (response || response === undefined) {
781
+ return response;
782
+ }
783
+ }
784
+ }
785
+ // If we still do not have a match call the mapping service
786
+ return this.fetchNewMappings(specifier);
787
+ }
788
+ async fetchNewMappings(specifier) {
789
+ if (typeof globalThis.fetch !== 'function') {
790
+ throw new LoaderError(UNRESOLVED, [specifier]);
791
+ }
792
+ // TODO For module invalidation with bundles it is recommended we have to send back all loaded root specified
793
+ // to ensure we detect all conflicts.
794
+ const uri = resolveUrl(this.buildMappingUrl(specifier), this.getBaseUrl());
795
+ return globalThis.fetch(uri).then((res) => {
796
+ if (!res.ok) {
797
+ this.config.profiler.logOperationStart({ id: MAPPINGS_ERROR, specifier });
798
+ throw new LoaderError(UNRESOLVED, [specifier]);
799
+ }
800
+ return res
801
+ .json()
802
+ .then((ret) => {
803
+ return ret;
804
+ })
805
+ .catch((err) => {
806
+ throw new LoaderError(UNRESOLVED, [specifier]);
807
+ });
808
+ });
809
+ }
810
+ saveImportURIRecord(specifier, uri, identity, isRoot) {
811
+ if (!identity || uri === identity) {
812
+ this.importURICache.set(specifier, {
813
+ uri,
814
+ isRoot: isRoot,
815
+ });
816
+ }
817
+ else {
818
+ this.importURICache.set(specifier, {
819
+ uri,
820
+ identity,
821
+ isRoot: isRoot,
822
+ });
823
+ }
824
+ }
825
+ }
826
+
827
+ function reportError(error) {
828
+ // TODO eventually this should be configurable instrumentation to send this somewhere
829
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
830
+ if (hasConsole)
831
+ console.error(error);
832
+ }
833
+
834
+ function evaluateHandleStaleModuleHooks(handleStaleModuleHooks, hookArgs) {
835
+ const { name, oldUrl, newUrl } = hookArgs;
836
+ // keep evaluating hooks if return value is null
837
+ for (let i = 0; i < handleStaleModuleHooks.length; i++) {
838
+ const hook = handleStaleModuleHooks[i];
839
+ try {
840
+ const hookResult = hook({ name, oldUrl, newUrl });
841
+ if (hookResult !== null) {
842
+ break;
843
+ }
844
+ }
845
+ catch (e) {
846
+ reportError(new LoaderError(STALE_HOOK_ERROR));
847
+ }
848
+ }
849
+ }
850
+
851
+ const MODULE_LOAD_TIMEOUT_TIMER = 300000;
852
+
853
+ /* global console,process */
854
+ let lastWindowError;
855
+ if (hasDocument) {
856
+ globalThis.addEventListener('error', (evt) => {
857
+ lastWindowError = evt.error;
858
+ });
859
+ }
860
+ if (process.env.NODE_ENV !== 'production') {
861
+ if (!hasSetTimeout && hasConsole) {
862
+ // eslint-disable-next-line lwr/no-unguarded-apis
863
+ console.warn('setTimeout API is not available, watchdog timer on load hook will not be set');
864
+ }
865
+ }
866
+ function isCustomResponse(response) {
867
+ return (Object.prototype.hasOwnProperty.call(response, 'data') &&
868
+ !Object.prototype.hasOwnProperty.call(response, 'blob'));
869
+ }
870
+ function isFetchResponse(response) {
871
+ // if it quacks like a duck...
872
+ return typeof response.blob === 'function';
873
+ }
874
+ function isResponseAPromise(response) {
875
+ return !!(response && response.then);
876
+ }
877
+ async function evaluateLoadHookResponse(response, id) {
878
+ return Promise.resolve().then(async () => {
879
+ if (!response.status) {
880
+ throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
881
+ }
882
+ if (response.status !== 200) {
883
+ throw new LoaderError(HTTP_FAIL_LOAD, [id, `${response.status}`]);
884
+ }
885
+ const isResponse = isFetchResponse(response);
886
+ let code;
887
+ if (isCustomResponse(response)) {
888
+ code = response.data;
889
+ }
890
+ else if (isResponse) {
891
+ // handle fetch response
892
+ code = await response.text();
893
+ }
894
+ else {
895
+ throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
896
+ }
897
+ if (!code) {
898
+ throw new LoaderError(FAIL_LOAD, [id]);
899
+ }
900
+ code = `${code}\n//# sourceURL=${id}`; // append sourceURL for debugging
901
+ try {
902
+ // TODO eval source maps for debugging
903
+ eval(code);
904
+ }
905
+ catch (e) {
906
+ throw new LoaderError(FAIL_LOAD, [id]);
907
+ }
908
+ if (lastWindowError) {
909
+ throw new LoaderError(FAIL_LOAD, [id]);
910
+ }
911
+ return true;
912
+ });
913
+ }
914
+ async function evaluateLoadHook(id, hookPromise) {
915
+ if (!hasSetTimeout) {
916
+ return hookPromise;
917
+ }
918
+ return new Promise((resolve, reject) => {
919
+ // wrap the hook in a watchdog timer
920
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
921
+ const timer = setTimeout(() => {
922
+ reject(new LoaderError(MODULE_LOAD_TIMEOUT, [id]));
923
+ }, MODULE_LOAD_TIMEOUT_TIMER);
924
+ hookPromise
925
+ .then((response) => {
926
+ resolve(response);
927
+ })
928
+ .catch(() => {
929
+ reject(new LoaderError(FAIL_HOOK_LOAD, [id]));
930
+ })
931
+ .finally(() => {
932
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
933
+ clearTimeout(timer);
934
+ });
935
+ });
936
+ }
937
+
938
+ /* global console,process */
939
+ class ModuleRegistry {
940
+ constructor(config) {
941
+ // A registry for named AMD defines containing the *metadata* of AMD module
942
+ this.namedDefineRegistry = new Map();
943
+ // The evaluated module registry where the module identifier (name or URL?) is the key
944
+ this.moduleRegistry = new Map();
945
+ // Aliases of modules in the registry
946
+ this.aliases = new Map();
947
+ this.profiler = config.profiler;
948
+ this.resolver = new ImportMetadataResolver(config, this.importMetadataInvalidationCallback.bind(this));
949
+ }
950
+ async load(id, importer) {
951
+ const resolvedId = await this.resolve(id, importer);
952
+ const moduleRecord = this.getModuleRecord(resolvedId, id);
953
+ if (moduleRecord.evaluated) {
954
+ return moduleRecord.module;
955
+ }
956
+ else {
957
+ if (!moduleRecord.evaluationPromise) {
958
+ moduleRecord.evaluationPromise = this.topLevelEvaluation(moduleRecord);
959
+ }
960
+ return moduleRecord.evaluationPromise;
961
+ }
962
+ }
963
+ async resolve(id, importer) {
964
+ const parentUrl = this.resolver.getBaseUrl(); // only support baseUrl for now
965
+ let resolved;
966
+ let aliasedId = id;
967
+ const resolveHooks = this.resolveHook;
968
+ if (resolveHooks) {
969
+ for (let i = 0; i < resolveHooks.length; i++) {
970
+ const resolveHook = resolveHooks[i];
971
+ const response = resolveHook(aliasedId, { parentUrl });
972
+ let result;
973
+ if (response || response === null) {
974
+ // eslint-disable-next-line no-await-in-loop
975
+ result = isResponseAPromise(response) ? await response : response;
976
+ }
977
+ // if result is not null, attempt resolution
978
+ if (result !== null) {
979
+ if (typeof result === 'string') {
980
+ if (resolveIfNotPlainOrUrl(result, parentUrl)) {
981
+ // string response can't be a URL
982
+ throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
983
+ }
984
+ aliasedId = result; // the next hook will receive the new id
985
+ continue;
986
+ }
987
+ resolved =
988
+ result && result.url && (resolveIfNotPlainOrUrl(result.url, parentUrl) || result.url);
989
+ if (!resolved) {
990
+ throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
991
+ }
992
+ // Don't process any more hooks if we have resolved
993
+ break;
994
+ }
995
+ }
996
+ if (aliasedId !== id) {
997
+ // resolved module id is the aliased module if it has already been defined
998
+ if (!resolved && this.namedDefineRegistry.has(aliasedId)) {
999
+ return aliasedId;
1000
+ }
1001
+ else {
1002
+ id = aliasedId;
1003
+ }
1004
+ }
1005
+ }
1006
+ if (!resolved) {
1007
+ const resolvedOrPlain = resolveIfNotPlainOrUrl(id, parentUrl) || id;
1008
+ // if module registry already has named module the resolved id is the plain id
1009
+ if (this.moduleRegistry.has(resolvedOrPlain)) {
1010
+ return resolvedOrPlain;
1011
+ }
1012
+ const resolvedUrl = this.resolver.resolveLocal(resolvedOrPlain);
1013
+ if (resolvedUrl) {
1014
+ // return the plain id if it is already defined && the resolvedUrl is NOT already in the module registry
1015
+ if (this.namedDefineRegistry.has(resolvedOrPlain) &&
1016
+ this.namedDefineRegistry.get(resolvedOrPlain).defined) {
1017
+ const record = this.moduleRegistry.get(resolvedUrl);
1018
+ if (!record || !this.aliases.has(resolvedOrPlain)) {
1019
+ return resolvedOrPlain;
1020
+ }
1021
+ }
1022
+ return resolvedUrl;
1023
+ }
1024
+ if (this.namedDefineRegistry.has(resolvedOrPlain)) {
1025
+ return resolvedOrPlain;
1026
+ }
1027
+ try {
1028
+ resolved = await this.resolver.resolve(resolvedOrPlain);
1029
+ }
1030
+ catch (e) {
1031
+ // defer to error handling below for unresolved
1032
+ }
1033
+ }
1034
+ if (!resolved || !isUrl(resolved)) {
1035
+ if (this.namedDefineRegistry.has(id)) {
1036
+ return id;
1037
+ }
1038
+ throw new LoaderError(UNRESOLVED, [id]);
1039
+ }
1040
+ if (importer && isUrl(resolved)) {
1041
+ resolved += `?importer=${encodeURIComponent(importer)}`;
1042
+ }
1043
+ return resolved;
1044
+ }
1045
+ has(id) {
1046
+ return this.moduleRegistry.has(id);
1047
+ }
1048
+ define(name, dependencies, exporter) {
1049
+ const mod = this.namedDefineRegistry.get(name);
1050
+ // Don't allow redefining a module.
1051
+ if (mod && mod.defined) {
1052
+ if (process.env.NODE_ENV !== 'production' && hasConsole) {
1053
+ // eslint-disable-next-line lwr/no-unguarded-apis
1054
+ console.warn(`Module redefine attempted: ${name}`);
1055
+ }
1056
+ this.lastDefine = mod;
1057
+ return;
1058
+ }
1059
+ const moduleDef = {
1060
+ name,
1061
+ dependencies,
1062
+ exporter,
1063
+ defined: true,
1064
+ };
1065
+ if (mod && mod.external) {
1066
+ // if module is "external", resolve the external promise to notify any dependees
1067
+ mod.external.resolveExternal(moduleDef);
1068
+ }
1069
+ this.profiler.logOperationStart({ id: MODULE_DEFINE, specifier: name });
1070
+ this.namedDefineRegistry.set(name, moduleDef);
1071
+ this.lastDefine = moduleDef;
1072
+ }
1073
+ /**
1074
+ * Marks modules as "externally" loaded/provided, so that the loader does not attempt to fetch them.
1075
+ *
1076
+ * @param modules - list of module identifiers
1077
+ */
1078
+ registerExternalModules(modules) {
1079
+ modules.map((id) => {
1080
+ if (!this.namedDefineRegistry.has(id)) {
1081
+ let resolveExternal;
1082
+ let timer;
1083
+ const moduleDefPromise = new Promise((resolve, reject) => {
1084
+ resolveExternal = resolve;
1085
+ // watch the external for timeout
1086
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
1087
+ timer = setTimeout(() => {
1088
+ reject(new LoaderError(MODULE_LOAD_TIMEOUT, [id]));
1089
+ }, MODULE_LOAD_TIMEOUT_TIMER);
1090
+ }).finally(() => {
1091
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
1092
+ clearTimeout(timer);
1093
+ });
1094
+ const moduleDef = {
1095
+ name: id,
1096
+ defined: false,
1097
+ external: {
1098
+ resolveExternal,
1099
+ moduleDefPromise,
1100
+ },
1101
+ };
1102
+ this.namedDefineRegistry.set(id, moduleDef);
1103
+ }
1104
+ else if (process.env.NODE_ENV !== 'production' && hasConsole) {
1105
+ // eslint-disable-next-line lwr/no-unguarded-apis
1106
+ console.warn(MODULE_ALREADY_LOADED.message, id);
1107
+ }
1108
+ });
1109
+ }
1110
+ getImportMetadataResolver() {
1111
+ return this.resolver;
1112
+ }
1113
+ // Returns an existing module record by the resolvedId or aliased id
1114
+ getExistingModuleRecord(resolvedId, aliasId) {
1115
+ const moduleRecord = this.moduleRegistry.get(resolvedId);
1116
+ if (moduleRecord) {
1117
+ this.storeModuleAlias(aliasId, resolvedId);
1118
+ return moduleRecord;
1119
+ }
1120
+ // Check if this is a known alias
1121
+ if (resolvedId !== aliasId) {
1122
+ const alias = this.aliases.get(aliasId);
1123
+ if (alias) {
1124
+ const aliasedModule = this.moduleRegistry.get(alias);
1125
+ if (aliasedModule) {
1126
+ return aliasedModule;
1127
+ }
1128
+ }
1129
+ }
1130
+ return moduleRecord;
1131
+ }
1132
+ getModuleRecord(resolvedId, id) {
1133
+ // Look for an existing record
1134
+ const existingRecord = this.getExistingModuleRecord(resolvedId, id);
1135
+ if (existingRecord) {
1136
+ // return existing
1137
+ return existingRecord;
1138
+ }
1139
+ // Create a new Module Record
1140
+ const instantiation = this.getModuleDef(resolvedId, id);
1141
+ const dependencyRecords = instantiation.then((moduleDef) => {
1142
+ const dependencies = moduleDef.dependencies;
1143
+ // get dep and filter out exports
1144
+ const filtered = dependencies
1145
+ .map((dep) => {
1146
+ if (dep === 'exports') {
1147
+ return;
1148
+ }
1149
+ invariant(dep !== 'require', NO_AMD_REQUIRE);
1150
+ return this.getModuleDependencyRecord.call(this, dep);
1151
+ })
1152
+ .filter((depRecord) => depRecord !== undefined);
1153
+ return Promise.all(filtered);
1154
+ });
1155
+ const newModuleRecord = {
1156
+ id: resolvedId,
1157
+ module: Object.create(null),
1158
+ dependencyRecords,
1159
+ instantiation,
1160
+ evaluated: false,
1161
+ evaluationPromise: null,
1162
+ };
1163
+ this.moduleRegistry.set(resolvedId, newModuleRecord);
1164
+ this.storeModuleAlias(id, resolvedId);
1165
+ return newModuleRecord;
1166
+ }
1167
+ storeModuleAlias(aliasId, resolvedId) {
1168
+ if (aliasId !== resolvedId) {
1169
+ if (!this.aliases.has(aliasId)) {
1170
+ this.aliases.set(aliasId, resolvedId);
1171
+ }
1172
+ else if (process.env.NODE_ENV !== 'production' && hasConsole) {
1173
+ // Warn the user if they were not aliasing to the resolvedId
1174
+ const currentResolvedId = this.aliases.get(aliasId);
1175
+ if (currentResolvedId !== resolvedId) {
1176
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
1177
+ console.warn(`Alias update attempt: ${aliasId}=>${currentResolvedId}, ${resolvedId}`);
1178
+ }
1179
+ }
1180
+ }
1181
+ }
1182
+ async getModuleDependencyRecord(dependency) {
1183
+ const resolvedDepId = await this.resolve(dependency);
1184
+ return this.getModuleRecord(resolvedDepId, dependency);
1185
+ }
1186
+ // execute the "top-level code" (the code outside of functions) of a module
1187
+ async topLevelEvaluation(moduleRecord) {
1188
+ await this.instantiateAll(moduleRecord, {});
1189
+ return this.evaluateModule(moduleRecord, {});
1190
+ }
1191
+ // Returns a promise when a module and all of it's dependencies have finished instantiation
1192
+ async instantiateAll(moduleRecord, instantiatedMap) {
1193
+ if (!instantiatedMap[moduleRecord.id]) {
1194
+ instantiatedMap[moduleRecord.id] = true;
1195
+ const dependencyModuleRecords = await moduleRecord.dependencyRecords;
1196
+ if (dependencyModuleRecords) {
1197
+ for (let i = 0; i < dependencyModuleRecords.length; i++) {
1198
+ const depRecord = dependencyModuleRecords[i];
1199
+ // eslint-disable-next-line no-await-in-loop
1200
+ await this.instantiateAll(depRecord, instantiatedMap);
1201
+ }
1202
+ }
1203
+ }
1204
+ }
1205
+ async evaluateModule(moduleRecord, evaluationMap) {
1206
+ const dependencyModuleRecords = await moduleRecord.dependencyRecords;
1207
+ if (dependencyModuleRecords.length > 0) {
1208
+ evaluationMap[moduleRecord.id] = true;
1209
+ // evaluate dependencies first
1210
+ await this.evaluateModuleDependencies(dependencyModuleRecords, evaluationMap);
1211
+ }
1212
+ const { exporter, dependencies } = await moduleRecord.instantiation;
1213
+ // The exports object automatically gets filled in by the exporter evaluation
1214
+ const exports = {};
1215
+ const depsMapped = await Promise.all(dependencies.map(async (dep) => {
1216
+ if (dep === 'exports') {
1217
+ return exports;
1218
+ }
1219
+ const resolvedDepId = await this.resolve(dep);
1220
+ const moduleRecord = this.moduleRegistry.get(resolvedDepId);
1221
+ if (!moduleRecord) {
1222
+ throw new LoaderError(FAILED_DEP, [resolvedDepId]);
1223
+ }
1224
+ const module = moduleRecord.module;
1225
+ /**
1226
+ * Circular dependencies are handled properly when named exports are used,
1227
+ * however, for default exports there is a bug: https://github.com/rollup/rollup/issues/3384
1228
+ *
1229
+ * The workaround below applies for circular dependencies (!moduleRecord.evaluated)
1230
+ */
1231
+ if (!moduleRecord.evaluated) {
1232
+ return this.getCircularDependencyWrapper(module);
1233
+ }
1234
+ if (module) {
1235
+ return module.__defaultInterop ? module.default : module;
1236
+ }
1237
+ throw new LoaderError(FAILED_DEP, [resolvedDepId]);
1238
+ }));
1239
+ // 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
1240
+ if (moduleRecord.evaluated) {
1241
+ return moduleRecord.module;
1242
+ }
1243
+ // evaluates the module function
1244
+ let moduleDefault = exporter(...depsMapped);
1245
+ // value is returned from exporter, then we are not using named exports
1246
+ if (moduleDefault !== undefined) {
1247
+ moduleDefault = { default: moduleDefault };
1248
+ // __defaultInterop is ONLY used to support backwards compatibility
1249
+ // of importing default exports the "wrong" way (when not using named exports).
1250
+ // See https://github.com/salesforce-experience-platform-emu/lwr/pull/816
1251
+ Object.defineProperty(moduleDefault, '__defaultInterop', { value: true });
1252
+ }
1253
+ // if no return value, then we are using the exports object
1254
+ else {
1255
+ // handle only default export with Rollup forced named exports
1256
+ if (this.isNamedExportDefaultOnly(exports)) {
1257
+ Object.defineProperty(exports, '__useDefault', { value: true });
1258
+ }
1259
+ }
1260
+ const moduleExports = moduleDefault || exports;
1261
+ // update the module record
1262
+ // copy over enumerable public methods to module
1263
+ for (const key in moduleExports) {
1264
+ Object.defineProperty(moduleRecord.module, key, {
1265
+ enumerable: true,
1266
+ set(value) {
1267
+ moduleExports[key] = value;
1268
+ },
1269
+ get() {
1270
+ return moduleExports[key];
1271
+ },
1272
+ });
1273
+ }
1274
+ // copy non-enumerable to module
1275
+ if (moduleExports.__useDefault) {
1276
+ Object.defineProperty(moduleRecord.module, '__useDefault', { value: true });
1277
+ }
1278
+ if (moduleExports.__defaultInterop) {
1279
+ Object.defineProperty(moduleRecord.module, '__defaultInterop', { value: true });
1280
+ }
1281
+ if (moduleExports.__esModule) {
1282
+ Object.defineProperty(moduleRecord.module, '__esModule', { value: true });
1283
+ }
1284
+ moduleRecord.evaluated = true;
1285
+ Object.freeze(moduleRecord.module);
1286
+ return moduleRecord.module;
1287
+ }
1288
+ // Determines if named exports module has only default export
1289
+ isNamedExportDefaultOnly(exports) {
1290
+ return (exports !== undefined &&
1291
+ Object.getOwnPropertyNames(exports).length === 2 &&
1292
+ Object.prototype.hasOwnProperty.call(exports, 'default') &&
1293
+ Object.prototype.hasOwnProperty.call(exports, '__esModule'));
1294
+ }
1295
+ // Wrap the dependency in a function that can be called and detected by __circular__ property.
1296
+ // The LWC engine checks for __circular__ to detect circular dependencies.
1297
+ getCircularDependencyWrapper(module) {
1298
+ const tmp = () => {
1299
+ return module.__useDefault || module.__defaultInterop ? module.default : module;
1300
+ };
1301
+ tmp.__circular__ = true;
1302
+ return tmp;
1303
+ }
1304
+ async evaluateModuleDependencies(dependencyModuleRecords, evaluationMap) {
1305
+ for (let i = 0; i < dependencyModuleRecords.length; i++) {
1306
+ const depRecord = dependencyModuleRecords[i];
1307
+ if (!depRecord.evaluated && !evaluationMap[depRecord.id]) {
1308
+ evaluationMap[depRecord.id] = true;
1309
+ // eslint-disable-next-line no-await-in-loop
1310
+ await this.evaluateModule(depRecord, evaluationMap);
1311
+ }
1312
+ }
1313
+ }
1314
+ async getModuleDef(resolvedId, originalId) {
1315
+ // reset lastDefine
1316
+ this.lastDefine = undefined;
1317
+ // the module name can be the resolved ID or the original ID if neither are URL's.
1318
+ const moduleName = !isUrl(resolvedId)
1319
+ ? resolvedId
1320
+ : originalId !== resolvedId
1321
+ ? originalId
1322
+ : undefined;
1323
+ let moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
1324
+ if (moduleDef && moduleDef.external) {
1325
+ return moduleDef.external.moduleDefPromise;
1326
+ }
1327
+ if (moduleDef && moduleDef.defined) {
1328
+ return moduleDef;
1329
+ }
1330
+ const parentUrl = this.resolver.getBaseUrl(); // only support baseUrl for now
1331
+ const specifier = moduleName || originalId;
1332
+ this.profiler.logOperationStart({ id: MODULE_FETCH, specifier });
1333
+ return Promise.resolve()
1334
+ .then(async () => {
1335
+ const loadHooks = this.loadHook;
1336
+ if (loadHooks) {
1337
+ for (let i = 0; i < loadHooks.length; i++) {
1338
+ const loadHook = loadHooks[i];
1339
+ const response = loadHook(resolvedId, parentUrl);
1340
+ const result = (isResponseAPromise(response)
1341
+ ? // eslint-disable-next-line no-await-in-loop
1342
+ await evaluateLoadHook(resolvedId, response)
1343
+ : response);
1344
+ if (result === undefined) {
1345
+ throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
1346
+ }
1347
+ if (result && result !== null) {
1348
+ return evaluateLoadHookResponse(result, resolvedId);
1349
+ }
1350
+ }
1351
+ }
1352
+ return false;
1353
+ })
1354
+ .then((result) => {
1355
+ if (result !== true && hasDocument) {
1356
+ return loadModuleDef(resolvedId);
1357
+ }
1358
+ })
1359
+ .then(() => {
1360
+ // Attempt to retrieve the module definition by name first
1361
+ moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
1362
+ // Fallback to the last loader.define call
1363
+ if (!moduleDef) {
1364
+ moduleDef = this.lastDefine;
1365
+ }
1366
+ // This should not happen
1367
+ if (!moduleDef) {
1368
+ throw new LoaderError(FAIL_INSTANTIATE, [resolvedId]);
1369
+ }
1370
+ this.profiler.logOperationEnd({ id: MODULE_FETCH, specifier });
1371
+ return moduleDef;
1372
+ })
1373
+ .catch((e) => {
1374
+ this.profiler.logOperationStart({ id: MODULE_ERROR, specifier });
1375
+ throw e;
1376
+ });
1377
+ }
1378
+ addLoaderPlugin(hooks) {
1379
+ if (typeof hooks !== 'object') {
1380
+ throw new LoaderError(INVALID_HOOK);
1381
+ }
1382
+ const { loadModule: loadHook, resolveModule: resolveHook, loadMapping } = hooks;
1383
+ if (resolveHook) {
1384
+ if (this.resolveHook) {
1385
+ this.resolveHook.push(resolveHook);
1386
+ }
1387
+ else {
1388
+ this.resolveHook = [resolveHook];
1389
+ }
1390
+ }
1391
+ if (loadHook) {
1392
+ if (this.loadHook) {
1393
+ this.loadHook.push(loadHook);
1394
+ }
1395
+ else {
1396
+ this.loadHook = [loadHook];
1397
+ }
1398
+ }
1399
+ if (loadMapping) {
1400
+ this.resolver.addLoadMappingHook(loadMapping);
1401
+ }
1402
+ }
1403
+ importMetadataInvalidationCallback({ name, oldUrl, newUrl }) {
1404
+ const handleStaleModuleHooks = this.handleStaleModuleHook;
1405
+ if (handleStaleModuleHooks) {
1406
+ evaluateHandleStaleModuleHooks(handleStaleModuleHooks, {
1407
+ name,
1408
+ oldUrl,
1409
+ newUrl,
1410
+ });
1411
+ }
1412
+ else {
1413
+ if (process.env.NODE_ENV !== 'production' && hasConsole) {
1414
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
1415
+ console.warn(`stale module detected ${name}, current URL:${oldUrl}, new URL:${newUrl}`);
1416
+ }
1417
+ }
1418
+ }
1419
+ registerHandleStaleModuleHook(handleStaleModule) {
1420
+ if (this.handleStaleModuleHook) {
1421
+ this.handleStaleModuleHook.push(handleStaleModule);
1422
+ }
1423
+ else {
1424
+ this.handleStaleModuleHook = [handleStaleModule];
1425
+ }
1426
+ }
1427
+ }
1428
+
1429
+ /**
1430
+ * The LWR loader is inspired and borrows from the algorithms and native browser principles of https://github.com/systemjs/systemjs
1431
+ */
1432
+ class Loader {
1433
+ constructor(config) {
1434
+ let baseUrl = config.baseUrl;
1435
+ const mappingEndpoint = config.endpoints ? config.endpoints.uris.mapping : undefined;
1436
+ let profiler = config.profiler;
1437
+ if (!mappingEndpoint) {
1438
+ throw new LoaderError(NO_MAPPING_URL);
1439
+ }
1440
+ // add a trailing slash, if it does not exist
1441
+ config.endpoints.uris.mapping = mappingEndpoint.replace(/\/?$/, '/');
1442
+ if (baseUrl) {
1443
+ // add a trailing slash, if it does not exist
1444
+ baseUrl = baseUrl.replace(/\/?$/, '/');
1445
+ }
1446
+ if (!baseUrl) {
1447
+ baseUrl = getBaseUrl();
1448
+ }
1449
+ if (!baseUrl) {
1450
+ throw new LoaderError(NO_BASE_URL);
1451
+ }
1452
+ if (!profiler) {
1453
+ // default noop profiler
1454
+ profiler = {
1455
+ logOperationStart: () => {
1456
+ /* noop */
1457
+ },
1458
+ logOperationEnd: () => {
1459
+ /* noop */
1460
+ },
1461
+ };
1462
+ }
1463
+ this.registry = new ModuleRegistry(Object.freeze({ endpoints: config.endpoints, baseUrl, profiler }));
1464
+ // TODO: W-10539691 - temp workaround for LWR-Java -- remove once appId is implemented there
1465
+ if (config.appMetadata && !config.appMetadata.appId) {
1466
+ // Parse the appId from the bootstrapModule
1467
+ // LWR-Java bootstrap module format: @lwr-bootstrap/my/app/v/0_0_1 -- my/app is the appId
1468
+ const match = config.appMetadata.bootstrapModule.match(/@lwr-bootstrap\/(.+)\/v\/.+/);
1469
+ const appId = match && match[1];
1470
+ config.appMetadata.appId = appId;
1471
+ }
1472
+ // TODO: https://github.com/salesforce-experience-platform-emu/lwr/issues/1087
1473
+ this.services = Object.freeze({
1474
+ addLoaderPlugin: this.registry.addLoaderPlugin.bind(this.registry),
1475
+ handleStaleModule: this.registry.registerHandleStaleModuleHook.bind(this.registry),
1476
+ appMetadata: config.appMetadata,
1477
+ });
1478
+ }
1479
+ /**
1480
+ * Defines/registers a single named AMD module definition.
1481
+ *
1482
+ * @param {string} name The module name
1483
+ * @param {string[]} dependencies A list of module dependencies (module imports)
1484
+ * @param {Function} execute The function containing the module code. AKA exporter as it also returns the modules exports when executed
1485
+ * @return {void}
1486
+ */
1487
+ define(name, dependencies, execute) {
1488
+ invariant(typeof name === 'string', MISSING_NAME);
1489
+ let ctor = execute;
1490
+ let deps = dependencies;
1491
+ // Convert no dependencies form `define('name', function(){}, {});` to: `define('name', [], function(){}, {})`
1492
+ if (typeof deps === 'function') {
1493
+ ctor = dependencies;
1494
+ deps = [];
1495
+ }
1496
+ invariant(Array.isArray(deps), INVALID_DEPS);
1497
+ this.registry.define(name, deps, ctor);
1498
+ }
1499
+ /**
1500
+ * Retrieves/loads a module, returning it from the registry if it exists and fetching it if it doesn't.
1501
+ *
1502
+ * @param {string} id - A module identifier or URL
1503
+ * @param {string} importer - The versioned specifier of the module importer
1504
+ * Used when the ID is not versioned (eg: variable dynamic imports)
1505
+ * @return {Promise<Module>}
1506
+ */
1507
+ async load(id, importer) {
1508
+ return this.registry.load(id, importer);
1509
+ }
1510
+ /**
1511
+ * 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).
1512
+ *
1513
+ * @param {string} id - A module identifier or URL
1514
+ * @return {boolean}
1515
+ */
1516
+ has(id) {
1517
+ return this.registry.has(id);
1518
+ }
1519
+ /**
1520
+ * Resolves the module identifier or URL. Returns the module identifier if the moduleDefinition exists, or the full resolved URL if a URL is given.
1521
+ *
1522
+ * @param {string} id - A module identifier or URL
1523
+ * @param {string} importer - The versioned specifier of the module importer
1524
+ * Used when the ID is not versioned (eg: variable dynamic imports)
1525
+ * @return {string}
1526
+ */
1527
+ async resolve(id, importer) {
1528
+ return this.registry.resolve(id, importer);
1529
+ }
1530
+ async registerImportMappings(mappings, rootSpecifiers) {
1531
+ this.registry.getImportMetadataResolver().registerImportMappings(mappings, rootSpecifiers);
1532
+ }
1533
+ /**
1534
+ * Marks modules as "externally" loaded/provided (e.g. preloaded), so that the loader does not attempt to load them.
1535
+ *
1536
+ * @param modules - list of module identifiers
1537
+ */
1538
+ registerExternalModules(modules) {
1539
+ this.registry.registerExternalModules(modules);
1540
+ }
1541
+ }
1542
+
1543
+ exports.Loader = Loader;
1544
+
1545
+ Object.defineProperty(exports, '__esModule', { value: true });
1546
+
1547
+ });