@lwrjs/loader 0.6.0-alpha.9 → 0.6.2
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-loader-shim-legacy.bundle.js +326 -218
- package/build/assets/prod/lwr-loader-shim-legacy.bundle.min.js +2 -2
- package/build/assets/prod/lwr-loader-shim-legacy.js +289 -213
- package/build/assets/prod/lwr-loader-shim.bundle.js +324 -258
- package/build/assets/prod/lwr-loader-shim.bundle.min.js +2 -2
- package/build/assets/prod/lwr-loader-shim.js +289 -246
- package/build/bundle/prod/lwr/esmLoader/esmLoader.js +1 -1
- package/build/cjs/modules/lwr/esmLoader/esmLoader.cjs +9 -6
- package/build/cjs/modules/lwr/esmLoader/importResolver.cjs +24 -3
- package/build/cjs/modules/lwr/loader/constants/constants.cjs +0 -10
- package/build/cjs/modules/lwr/loader/moduleRegistry/importMetadataResolver.cjs +4 -3
- package/build/cjs/modules/lwr/loader/moduleRegistry/moduleRegistry.cjs +8 -3
- package/build/cjs/modules/lwr/loaderLegacy/moduleRegistry/moduleRegistry.cjs +12 -2
- package/build/modules/lwr/esmLoader/esmLoader.js +38 -10
- package/build/modules/lwr/loader/loader.js +35 -12
- package/build/modules/lwr/loaderLegacy/loaderLegacy.js +37 -5
- package/package.json +12 -7
|
@@ -4,265 +4,308 @@
|
|
|
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 Module Loader Shim v0.6.
|
|
7
|
+
/* LWR Module Loader Shim v0.6.2 */
|
|
8
8
|
(function () {
|
|
9
|
-
|
|
9
|
+
'use strict';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
// Create a Loader instance
|
|
16
|
-
const exports = {};
|
|
17
|
-
definition[2].call(null, exports);
|
|
18
|
-
const { Loader } = exports;
|
|
19
|
-
const loader = new Loader(config);
|
|
20
|
-
if (externalModules && externalModules.length) {
|
|
21
|
-
loader.registerExternalModules(externalModules);
|
|
22
|
-
}
|
|
23
|
-
// Define the loader module with public API: { define, load, services }
|
|
24
|
-
const exporter = (exports) => {
|
|
25
|
-
Object.assign(exports, {
|
|
26
|
-
define: loader.define.bind(loader),
|
|
27
|
-
load: loader.load.bind(loader),
|
|
28
|
-
services: loader.services,
|
|
29
|
-
});
|
|
30
|
-
return;
|
|
31
|
-
};
|
|
32
|
-
loader.define(name, ['exports'], exporter);
|
|
33
|
-
return loader;
|
|
34
|
-
}
|
|
11
|
+
// Bootstrap / shim
|
|
12
|
+
const BOOTSTRAP_PREFIX = 'lwr.bootstrap.';
|
|
13
|
+
const BOOTSTRAP_ERROR = `${BOOTSTRAP_PREFIX}error`;
|
|
35
14
|
|
|
36
|
-
|
|
37
|
-
const METRIC_END = 'lwr.bootstrap.end';
|
|
38
|
-
const METRIC_ERROR = 'lwr.bootstrap.error';
|
|
15
|
+
var Phase;
|
|
39
16
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// Attach a custom dispatcher
|
|
45
|
-
let customDispatcher;
|
|
46
|
-
function attachDispatcher(dispatcher) {
|
|
47
|
-
customDispatcher = dispatcher;
|
|
48
|
-
}
|
|
49
|
-
// Check if the Performance API is available
|
|
50
|
-
// e.g. JSDom (used in Jest) doesn't implement these
|
|
51
|
-
const isPerfSupported = typeof globalThis.performance !== 'undefined' && typeof globalThis.performance.mark === 'function';
|
|
52
|
-
// For marking request metrics
|
|
53
|
-
// Fallback to the Performance API if there is no custom dispatcher
|
|
54
|
-
function logOperationStart({ id, specifier }) {
|
|
55
|
-
if (customDispatcher) {
|
|
56
|
-
customDispatcher({ id, phase: Phase.Start, specifier });
|
|
57
|
-
}
|
|
58
|
-
else if (isPerfSupported) {
|
|
59
|
-
globalThis.performance.mark(id + (specifier ? `.${specifier}` : ''));
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
function getProfilerAPI() {
|
|
63
|
-
// Create the public Profiler API
|
|
64
|
-
return { logOperationStart: logOperationStart.bind(this) };
|
|
65
|
-
}
|
|
17
|
+
(function (Phase) {
|
|
18
|
+
Phase[Phase["Start"] = 0] = "Start";
|
|
19
|
+
Phase[Phase["End"] = 1] = "End";
|
|
20
|
+
})(Phase || (Phase = {}));
|
|
66
21
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// If autoBoot === true, there must NOT be a customInit hook
|
|
74
|
-
if (autoBoot && customInit) {
|
|
75
|
-
throw new Error('The customInit hook must not be defined when autoBoot is true');
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
// Process the customInit hook
|
|
79
|
-
function customInit(config, initializeApp, define, onBootstrapError) {
|
|
80
|
-
// Validate config
|
|
81
|
-
const { autoBoot, customInit } = config;
|
|
82
|
-
validatePreInit(autoBoot, customInit);
|
|
83
|
-
// Set up arguments and call the customInit hook, if available
|
|
84
|
-
if (customInit) {
|
|
85
|
-
const lwr = {
|
|
86
|
-
initializeApp,
|
|
87
|
-
define,
|
|
88
|
-
onBootstrapError,
|
|
89
|
-
attachDispatcher,
|
|
90
|
-
};
|
|
91
|
-
customInit(lwr, config);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
22
|
+
// Attach a custom dispatcher
|
|
23
|
+
let customDispatcher;
|
|
24
|
+
function attachDispatcher(dispatcher) {
|
|
25
|
+
customDispatcher = dispatcher;
|
|
26
|
+
} // Check if the Performance API is available
|
|
27
|
+
// e.g. JSDom (used in Jest) doesn't implement these
|
|
94
28
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const tempDefine = this.tempDefine.bind(this);
|
|
112
|
-
global.LWR.define = tempDefine;
|
|
113
|
-
this.bootReady = this.config.autoBoot;
|
|
114
|
-
// Start watchdog timer
|
|
115
|
-
if (hasSetTimeout) {
|
|
116
|
-
this.watchdogTimerId = this.startWatchdogTimer();
|
|
117
|
-
}
|
|
118
|
-
try {
|
|
119
|
-
customInit(Object.freeze(this.config), this.postCustomInit.bind(this), tempDefine, (e) => {
|
|
120
|
-
this.errorHandler = e;
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
catch (e) {
|
|
124
|
-
this.enterErrorState(e);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// Return true if the app can be initialized
|
|
128
|
-
canInit() {
|
|
129
|
-
// Initialize the app if:
|
|
130
|
-
// - bootReady: autoBoot is on OR customInit has finished
|
|
131
|
-
// - all required modules are defined
|
|
132
|
-
const allDefined = this.config.requiredModules.every((m) => this.orderedDefs.includes(m));
|
|
133
|
-
return this.bootReady && allDefined;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Create a temporary LWR.define() function which captures all
|
|
137
|
-
* calls that occur BEFORE the full loader module is available
|
|
138
|
-
*
|
|
139
|
-
* Each call to LWR.define() is stored in 2 ways:
|
|
140
|
-
* - in a map as [moduleName, arguments] pairs
|
|
141
|
-
* - each moduleName is pushed onto an array, to preserve
|
|
142
|
-
* the order in which the modules were defined
|
|
143
|
-
*/
|
|
144
|
-
tempDefine(...args) {
|
|
145
|
-
// Cache the incoming module
|
|
146
|
-
const moduleName = args[0];
|
|
147
|
-
this.defineCache[moduleName] = args;
|
|
148
|
-
this.orderedDefs.push(moduleName);
|
|
149
|
-
if (this.canInit()) {
|
|
150
|
-
if (hasSetTimeout) {
|
|
151
|
-
// requiredModules are defined, clear watchdog timer
|
|
152
|
-
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
153
|
-
clearTimeout(this.watchdogTimerId);
|
|
154
|
-
}
|
|
155
|
-
this.initApp();
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
// Called by the customInit hook via lwr.initializeApp()
|
|
159
|
-
postCustomInit() {
|
|
160
|
-
this.bootReady = true;
|
|
161
|
-
if (this.canInit()) {
|
|
162
|
-
this.initApp();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
// Create the loader and initialize the application
|
|
166
|
-
initApp() {
|
|
167
|
-
try {
|
|
168
|
-
const loaderConfig = {
|
|
169
|
-
endpoints: this.config.endpoints,
|
|
170
|
-
baseUrl: this.config.baseUrl,
|
|
171
|
-
profiler: this.profiler,
|
|
172
|
-
};
|
|
173
|
-
const loader = createLoader(this.loaderModule, this.defineCache[this.loaderModule], loaderConfig, this.config.preloadModules);
|
|
174
|
-
this.mountApp(loader);
|
|
175
|
-
}
|
|
176
|
-
catch (e) {
|
|
177
|
-
this.enterErrorState(e);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
waitForDOMContentLoaded() {
|
|
181
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
182
|
-
if (typeof document === undefined) {
|
|
183
|
-
return Promise.resolve();
|
|
184
|
-
}
|
|
185
|
-
// Resolve if document is already "ready" https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
|
|
186
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
187
|
-
if (document.readyState === 'interactive' || document.readyState === 'complete') {
|
|
188
|
-
return Promise.resolve();
|
|
189
|
-
}
|
|
190
|
-
return new Promise((resolve) => {
|
|
191
|
-
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
192
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
193
|
-
resolve();
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
// Set up the application globals, import map, root custom element...
|
|
198
|
-
mountApp(loader) {
|
|
199
|
-
const { bootstrapModule, rootComponent, rootComponents, endpoints, imports, index } = this.config;
|
|
200
|
-
// Set global LWR.define to loader.define
|
|
201
|
-
this.global.LWR = Object.freeze({
|
|
202
|
-
define: loader.define.bind(loader),
|
|
203
|
-
rootComponent,
|
|
204
|
-
rootComponents,
|
|
205
|
-
endpoints,
|
|
206
|
-
imports: imports || {},
|
|
207
|
-
index: index || {},
|
|
208
|
-
});
|
|
209
|
-
// Redefine all modules in the temporary cache
|
|
210
|
-
this.orderedDefs.forEach((specifier) => {
|
|
211
|
-
if (specifier !== this.loaderModule) {
|
|
212
|
-
loader.define(...this.defineCache[specifier]);
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
// by default, app initialization is gated on waiting for document to be parsed (via DOMContentLoaded)
|
|
216
|
-
const { disableInitDefer } = this.config;
|
|
217
|
-
// Load the import mappings and application bootstrap module
|
|
218
|
-
loader
|
|
219
|
-
.registerImportMappings({ imports, index }, [bootstrapModule, rootComponent])
|
|
220
|
-
.then(() => {
|
|
221
|
-
if (!disableInitDefer) {
|
|
222
|
-
return this.waitForDOMContentLoaded();
|
|
223
|
-
}
|
|
224
|
-
})
|
|
225
|
-
.then(() => loader.load(bootstrapModule))
|
|
226
|
-
.then(() => {
|
|
227
|
-
this.profiler.logOperationStart({ id: METRIC_END });
|
|
228
|
-
})
|
|
229
|
-
.catch((reason) => {
|
|
230
|
-
this.enterErrorState(new Error(`Application ${rootComponent} could not be loaded: ${reason}`));
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
// Trigger bootstrap error state, and call error handler if registered
|
|
234
|
-
enterErrorState(error) {
|
|
235
|
-
this.profiler.logOperationStart({ id: METRIC_ERROR });
|
|
236
|
-
if (this.errorHandler) {
|
|
237
|
-
this.errorHandler(error);
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
if (hasConsole) {
|
|
241
|
-
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
242
|
-
console.error(`An error occurred during LWR bootstrap. ${error.message}`, error.stack);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
// eslint-disable-next-line no-undef, lwr/no-unguarded-apis
|
|
247
|
-
startWatchdogTimer() {
|
|
248
|
-
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
249
|
-
return setTimeout(() => {
|
|
250
|
-
this.enterErrorState(new Error('Failed to load required modules - timed out'));
|
|
251
|
-
}, REQUIRED_MODULES_TIMEOUT);
|
|
252
|
-
}
|
|
29
|
+
const perf = globalThis.performance;
|
|
30
|
+
const isPerfSupported = typeof perf !== 'undefined' && typeof perf.mark === 'function' && typeof perf.clearMarks === 'function' && typeof perf.measure === 'function' && typeof perf.clearMeasures === 'function'; // For marking request metrics
|
|
31
|
+
// Fallback to the Performance API if there is no custom dispatcher
|
|
32
|
+
|
|
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}` : ''));
|
|
253
45
|
}
|
|
46
|
+
} // For measuring duration metrics
|
|
47
|
+
// Fallback to the Performance API if there is no custom dispatcher
|
|
254
48
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
49
|
+
/* istanbul ignore next */
|
|
50
|
+
|
|
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); // Clear the created mark and measure to avoid filling the performance entry buffer
|
|
66
|
+
// Even if they get deleted, existing PerformanceObservers preserve copies of the entries
|
|
67
|
+
|
|
68
|
+
perf.clearMarks(markName);
|
|
69
|
+
perf.clearMeasures(measureName);
|
|
260
70
|
}
|
|
261
|
-
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function createLoader(name, definition, config, externalModules) {
|
|
74
|
+
if (!definition || typeof definition[2] !== 'function') {
|
|
75
|
+
throw new Error(`Expected loader with specifier "${name}" to be a module`);
|
|
76
|
+
}
|
|
77
|
+
// Create a Loader instance
|
|
78
|
+
const exports = {};
|
|
79
|
+
definition[2].call(null, exports);
|
|
80
|
+
const { Loader } = exports;
|
|
81
|
+
const loader = new Loader(config);
|
|
82
|
+
if (externalModules && externalModules.length) {
|
|
83
|
+
loader.registerExternalModules(externalModules);
|
|
84
|
+
}
|
|
85
|
+
// Define the loader module with public API: { define, load, services }
|
|
86
|
+
const exporter = (exports) => {
|
|
87
|
+
Object.assign(exports, {
|
|
88
|
+
define: loader.define.bind(loader),
|
|
89
|
+
load: loader.load.bind(loader),
|
|
90
|
+
services: loader.services,
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
loader.define(name, ['exports'], exporter);
|
|
94
|
+
return loader;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const REQUIRED_MODULES_TIMEOUT = 300 * 1000;
|
|
98
|
+
|
|
99
|
+
// Check for errors with autoBoot and customInit
|
|
100
|
+
function validatePreInit(autoBoot, customInit) {
|
|
101
|
+
// If autoBoot === false, there must be a customInit hook
|
|
102
|
+
if (!autoBoot && !customInit) {
|
|
103
|
+
throw new Error('The customInit hook is required when autoBoot is false');
|
|
104
|
+
}
|
|
105
|
+
// If autoBoot === true, there must NOT be a customInit hook
|
|
106
|
+
if (autoBoot && customInit) {
|
|
107
|
+
throw new Error('The customInit hook must not be defined when autoBoot is true');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Process the customInit hook
|
|
111
|
+
function customInit(config, initializeApp, define, onBootstrapError) {
|
|
112
|
+
// Validate config
|
|
113
|
+
const { autoBoot, customInit } = config;
|
|
114
|
+
validatePreInit(autoBoot, customInit);
|
|
115
|
+
// Set up arguments and call the customInit hook, if available
|
|
116
|
+
if (customInit) {
|
|
117
|
+
const lwr = {
|
|
118
|
+
initializeApp,
|
|
119
|
+
define,
|
|
120
|
+
onBootstrapError,
|
|
121
|
+
attachDispatcher,
|
|
122
|
+
};
|
|
123
|
+
customInit(lwr, config);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* global document */
|
|
128
|
+
/* eslint-disable lwr/no-unguarded-apis */
|
|
129
|
+
const hasSetTimeout = typeof setTimeout === 'function';
|
|
130
|
+
const hasConsole = typeof console !== 'undefined';
|
|
131
|
+
/* eslint-enable lwr/no-unguarded-apis */
|
|
132
|
+
class LoaderShim {
|
|
133
|
+
constructor(global) {
|
|
134
|
+
this.defineCache = {};
|
|
135
|
+
this.orderedDefs = [];
|
|
136
|
+
// Parse configuration
|
|
137
|
+
this.global = global;
|
|
138
|
+
this.config = global.LWR;
|
|
139
|
+
this.loaderSpecifier = 'lwr/loader/v/0_6_2';
|
|
140
|
+
// Set up the temporary LWR.define function and customInit hook
|
|
141
|
+
const tempDefine = this.tempDefine.bind(this);
|
|
142
|
+
global.LWR.define = tempDefine;
|
|
143
|
+
this.bootReady = this.config.autoBoot;
|
|
144
|
+
// Start watchdog timer
|
|
145
|
+
if (hasSetTimeout) {
|
|
146
|
+
this.watchdogTimerId = this.startWatchdogTimer();
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
customInit(Object.freeze(this.config), this.postCustomInit.bind(this), tempDefine, (e) => {
|
|
150
|
+
this.errorHandler = e;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
this.enterErrorState(e);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Return true if the app can be initialized
|
|
158
|
+
canInit() {
|
|
159
|
+
// Initialize the app if:
|
|
160
|
+
// - bootReady: autoBoot is on OR customInit has finished
|
|
161
|
+
// - all required modules are defined
|
|
162
|
+
const allDefined = this.config.requiredModules.every((m) => this.orderedDefs.includes(m));
|
|
163
|
+
return this.bootReady && allDefined;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Create a temporary LWR.define() function which captures all
|
|
167
|
+
* calls that occur BEFORE the full loader module is available
|
|
168
|
+
*
|
|
169
|
+
* Each call to LWR.define() is stored in 2 ways:
|
|
170
|
+
* - in a map as [moduleName, arguments] pairs
|
|
171
|
+
* - each moduleName is pushed onto an array, to preserve
|
|
172
|
+
* the order in which the modules were defined
|
|
173
|
+
*/
|
|
174
|
+
tempDefine(...args) {
|
|
175
|
+
// Cache the incoming module
|
|
176
|
+
const moduleName = args[0];
|
|
177
|
+
this.defineCache[moduleName] = args;
|
|
178
|
+
this.orderedDefs.push(moduleName);
|
|
179
|
+
if (this.canInit()) {
|
|
180
|
+
if (hasSetTimeout) {
|
|
181
|
+
// requiredModules are defined, clear watchdog timer
|
|
182
|
+
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
183
|
+
clearTimeout(this.watchdogTimerId);
|
|
184
|
+
}
|
|
185
|
+
this.initApp();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// Called by the customInit hook via lwr.initializeApp()
|
|
189
|
+
postCustomInit() {
|
|
190
|
+
this.bootReady = true;
|
|
191
|
+
if (this.canInit()) {
|
|
192
|
+
this.initApp();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Create the loader and initialize the application
|
|
196
|
+
initApp() {
|
|
197
|
+
try {
|
|
198
|
+
const loaderConfig = {
|
|
199
|
+
endpoints: this.config.endpoints,
|
|
200
|
+
baseUrl: this.config.baseUrl,
|
|
201
|
+
profiler: { logOperationStart, logOperationEnd },
|
|
202
|
+
// TODO: can be removed following https://github.com/salesforce/lwr/issues/1087
|
|
203
|
+
appMetadata: {
|
|
204
|
+
appId: this.config.appId,
|
|
205
|
+
bootstrapModule: this.config.bootstrapModule,
|
|
206
|
+
rootComponent: this.config.rootComponent,
|
|
207
|
+
rootComponents: this.config.rootComponents,
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
const loader = createLoader(this.loaderSpecifier, this.defineCache[this.loaderSpecifier], loaderConfig, this.config.preloadModules);
|
|
211
|
+
this.createProfilerModule(loader);
|
|
212
|
+
this.mountApp(loader);
|
|
213
|
+
}
|
|
214
|
+
catch (e) {
|
|
215
|
+
this.enterErrorState(e);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
waitForDOMContentLoaded() {
|
|
219
|
+
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
220
|
+
if (typeof document === undefined) {
|
|
221
|
+
return Promise.resolve();
|
|
222
|
+
}
|
|
223
|
+
// Resolve if document is already "ready" https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
|
|
224
|
+
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
225
|
+
if (document.readyState === 'interactive' || document.readyState === 'complete') {
|
|
226
|
+
return Promise.resolve();
|
|
227
|
+
}
|
|
228
|
+
return new Promise((resolve) => {
|
|
229
|
+
// eslint-disable-next-line lwr/no-unguarded-apis
|
|
230
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
231
|
+
resolve();
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
// Create a module out of the profiler
|
|
236
|
+
// Note: The profiler is also available as a module through lwc module resolution (see package.json)
|
|
237
|
+
createProfilerModule(loader) {
|
|
238
|
+
const exporter = (exports) => {
|
|
239
|
+
Object.assign(exports, { logOperationStart, logOperationEnd });
|
|
240
|
+
};
|
|
241
|
+
loader.define('lwr/profiler/v/0_6_2', ['exports'], exporter);
|
|
242
|
+
}
|
|
243
|
+
// Set up the application globals, import map, root custom element...
|
|
244
|
+
mountApp(loader) {
|
|
245
|
+
const { bootstrapModule, rootComponent, rootComponents, endpoints, imports, index } = this.config;
|
|
246
|
+
// Set global LWR.define to loader.define
|
|
247
|
+
this.global.LWR = Object.freeze({
|
|
248
|
+
define: loader.define.bind(loader),
|
|
249
|
+
rootComponent,
|
|
250
|
+
rootComponents,
|
|
251
|
+
endpoints,
|
|
252
|
+
imports: imports || {},
|
|
253
|
+
index: index || {},
|
|
254
|
+
});
|
|
255
|
+
// Redefine all modules in the temporary cache
|
|
256
|
+
this.orderedDefs.forEach((specifier) => {
|
|
257
|
+
if (specifier !== this.loaderSpecifier) {
|
|
258
|
+
loader.define(...this.defineCache[specifier]);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
// by default, app initialization is gated on waiting for document to be parsed (via DOMContentLoaded)
|
|
262
|
+
const { disableInitDefer } = this.config;
|
|
263
|
+
// Load the import mappings and application bootstrap module
|
|
264
|
+
loader
|
|
265
|
+
.registerImportMappings({ imports, index }, [bootstrapModule, rootComponent])
|
|
266
|
+
.then(() => {
|
|
267
|
+
if (!disableInitDefer) {
|
|
268
|
+
return this.waitForDOMContentLoaded();
|
|
269
|
+
}
|
|
270
|
+
})
|
|
271
|
+
.then(() => loader.load(bootstrapModule))
|
|
272
|
+
.catch((reason) => {
|
|
273
|
+
this.enterErrorState(new Error(`Application ${rootComponent} could not be loaded: ${reason}`));
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
// Trigger bootstrap error state, and call error handler if registered
|
|
277
|
+
enterErrorState(error) {
|
|
278
|
+
logOperationStart({ id: BOOTSTRAP_ERROR });
|
|
279
|
+
if (this.errorHandler) {
|
|
280
|
+
this.errorHandler(error);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
if (hasConsole) {
|
|
284
|
+
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
285
|
+
console.error(`An error occurred during LWR bootstrap. ${error.message}`, error.stack);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// eslint-disable-next-line no-undef, lwr/no-unguarded-apis
|
|
290
|
+
startWatchdogTimer() {
|
|
291
|
+
// eslint-disable-next-line lwr/no-unguarded-apis, no-undef
|
|
292
|
+
return setTimeout(() => {
|
|
293
|
+
this.enterErrorState(new Error('Failed to load required modules - timed out'));
|
|
294
|
+
}, REQUIRED_MODULES_TIMEOUT);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// The loader module is ALWAYS required
|
|
299
|
+
const GLOBAL = globalThis;
|
|
300
|
+
GLOBAL.LWR.requiredModules = GLOBAL.LWR.requiredModules || [];
|
|
301
|
+
if (GLOBAL.LWR.requiredModules.indexOf('lwr/loader/v/0_6_2') < 0) {
|
|
302
|
+
GLOBAL.LWR.requiredModules.push('lwr/loader/v/0_6_2');
|
|
303
|
+
}
|
|
304
|
+
new LoaderShim(GLOBAL);
|
|
262
305
|
|
|
263
306
|
}());
|
|
264
307
|
|
|
265
|
-
LWR.define('lwr/loader/v/
|
|
308
|
+
LWR.define('lwr/loader/v/0_6_2', ['exports'], function (exports) { 'use strict';
|
|
266
309
|
|
|
267
310
|
const templateRegex = /\{([0-9]+)\}/g;
|
|
268
311
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -559,12 +602,15 @@ LWR.define('lwr/loader/v/0_6_0-alpha_9', ['exports'], function (exports) { 'use
|
|
|
559
602
|
});
|
|
560
603
|
}
|
|
561
604
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
const
|
|
565
|
-
const
|
|
566
|
-
const
|
|
567
|
-
const
|
|
605
|
+
// Bootstrap / shim
|
|
606
|
+
|
|
607
|
+
const LOADER_PREFIX = 'lwr.loader.';
|
|
608
|
+
const MODULE_DEFINE = `${LOADER_PREFIX}module.define`;
|
|
609
|
+
const MODULE_FETCH = `${LOADER_PREFIX}module.fetch`;
|
|
610
|
+
const MODULE_ERROR = `${LOADER_PREFIX}module.error`;
|
|
611
|
+
|
|
612
|
+
const MAPPINGS_FETCH = `${LOADER_PREFIX}mappings.fetch`;
|
|
613
|
+
const MAPPINGS_ERROR = `${LOADER_PREFIX}mappings.error`;
|
|
568
614
|
|
|
569
615
|
/* spec based import map resolver */
|
|
570
616
|
class ImportMetadataResolver {
|
|
@@ -681,7 +727,7 @@ LWR.define('lwr/loader/v/0_6_0-alpha_9', ['exports'], function (exports) { 'use
|
|
|
681
727
|
if (pending) {
|
|
682
728
|
return pending;
|
|
683
729
|
}
|
|
684
|
-
this.config.profiler.logOperationStart({ id:
|
|
730
|
+
this.config.profiler.logOperationStart({ id: MAPPINGS_FETCH, specifier });
|
|
685
731
|
const fetchMappingService = this.hasMappingHooks()
|
|
686
732
|
? this.evaluateMappingHooks
|
|
687
733
|
: this.fetchNewMappings;
|
|
@@ -696,6 +742,7 @@ LWR.define('lwr/loader/v/0_6_0-alpha_9', ['exports'], function (exports) { 'use
|
|
|
696
742
|
if (!uri) {
|
|
697
743
|
throw new LoaderError(UNRESOLVED, [specifier]);
|
|
698
744
|
}
|
|
745
|
+
this.config.profiler.logOperationEnd({ id: MAPPINGS_FETCH, specifier });
|
|
699
746
|
return uri;
|
|
700
747
|
})
|
|
701
748
|
.finally(() => {
|
|
@@ -740,7 +787,7 @@ LWR.define('lwr/loader/v/0_6_0-alpha_9', ['exports'], function (exports) { 'use
|
|
|
740
787
|
const uri = resolveUrl(this.buildMappingUrl(specifier), this.getBaseUrl());
|
|
741
788
|
return globalThis.fetch(uri).then((res) => {
|
|
742
789
|
if (!res.ok) {
|
|
743
|
-
this.config.profiler.logOperationStart({ id:
|
|
790
|
+
this.config.profiler.logOperationStart({ id: MAPPINGS_ERROR, specifier });
|
|
744
791
|
throw new LoaderError(UNRESOLVED, [specifier]);
|
|
745
792
|
}
|
|
746
793
|
return res
|
|
@@ -794,6 +841,8 @@ LWR.define('lwr/loader/v/0_6_0-alpha_9', ['exports'], function (exports) { 'use
|
|
|
794
841
|
}
|
|
795
842
|
}
|
|
796
843
|
|
|
844
|
+
const MODULE_LOAD_TIMEOUT_TIMER = 300000;
|
|
845
|
+
|
|
797
846
|
let lastWindowError;
|
|
798
847
|
if (hasDocument) {
|
|
799
848
|
globalThis.addEventListener('error', (evt) => {
|
|
@@ -1008,7 +1057,7 @@ LWR.define('lwr/loader/v/0_6_0-alpha_9', ['exports'], function (exports) { 'use
|
|
|
1008
1057
|
// if module is "external", resolve the external promise to notify any dependees
|
|
1009
1058
|
mod.external.resolveExternal(moduleDef);
|
|
1010
1059
|
}
|
|
1011
|
-
this.profiler.logOperationStart({ id:
|
|
1060
|
+
this.profiler.logOperationStart({ id: MODULE_DEFINE, specifier: name });
|
|
1012
1061
|
this.namedDefineRegistry.set(name, moduleDef);
|
|
1013
1062
|
this.lastDefine = moduleDef;
|
|
1014
1063
|
}
|
|
@@ -1191,6 +1240,9 @@ LWR.define('lwr/loader/v/0_6_0-alpha_9', ['exports'], function (exports) { 'use
|
|
|
1191
1240
|
if (moduleExports.__defaultInterop) {
|
|
1192
1241
|
Object.defineProperty(moduleRecord.module, '__defaultInterop', { value: true });
|
|
1193
1242
|
}
|
|
1243
|
+
if (moduleExports.__esModule) {
|
|
1244
|
+
Object.defineProperty(moduleRecord.module, '__esModule', { value: true });
|
|
1245
|
+
}
|
|
1194
1246
|
moduleRecord.evaluated = true;
|
|
1195
1247
|
Object.freeze(moduleRecord.module);
|
|
1196
1248
|
return moduleRecord.module;
|
|
@@ -1239,7 +1291,7 @@ LWR.define('lwr/loader/v/0_6_0-alpha_9', ['exports'], function (exports) { 'use
|
|
|
1239
1291
|
}
|
|
1240
1292
|
const parentUrl = this.resolver.getBaseUrl(); // only support baseUrl for now
|
|
1241
1293
|
const specifier = moduleName || originalId;
|
|
1242
|
-
this.profiler.logOperationStart({ id:
|
|
1294
|
+
this.profiler.logOperationStart({ id: MODULE_FETCH, specifier });
|
|
1243
1295
|
return Promise.resolve()
|
|
1244
1296
|
.then(async () => {
|
|
1245
1297
|
const loadHooks = this.loadHook;
|
|
@@ -1277,10 +1329,11 @@ LWR.define('lwr/loader/v/0_6_0-alpha_9', ['exports'], function (exports) { 'use
|
|
|
1277
1329
|
if (!moduleDef) {
|
|
1278
1330
|
throw new LoaderError(FAIL_INSTANTIATE, [resolvedId]);
|
|
1279
1331
|
}
|
|
1332
|
+
this.profiler.logOperationEnd({ id: MODULE_FETCH, specifier });
|
|
1280
1333
|
return moduleDef;
|
|
1281
1334
|
})
|
|
1282
1335
|
.catch((e) => {
|
|
1283
|
-
this.profiler.logOperationStart({ id:
|
|
1336
|
+
this.profiler.logOperationStart({ id: MODULE_ERROR, specifier });
|
|
1284
1337
|
throw e;
|
|
1285
1338
|
});
|
|
1286
1339
|
}
|
|
@@ -1364,12 +1417,25 @@ LWR.define('lwr/loader/v/0_6_0-alpha_9', ['exports'], function (exports) { 'use
|
|
|
1364
1417
|
logOperationStart: () => {
|
|
1365
1418
|
/* noop */
|
|
1366
1419
|
},
|
|
1420
|
+
logOperationEnd: () => {
|
|
1421
|
+
/* noop */
|
|
1422
|
+
},
|
|
1367
1423
|
};
|
|
1368
1424
|
}
|
|
1369
1425
|
this.registry = new ModuleRegistry(Object.freeze({ endpoints: config.endpoints, baseUrl, profiler }));
|
|
1426
|
+
// TODO: W-10539691 - temp workaround for LWR-Java -- remove once appId is implemented there
|
|
1427
|
+
if (config.appMetadata && !config.appMetadata.appId) {
|
|
1428
|
+
// Parse the appId from the bootstrapModule
|
|
1429
|
+
// LWR-Java bootstrap module format: @lwr-bootstrap/my/app/v/0_0_1 -- my/app is the appId
|
|
1430
|
+
const match = config.appMetadata.bootstrapModule.match(/@lwr-bootstrap\/(.+)\/v\/.+/);
|
|
1431
|
+
const appId = match && match[1];
|
|
1432
|
+
config.appMetadata.appId = appId;
|
|
1433
|
+
}
|
|
1434
|
+
// TODO: https://github.com/salesforce/lwr/issues/1087
|
|
1370
1435
|
this.services = Object.freeze({
|
|
1371
1436
|
addLoaderPlugin: this.registry.addLoaderPlugin.bind(this.registry),
|
|
1372
1437
|
handleStaleModule: this.registry.registerHandleStaleModuleHook.bind(this.registry),
|
|
1438
|
+
appMetadata: config.appMetadata,
|
|
1373
1439
|
});
|
|
1374
1440
|
}
|
|
1375
1441
|
/**
|