@lwrjs/everywhere 0.9.0-alpha.8 → 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 -6
  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_8/s/b332def6b740c63a4aa2d9a373f969bb → 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_8 → 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/23c5f9e329a04ac555e7cc8afbb642c2/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_8/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_17_0/s/60dae7a83431c35c02c87ca8aaaa6044/lwc.js +0 -6244
  36. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/everywhereAmd/v/0_9_0-alpha_8/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_8/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_8/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_8/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_8/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_8 +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
@@ -1,11 +1,21 @@
1
- LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
2
- "use strict";
1
+ LWR.define('lwr/loader/v/0_9_0', ['exports'], function (exports) { 'use strict';
2
+
3
+ /**
4
+ * Copyright (c) 2021, salesforce.com, inc.
5
+ * All rights reserved.
6
+ * SPDX-License-Identifier: MIT
7
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
8
+ */
9
+ /* LWR Module Loader v0.9.0 */
3
10
  const templateRegex = /\{([0-9]+)\}/g;
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
12
  function templateString(template, args) {
5
13
  return template.replace(templateRegex, (_, index) => {
6
14
  return args[index];
7
15
  });
8
16
  }
17
+
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
19
  function generateErrorMessage(errorInfo, args) {
10
20
  const message = Array.isArray(args) ? templateString(errorInfo.message, args) : errorInfo.message;
11
21
  return `LWR${errorInfo.code}: ${message}`;
@@ -15,6 +25,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
15
25
  super();
16
26
  this.message = generateErrorMessage(errorInfo, errorArgs);
17
27
  }
28
+ /*LWC compiler v2.38.1*/
18
29
  }
19
30
  function invariant(condition, errorInfo) {
20
31
  if (!condition) {
@@ -22,79 +33,79 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
22
33
  }
23
34
  }
24
35
  const MISSING_NAME = Object.freeze({
25
- code: 3e3,
26
- message: "A module name is required.",
36
+ code: 3000,
37
+ message: 'A module name is required.',
27
38
  level: 0
28
39
  });
29
40
  const FAIL_INSTANTIATE = Object.freeze({
30
41
  code: 3004,
31
- message: "Failed to instantiate module: {0}",
42
+ message: 'Failed to instantiate module: {0}',
32
43
  level: 0
33
44
  });
34
45
  const NO_AMD_REQUIRE = Object.freeze({
35
46
  code: 3005,
36
- message: "AMD require not supported.",
47
+ message: 'AMD require not supported.',
37
48
  level: 0
38
49
  });
39
50
  const FAILED_DEP = Object.freeze({
40
51
  code: 3006,
41
52
  level: 0,
42
- message: "Failed to load dependency: {0}"
53
+ message: 'Failed to load dependency: {0}'
43
54
  });
44
55
  const INVALID_DEPS = Object.freeze({
45
56
  code: 3007,
46
- message: "Unexpected value received for dependencies argument; expected an array.",
57
+ message: 'Unexpected value received for dependencies argument; expected an array.',
47
58
  level: 0
48
59
  });
49
60
  const FAIL_LOAD = Object.freeze({
50
61
  code: 3008,
51
62
  level: 0,
52
- message: "Error loading {0}"
63
+ message: 'Error loading {0}'
53
64
  });
54
65
  const UNRESOLVED = Object.freeze({
55
66
  code: 3009,
56
67
  level: 0,
57
- message: "Unable to resolve bare specifier: {0}"
68
+ message: 'Unable to resolve bare specifier: {0}'
58
69
  });
59
70
  const NO_BASE_URL = Object.freeze({
60
71
  code: 3010,
61
72
  level: 0,
62
- message: "baseUrl not set"
73
+ message: 'baseUrl not set'
63
74
  });
64
75
  Object.freeze({
65
76
  code: 3011,
66
77
  level: 0,
67
- message: "Cannot set a loader service multiple times"
78
+ message: 'Cannot set a loader service multiple times'
68
79
  });
69
80
  const INVALID_HOOK = Object.freeze({
70
81
  code: 3012,
71
82
  level: 0,
72
- message: "Invalid hook received"
83
+ message: 'Invalid hook received'
73
84
  });
74
85
  const INVALID_LOADER_SERVICE_RESPONSE = Object.freeze({
75
86
  code: 3013,
76
87
  level: 0,
77
- message: "Invalid response received from hook"
88
+ message: 'Invalid response received from hook'
78
89
  });
79
90
  const MODULE_LOAD_TIMEOUT = Object.freeze({
80
91
  code: 3014,
81
92
  level: 0,
82
- message: "Error loading {0} - timed out"
93
+ message: 'Error loading {0} - timed out'
83
94
  });
84
95
  const HTTP_FAIL_LOAD = Object.freeze({
85
96
  code: 3015,
86
97
  level: 0,
87
- message: "Error loading {0}, status code {1}"
98
+ message: 'Error loading {0}, status code {1}'
88
99
  });
89
100
  const STALE_HOOK_ERROR = Object.freeze({
90
101
  code: 3016,
91
102
  level: 0,
92
- message: "An error occurred handling module conflict"
103
+ message: 'An error occurred handling module conflict'
93
104
  });
94
105
  const MODULE_ALREADY_LOADED = Object.freeze({
95
106
  code: 3017,
96
107
  level: 0,
97
- message: "Marking module(s) as externally loaded, but they are already loaded: {0}"
108
+ message: 'Marking module(s) as externally loaded, but they are already loaded:'
98
109
  });
99
110
  const FAIL_HOOK_LOAD = Object.freeze({
100
111
  code: 3018,
@@ -104,107 +115,159 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
104
115
  const NO_MAPPING_URL = Object.freeze({
105
116
  code: 3019,
106
117
  level: 0,
107
- message: "Mapping endpoint not set"
118
+ message: 'Mapping endpoint not set'
108
119
  });
109
120
  const BAD_IMPORT_METADATA = Object.freeze({
110
121
  code: 3020,
111
122
  level: 0,
112
- message: "Invalid import metadata: {0} {1}"
123
+ message: 'Invalid import metadata: {0} {1}'
113
124
  });
125
+ /* importMap errors */
114
126
  Object.freeze({
115
127
  code: 3011,
116
128
  level: 0,
117
- message: "import map is not valid"
129
+ message: 'import map is not valid'
118
130
  });
119
- const hasDocument = typeof document !== "undefined";
120
- const hasSetTimeout = typeof setTimeout === "function";
121
- const hasConsole = typeof console !== "undefined";
131
+
132
+ /* eslint-disable lwr/no-unguarded-apis */
133
+ const hasDocument = typeof document !== 'undefined';
134
+ const hasSetTimeout = typeof setTimeout === 'function';
135
+ const hasConsole = typeof console !== 'undefined';
136
+ /* eslint-enable lwr/no-unguarded-apis */
137
+
122
138
  function getBaseUrl() {
123
- let baseUrl = void 0;
139
+ let baseUrl = undefined;
124
140
  if (hasDocument) {
125
- const baseEl = document.querySelector("base[href]");
141
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
142
+ const baseEl = document.querySelector('base[href]');
126
143
  baseUrl = baseEl && baseEl.href;
127
144
  }
128
- if (!baseUrl && typeof location !== "undefined") {
129
- baseUrl = location.href.split("#")[0].split("?")[0];
130
- const lastSepIndex = baseUrl.lastIndexOf("/");
145
+ // eslint-disable-next-line lwr/no-unguarded-apis
146
+ if (!baseUrl && typeof location !== 'undefined') {
147
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
148
+ baseUrl = location.href.split('#')[0].split('?')[0];
149
+ const lastSepIndex = baseUrl.lastIndexOf('/');
131
150
  if (lastSepIndex !== -1) {
132
151
  baseUrl = baseUrl.slice(0, lastSepIndex + 1);
133
152
  }
134
153
  }
135
154
  return baseUrl;
136
155
  }
156
+ /**
157
+ * Check if a string is a URL based on Common Internet Scheme Syntax
158
+ * https://www.ietf.org/rfc/rfc1738.txt
159
+ *
160
+ * URL Format:
161
+ * <scheme>:<scheme-specific-part>
162
+ * Common Internet Scheme Syntax:
163
+ * The scheme specific part starts with a double slash('//')
164
+ *
165
+ * A valid URL has a colon that is followed by a double slash.
166
+ *
167
+ * @param url - the url that is being checked
168
+ * @returns boolean
169
+ *
170
+ * @example Valid URLs
171
+ * 'https://salesforce.com'
172
+ * 'http://localhost:3000'
173
+ *
174
+ * @example Invalid URLs
175
+ * 'salesforce.com'
176
+ * 'localhost:3000'
177
+ * '@salesforce/label/type:namespace:name'
178
+ */
137
179
  function isUrl(url) {
138
- return url.indexOf("://") !== -1;
180
+ return url.indexOf('://') !== -1;
139
181
  }
182
+ // Borrowed and adapted from https://github.com/systemjs/systemjs/blob/master/src/common.js
183
+ // Resolves the first path segment relative to the second/parent URL
184
+ // eg: resolveIfNotPlainOrUrl('../test', 'http://www.site.com/one/two') => 'http://www.site.com/test'
185
+ // eg: resolveIfNotPlainOrUrl('./x/y/z', 'https://my.com/segment')).toBe('https://my.com/x/y/z')
140
186
  function resolveIfNotPlainOrUrl(relUrl, parentUrl) {
141
187
  const backslashRegEx = /\\/g;
142
- if (relUrl.indexOf("\\") !== -1)
143
- relUrl = relUrl.replace(backslashRegEx, "/");
144
- if (relUrl[0] === "/" && relUrl[1] === "/") {
145
- return parentUrl.slice(0, parentUrl.indexOf(":") + 1) + relUrl;
146
- } else if (relUrl[0] === "." && (relUrl[1] === "/" || relUrl[1] === "." && (relUrl[2] === "/" || relUrl.length === 2 && (relUrl += "/")) || relUrl.length === 1 && (relUrl += "/")) || relUrl[0] === "/") {
147
- const parentProtocol = parentUrl.slice(0, parentUrl.indexOf(":") + 1);
188
+ if (relUrl.indexOf('\\') !== -1) relUrl = relUrl.replace(backslashRegEx, '/');
189
+ // protocol-relative
190
+ if (relUrl[0] === '/' && relUrl[1] === '/') {
191
+ return parentUrl.slice(0, parentUrl.indexOf(':') + 1) + relUrl;
192
+ }
193
+ // relative-url
194
+ else if (relUrl[0] === '.' && (relUrl[1] === '/' || relUrl[1] === '.' && (relUrl[2] === '/' || relUrl.length === 2 && (relUrl += '/')) || relUrl.length === 1 && (relUrl += '/')) || relUrl[0] === '/') {
195
+ const parentProtocol = parentUrl.slice(0, parentUrl.indexOf(':') + 1);
148
196
  let pathname;
149
- if (parentUrl[parentProtocol.length + 1] === "/") {
150
- if (parentProtocol !== "file:") {
197
+ if (parentUrl[parentProtocol.length + 1] === '/') {
198
+ // resolving to a :// so we need to read out the auth and host
199
+ if (parentProtocol !== 'file:') {
151
200
  pathname = parentUrl.slice(parentProtocol.length + 2);
152
- pathname = pathname.slice(pathname.indexOf("/") + 1);
201
+ pathname = pathname.slice(pathname.indexOf('/') + 1);
153
202
  } else {
154
203
  pathname = parentUrl.slice(8);
155
204
  }
156
205
  } else {
157
- pathname = parentUrl.slice(parentProtocol.length + (parentUrl[parentProtocol.length] === "/" ? 1 : 0));
206
+ // resolving to :/ so pathname is the /... part
207
+ pathname = parentUrl.slice(parentProtocol.length + (parentUrl[parentProtocol.length] === '/' ? 1 : 0));
158
208
  }
159
- if (relUrl[0] === "/")
160
- return parentUrl.slice(0, parentUrl.length - pathname.length - 1) + relUrl;
161
- const segmented = pathname.slice(0, pathname.lastIndexOf("/") + 1) + relUrl;
209
+ if (relUrl[0] === '/') return parentUrl.slice(0, parentUrl.length - pathname.length - 1) + relUrl;
210
+ // join together and split for removal of .. and . segments
211
+ // looping the string instead of anything fancy for perf reasons
212
+ // '../../../../../z' resolved to 'x/y' is just 'z'
213
+ const segmented = pathname.slice(0, pathname.lastIndexOf('/') + 1) + relUrl;
162
214
  const output = [];
163
215
  let segmentIndex = -1;
164
216
  for (let i = 0; i < segmented.length; i++) {
217
+ // busy reading a segment - only terminate on '/'
165
218
  if (segmentIndex !== -1) {
166
- if (segmented[i] === "/") {
219
+ if (segmented[i] === '/') {
167
220
  output.push(segmented.slice(segmentIndex, i + 1));
168
221
  segmentIndex = -1;
169
222
  }
170
- } else if (segmented[i] === ".") {
171
- if (segmented[i + 1] === "." && (segmented[i + 2] === "/" || i + 2 === segmented.length)) {
223
+ }
224
+ // new segment - check if it is relative
225
+ else if (segmented[i] === '.') {
226
+ // ../ segment
227
+ if (segmented[i + 1] === '.' && (segmented[i + 2] === '/' || i + 2 === segmented.length)) {
172
228
  output.pop();
173
229
  i += 2;
174
- } else if (segmented[i + 1] === "/" || i + 1 === segmented.length) {
230
+ }
231
+ // ./ segment
232
+ else if (segmented[i + 1] === '/' || i + 1 === segmented.length) {
175
233
  i += 1;
176
234
  } else {
235
+ // the start of a new segment as below
177
236
  segmentIndex = i;
178
237
  }
179
- } else {
238
+ }
239
+ // it is the start of a new segment
240
+ else {
180
241
  segmentIndex = i;
181
242
  }
182
243
  }
183
- if (segmentIndex !== -1)
184
- output.push(segmented.slice(segmentIndex));
185
- return parentUrl.slice(0, parentUrl.length - pathname.length) + output.join("");
244
+ // finish reading out the last segment
245
+ if (segmentIndex !== -1) output.push(segmented.slice(segmentIndex));
246
+ return parentUrl.slice(0, parentUrl.length - pathname.length) + output.join('');
186
247
  }
187
248
  }
188
249
  function resolveUrl(relUrl, parentUrl) {
189
- const resolvedUrl = resolveIfNotPlainOrUrl(relUrl, parentUrl) || (isUrl(relUrl) ? relUrl : resolveIfNotPlainOrUrl("./" + relUrl, parentUrl));
250
+ const resolvedUrl = resolveIfNotPlainOrUrl(relUrl, parentUrl) || (isUrl(relUrl) ? relUrl : resolveIfNotPlainOrUrl('./' + relUrl, parentUrl));
190
251
  return resolvedUrl;
191
252
  }
192
253
  function createScript(url) {
193
- const script = document.createElement("script");
254
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
255
+ const script = document.createElement('script');
194
256
  script.async = true;
195
- script.crossOrigin = "anonymous";
257
+ script.crossOrigin = 'anonymous';
196
258
  script.src = url;
197
259
  return script;
198
260
  }
199
261
  let lastWindowError$1, lastWindowErrorUrl;
200
262
  function loadModuleDef(url) {
201
- return new Promise(function(resolve, reject) {
263
+ return new Promise(function (resolve, reject) {
202
264
  if (hasDocument) {
265
+ /* eslint-disable lwr/no-unguarded-apis, no-undef */
203
266
  const script = createScript(url);
204
- script.addEventListener("error", () => {
267
+ script.addEventListener('error', () => {
205
268
  reject(new LoaderError(FAIL_LOAD, [url]));
206
269
  });
207
- script.addEventListener("load", () => {
270
+ script.addEventListener('load', () => {
208
271
  document.head.removeChild(script);
209
272
  if (lastWindowErrorUrl === url) {
210
273
  reject(lastWindowError$1);
@@ -213,23 +276,36 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
213
276
  }
214
277
  });
215
278
  document.head.appendChild(script);
279
+ /* eslint-enable lwr/no-unguarded-apis, no-undef */
216
280
  }
217
281
  });
218
282
  }
283
+
219
284
  if (hasDocument) {
220
- window.addEventListener("error", (evt) => {
285
+ // When a script is executed, runtime errors are on the global/window scope which are NOT caught by the script's onerror handler.
286
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
287
+ window.addEventListener('error', evt => {
221
288
  lastWindowErrorUrl = evt.filename;
222
289
  lastWindowError$1 = evt.error;
223
290
  });
224
291
  }
225
- const LOADER_PREFIX = "lwr.loader.";
292
+
293
+ // Bootstrap / shim
294
+
295
+ // Loader: modules
296
+ const LOADER_PREFIX = 'lwr.loader.';
226
297
  const MODULE_DEFINE = `${LOADER_PREFIX}module.define`;
227
298
  const MODULE_FETCH = `${LOADER_PREFIX}module.fetch`;
228
299
  const MODULE_ERROR = `${LOADER_PREFIX}module.error`;
300
+
301
+ // Loader: mappings
229
302
  const MAPPINGS_FETCH = `${LOADER_PREFIX}mappings.fetch`;
230
303
  const MAPPINGS_ERROR = `${LOADER_PREFIX}mappings.error`;
304
+
305
+ /* spec based import map resolver */
231
306
  class ImportMetadataResolver {
232
307
  constructor(config, invalidationCallback) {
308
+ // Default to empty mappings
233
309
  this.importURICache = new Map();
234
310
  this.pendingURICache = new Map();
235
311
  this.loadMappingHooks = [];
@@ -240,14 +316,15 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
240
316
  this.loadMappingHooks.push(hook);
241
317
  }
242
318
  getMappingEndpoint() {
243
- return this.config.endpoints && this.config.endpoints.uris ? this.config.endpoints.uris.mapping : void 0;
319
+ return this.config.endpoints && this.config.endpoints.uris ? this.config.endpoints.uris.mapping : undefined;
244
320
  }
245
321
  getModifiersAsUrlParams() {
246
- const modifiers = this.config.endpoints ? this.config.endpoints.modifiers : void 0;
322
+ const modifiers = this.config.endpoints ? this.config.endpoints.modifiers : undefined;
247
323
  if (!modifiers) {
248
- return "";
324
+ // No modifiers return an empty string to append to the URL
325
+ return '';
249
326
  } else {
250
- const qs = Object.keys(modifiers).map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(modifiers[key])}`).join("&");
327
+ const qs = Object.keys(modifiers).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(modifiers[key])}`).join('&');
251
328
  return `?${qs}`;
252
329
  }
253
330
  }
@@ -262,18 +339,18 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
262
339
  }
263
340
  registerImportMappings(newImportMetadata, rootSpecifiers) {
264
341
  if (!rootSpecifiers || rootSpecifiers.length === 0) {
265
- const imports = newImportMetadata ? JSON.stringify(newImportMetadata) : "undefined";
266
- throw new LoaderError(BAD_IMPORT_METADATA, [imports, rootSpecifiers ? "[]" : "undefined"]);
342
+ const imports = newImportMetadata ? JSON.stringify(newImportMetadata) : 'undefined';
343
+ throw new LoaderError(BAD_IMPORT_METADATA, [imports, rootSpecifiers ? '[]' : 'undefined']);
267
344
  }
268
345
  if (!newImportMetadata) {
269
- throw new LoaderError(BAD_IMPORT_METADATA, ["undefined", JSON.stringify(rootSpecifiers)]);
346
+ throw new LoaderError(BAD_IMPORT_METADATA, ['undefined', JSON.stringify(rootSpecifiers)]);
270
347
  }
271
348
  if (!newImportMetadata.imports || Object.keys(newImportMetadata.imports).length === 0) {
272
349
  throw new LoaderError(BAD_IMPORT_METADATA, [JSON.stringify(newImportMetadata), JSON.stringify(rootSpecifiers)]);
273
350
  }
274
351
  const index = newImportMetadata.index || {};
275
352
  for (const [uri, specifiers] of Object.entries(newImportMetadata.imports)) {
276
- specifiers.forEach((specifier) => {
353
+ specifiers.forEach(specifier => {
277
354
  const indexValue = index[specifier];
278
355
  const existing = this.importURICache.get(specifier);
279
356
  if (!existing) {
@@ -292,23 +369,34 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
292
369
  });
293
370
  }
294
371
  }
372
+ // Get URL from the local cache or return undefiend
295
373
  getURI(specifier) {
296
- return this.importURICache.has(specifier) ? resolveUrl(this.importURICache.get(specifier).uri, this.getBaseUrl()) : void 0;
374
+ return this.importURICache.has(specifier) ? resolveUrl(this.importURICache.get(specifier).uri, this.getBaseUrl()) : undefined;
297
375
  }
298
376
  resolveLocal(specifier) {
299
377
  const uri = this.getURI(specifier);
300
378
  if (uri) {
301
379
  return uri;
302
- } else if (isUrl(specifier) || specifier.startsWith("/")) {
380
+ } else if (isUrl(specifier) || specifier.startsWith('/')) {
303
381
  return specifier;
304
382
  }
305
- return void 0;
383
+ return undefined;
306
384
  }
385
+ /**
386
+ * Resolves a the URI for a specified module. It will return the value in this order:
387
+ *
388
+ * 1) Mapping from local URI cache
389
+ * 2) The URI if a specifier is already an absolute URI
390
+ * 3) Mapping fetched from a registered loader hook
391
+ * 4)
392
+ * @param specifier
393
+ * @returns module URI
394
+ */
307
395
  async resolve(specifier) {
308
396
  let uri = this.getURI(specifier);
309
397
  if (uri) {
310
398
  return uri;
311
- } else if (isUrl(specifier) || specifier.startsWith("/")) {
399
+ } else if (isUrl(specifier) || specifier.startsWith('/')) {
312
400
  return specifier;
313
401
  } else {
314
402
  const pending = this.pendingURICache.get(specifier);
@@ -320,7 +408,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
320
408
  specifier
321
409
  });
322
410
  const fetchMappingService = this.hasMappingHooks() ? this.evaluateMappingHooks : this.fetchNewMappings;
323
- const promise = fetchMappingService.bind(this)(specifier).then((importMetadata) => {
411
+ const promise = fetchMappingService.bind(this)(specifier).then(importMetadata => {
324
412
  if (!importMetadata || !importMetadata.imports) {
325
413
  throw new LoaderError(UNRESOLVED, [specifier]);
326
414
  }
@@ -344,28 +432,39 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
344
432
  hasMappingHooks() {
345
433
  return this.loadMappingHooks.length > 0;
346
434
  }
435
+ /**
436
+ * Evaluates mapping hooks. Returns first match. If all hooks return null call the mapping service.
437
+ * @param specifier Request module identifier
438
+ * @returns Import Metadata from the module root
439
+ */
347
440
  async evaluateMappingHooks(specifier) {
441
+ // Check with any registered loadMappingHooks
348
442
  const loadMappingHooks = this.loadMappingHooks;
349
443
  if (loadMappingHooks.length) {
350
444
  const knownModules = Array.from(this.importURICache.keys());
351
445
  for (let i = 0; i < loadMappingHooks.length; i++) {
352
446
  const loadMappingHook = loadMappingHooks[i];
447
+ // eslint-disable-next-line no-await-in-loop
353
448
  const response = await loadMappingHook(specifier, {
354
449
  knownModules
355
450
  });
356
- if (response || response === void 0) {
451
+ // undefined (but not null) is considered an un expected response so we will stop processing hooks here and throw an error
452
+ if (response || response === undefined) {
357
453
  return response;
358
454
  }
359
455
  }
360
456
  }
457
+ // If we still do not have a match call the mapping service
361
458
  return this.fetchNewMappings(specifier);
362
459
  }
363
460
  async fetchNewMappings(specifier) {
364
- if (typeof globalThis.fetch !== "function") {
461
+ if (typeof globalThis.fetch !== 'function') {
365
462
  throw new LoaderError(UNRESOLVED, [specifier]);
366
463
  }
464
+ // TODO For module invalidation with bundles it is recommended we have to send back all loaded root specified
465
+ // to ensure we detect all conflicts.
367
466
  const uri = resolveUrl(this.buildMappingUrl(specifier), this.getBaseUrl());
368
- return globalThis.fetch(uri).then((res) => {
467
+ return globalThis.fetch(uri).then(res => {
369
468
  if (!res.ok) {
370
469
  this.config.profiler.logOperationStart({
371
470
  id: MAPPINGS_ERROR,
@@ -373,9 +472,9 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
373
472
  });
374
473
  throw new LoaderError(UNRESOLVED, [specifier]);
375
474
  }
376
- return res.json().then((ret) => {
475
+ return res.json().then(ret => {
377
476
  return ret;
378
- }).catch((err) => {
477
+ }).catch(err => {
379
478
  throw new LoaderError(UNRESOLVED, [specifier]);
380
479
  });
381
480
  });
@@ -384,20 +483,21 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
384
483
  if (!identity || uri === identity) {
385
484
  this.importURICache.set(specifier, {
386
485
  uri,
387
- isRoot
486
+ isRoot: isRoot
388
487
  });
389
488
  } else {
390
489
  this.importURICache.set(specifier, {
391
490
  uri,
392
491
  identity,
393
- isRoot
492
+ isRoot: isRoot
394
493
  });
395
494
  }
396
495
  }
397
496
  }
398
497
  function reportError(error) {
399
- if (hasConsole)
400
- console.error(error);
498
+ // TODO eventually this should be configurable instrumentation to send this somewhere
499
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
500
+ if (hasConsole) console.error(error);
401
501
  }
402
502
  function evaluateHandleStaleModuleHooks(handleStaleModuleHooks, hookArgs) {
403
503
  const {
@@ -405,6 +505,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
405
505
  oldUrl,
406
506
  newUrl
407
507
  } = hookArgs;
508
+ // keep evaluating hooks if return value is null
408
509
  for (let i = 0; i < handleStaleModuleHooks.length; i++) {
409
510
  const hook = handleStaleModuleHooks[i];
410
511
  try {
@@ -421,23 +522,27 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
421
522
  }
422
523
  }
423
524
  }
424
- const MODULE_LOAD_TIMEOUT_TIMER = 3e5;
525
+ const MODULE_LOAD_TIMEOUT_TIMER = 300000;
526
+
527
+ /* global console,process */
425
528
  let lastWindowError;
426
529
  if (hasDocument) {
427
- globalThis.addEventListener("error", (evt) => {
530
+ globalThis.addEventListener('error', evt => {
428
531
  lastWindowError = evt.error;
429
532
  });
430
533
  }
431
- if (true) {
534
+ if (process.env.NODE_ENV !== 'production') {
432
535
  if (!hasSetTimeout && hasConsole) {
433
- console.warn("setTimeout API is not available, watchdog timer on load hook will not be set");
536
+ // eslint-disable-next-line lwr/no-unguarded-apis
537
+ console.warn('setTimeout API is not available, watchdog timer on load hook will not be set');
434
538
  }
435
539
  }
436
540
  function isCustomResponse(response) {
437
- return Object.prototype.hasOwnProperty.call(response, "data") && !Object.prototype.hasOwnProperty.call(response, "blob");
541
+ return Object.prototype.hasOwnProperty.call(response, 'data') && !Object.prototype.hasOwnProperty.call(response, 'blob');
438
542
  }
439
543
  function isFetchResponse(response) {
440
- return typeof response.blob === "function";
544
+ // if it quacks like a duck...
545
+ return typeof response.blob === 'function';
441
546
  }
442
547
  function isResponseAPromise(response) {
443
548
  return !!(response && response.then);
@@ -455,6 +560,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
455
560
  if (isCustomResponse(response)) {
456
561
  code = response.data;
457
562
  } else if (isResponse) {
563
+ // handle fetch response
458
564
  code = await response.text();
459
565
  } else {
460
566
  throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
@@ -462,9 +568,9 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
462
568
  if (!code) {
463
569
  throw new LoaderError(FAIL_LOAD, [id]);
464
570
  }
465
- code = `${code}
466
- //# sourceURL=${id}`;
571
+ code = `${code}\n//# sourceURL=${id}`; // append sourceURL for debugging
467
572
  try {
573
+ // TODO eval source maps for debugging
468
574
  eval(code);
469
575
  } catch (e) {
470
576
  throw new LoaderError(FAIL_LOAD, [id]);
@@ -480,22 +586,30 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
480
586
  return hookPromise;
481
587
  }
482
588
  return new Promise((resolve, reject) => {
589
+ // wrap the hook in a watchdog timer
590
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
483
591
  const timer = setTimeout(() => {
484
592
  reject(new LoaderError(MODULE_LOAD_TIMEOUT, [id]));
485
593
  }, MODULE_LOAD_TIMEOUT_TIMER);
486
- hookPromise.then((response) => {
594
+ hookPromise.then(response => {
487
595
  resolve(response);
488
596
  }).catch(() => {
489
597
  reject(new LoaderError(FAIL_HOOK_LOAD, [id]));
490
598
  }).finally(() => {
599
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
491
600
  clearTimeout(timer);
492
601
  });
493
602
  });
494
603
  }
604
+
605
+ /* global console,process */
495
606
  class ModuleRegistry {
496
607
  constructor(config) {
608
+ // A registry for named AMD defines containing the *metadata* of AMD module
497
609
  this.namedDefineRegistry = new Map();
610
+ // The evaluated module registry where the module identifier (name or URL?) is the key
498
611
  this.moduleRegistry = new Map();
612
+ // Aliases of modules in the registry
499
613
  this.aliases = new Map();
500
614
  this.profiler = config.profiler;
501
615
  this.resolver = new ImportMetadataResolver(config, this.importMetadataInvalidationCallback.bind(this));
@@ -513,7 +627,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
513
627
  }
514
628
  }
515
629
  async resolve(id, importer) {
516
- const parentUrl = this.resolver.getBaseUrl();
630
+ const parentUrl = this.resolver.getBaseUrl(); // only support baseUrl for now
517
631
  let resolved;
518
632
  let aliasedId = id;
519
633
  const resolveHooks = this.resolveHook;
@@ -525,24 +639,29 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
525
639
  });
526
640
  let result;
527
641
  if (response || response === null) {
642
+ // eslint-disable-next-line no-await-in-loop
528
643
  result = isResponseAPromise(response) ? await response : response;
529
644
  }
645
+ // if result is not null, attempt resolution
530
646
  if (result !== null) {
531
- if (typeof result === "string") {
647
+ if (typeof result === 'string') {
532
648
  if (resolveIfNotPlainOrUrl(result, parentUrl)) {
649
+ // string response can't be a URL
533
650
  throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
534
651
  }
535
- aliasedId = result;
652
+ aliasedId = result; // the next hook will receive the new id
536
653
  continue;
537
654
  }
538
655
  resolved = result && result.url && (resolveIfNotPlainOrUrl(result.url, parentUrl) || result.url);
539
656
  if (!resolved) {
540
657
  throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
541
658
  }
659
+ // Don't process any more hooks if we have resolved
542
660
  break;
543
661
  }
544
662
  }
545
663
  if (aliasedId !== id) {
664
+ // resolved module id is the aliased module if it has already been defined
546
665
  if (!resolved && this.namedDefineRegistry.has(aliasedId)) {
547
666
  return aliasedId;
548
667
  } else {
@@ -552,11 +671,13 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
552
671
  }
553
672
  if (!resolved) {
554
673
  const resolvedOrPlain = resolveIfNotPlainOrUrl(id, parentUrl) || id;
674
+ // if module registry already has named module the resolved id is the plain id
555
675
  if (this.moduleRegistry.has(resolvedOrPlain)) {
556
676
  return resolvedOrPlain;
557
677
  }
558
678
  const resolvedUrl = this.resolver.resolveLocal(resolvedOrPlain);
559
679
  if (resolvedUrl) {
680
+ // return the plain id if it is already defined && the resolvedUrl is NOT already in the module registry
560
681
  if (this.namedDefineRegistry.has(resolvedOrPlain) && this.namedDefineRegistry.get(resolvedOrPlain).defined) {
561
682
  const record = this.moduleRegistry.get(resolvedUrl);
562
683
  if (!record || !this.aliases.has(resolvedOrPlain)) {
@@ -571,6 +692,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
571
692
  try {
572
693
  resolved = await this.resolver.resolve(resolvedOrPlain);
573
694
  } catch (e) {
695
+ // defer to error handling below for unresolved
574
696
  }
575
697
  }
576
698
  if (!resolved || !isUrl(resolved)) {
@@ -589,8 +711,10 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
589
711
  }
590
712
  define(name, dependencies, exporter) {
591
713
  const mod = this.namedDefineRegistry.get(name);
714
+ // Don't allow redefining a module.
592
715
  if (mod && mod.defined) {
593
- if (hasConsole) {
716
+ if (process.env.NODE_ENV !== 'production' && hasConsole) {
717
+ // eslint-disable-next-line lwr/no-unguarded-apis
594
718
  console.warn(`Module redefine attempted: ${name}`);
595
719
  }
596
720
  this.lastDefine = mod;
@@ -603,6 +727,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
603
727
  defined: true
604
728
  };
605
729
  if (mod && mod.external) {
730
+ // if module is "external", resolve the external promise to notify any dependees
606
731
  mod.external.resolveExternal(moduleDef);
607
732
  }
608
733
  this.profiler.logOperationStart({
@@ -612,20 +737,25 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
612
737
  this.namedDefineRegistry.set(name, moduleDef);
613
738
  this.lastDefine = moduleDef;
614
739
  }
740
+ /**
741
+ * Marks modules as "externally" loaded/provided, so that the loader does not attempt to fetch them.
742
+ *
743
+ * @param modules - list of module identifiers
744
+ */
615
745
  registerExternalModules(modules) {
616
- const alreadyRegistered = [];
617
- modules.map((id) => {
618
- if (this.namedDefineRegistry.has(id)) {
619
- alreadyRegistered.push(id);
620
- } else {
746
+ modules.map(id => {
747
+ if (!this.namedDefineRegistry.has(id)) {
621
748
  let resolveExternal;
622
749
  let timer;
623
750
  const moduleDefPromise = new Promise((resolve, reject) => {
624
751
  resolveExternal = resolve;
752
+ // watch the external for timeout
753
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
625
754
  timer = setTimeout(() => {
626
755
  reject(new LoaderError(MODULE_LOAD_TIMEOUT, [id]));
627
756
  }, MODULE_LOAD_TIMEOUT_TIMER);
628
757
  }).finally(() => {
758
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
629
759
  clearTimeout(timer);
630
760
  });
631
761
  const moduleDef = {
@@ -637,21 +767,23 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
637
767
  }
638
768
  };
639
769
  this.namedDefineRegistry.set(id, moduleDef);
770
+ } else if (process.env.NODE_ENV !== 'production' && hasConsole) {
771
+ // eslint-disable-next-line lwr/no-unguarded-apis
772
+ console.warn(MODULE_ALREADY_LOADED.message, id);
640
773
  }
641
774
  });
642
- if (alreadyRegistered.length) {
643
- throw new LoaderError(MODULE_ALREADY_LOADED, [alreadyRegistered.join(", ")]);
644
- }
645
775
  }
646
776
  getImportMetadataResolver() {
647
777
  return this.resolver;
648
778
  }
779
+ // Returns an existing module record by the resolvedId or aliased id
649
780
  getExistingModuleRecord(resolvedId, aliasId) {
650
781
  const moduleRecord = this.moduleRegistry.get(resolvedId);
651
782
  if (moduleRecord) {
652
783
  this.storeModuleAlias(aliasId, resolvedId);
653
784
  return moduleRecord;
654
785
  }
786
+ // Check if this is a known alias
655
787
  if (resolvedId !== aliasId) {
656
788
  const alias = this.aliases.get(aliasId);
657
789
  if (alias) {
@@ -664,20 +796,24 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
664
796
  return moduleRecord;
665
797
  }
666
798
  getModuleRecord(resolvedId, id) {
799
+ // Look for an existing record
667
800
  const existingRecord = this.getExistingModuleRecord(resolvedId, id);
668
801
  if (existingRecord) {
802
+ // return existing
669
803
  return existingRecord;
670
804
  }
805
+ // Create a new Module Record
671
806
  const instantiation = this.getModuleDef(resolvedId, id);
672
- const dependencyRecords = instantiation.then((moduleDef) => {
807
+ const dependencyRecords = instantiation.then(moduleDef => {
673
808
  const dependencies = moduleDef.dependencies;
674
- const filtered = dependencies.map((dep) => {
675
- if (dep === "exports") {
809
+ // get dep and filter out exports
810
+ const filtered = dependencies.map(dep => {
811
+ if (dep === 'exports') {
676
812
  return;
677
813
  }
678
- invariant(dep !== "require", NO_AMD_REQUIRE);
814
+ invariant(dep !== 'require', NO_AMD_REQUIRE);
679
815
  return this.getModuleDependencyRecord.call(this, dep);
680
- }).filter((depRecord) => depRecord !== void 0);
816
+ }).filter(depRecord => depRecord !== undefined);
681
817
  return Promise.all(filtered);
682
818
  });
683
819
  const newModuleRecord = {
@@ -696,9 +832,11 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
696
832
  if (aliasId !== resolvedId) {
697
833
  if (!this.aliases.has(aliasId)) {
698
834
  this.aliases.set(aliasId, resolvedId);
699
- } else if (hasConsole) {
835
+ } else if (process.env.NODE_ENV !== 'production' && hasConsole) {
836
+ // Warn the user if they were not aliasing to the resolvedId
700
837
  const currentResolvedId = this.aliases.get(aliasId);
701
838
  if (currentResolvedId !== resolvedId) {
839
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
702
840
  console.warn(`Alias update attempt: ${aliasId}=>${currentResolvedId}, ${resolvedId}`);
703
841
  }
704
842
  }
@@ -708,10 +846,12 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
708
846
  const resolvedDepId = await this.resolve(dependency);
709
847
  return this.getModuleRecord(resolvedDepId, dependency);
710
848
  }
849
+ // execute the "top-level code" (the code outside of functions) of a module
711
850
  async topLevelEvaluation(moduleRecord) {
712
851
  await this.instantiateAll(moduleRecord, {});
713
852
  return this.evaluateModule(moduleRecord, {});
714
853
  }
854
+ // Returns a promise when a module and all of it's dependencies have finished instantiation
715
855
  async instantiateAll(moduleRecord, instantiatedMap) {
716
856
  if (!instantiatedMap[moduleRecord.id]) {
717
857
  instantiatedMap[moduleRecord.id] = true;
@@ -719,6 +859,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
719
859
  if (dependencyModuleRecords) {
720
860
  for (let i = 0; i < dependencyModuleRecords.length; i++) {
721
861
  const depRecord = dependencyModuleRecords[i];
862
+ // eslint-disable-next-line no-await-in-loop
722
863
  await this.instantiateAll(depRecord, instantiatedMap);
723
864
  }
724
865
  }
@@ -728,24 +869,32 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
728
869
  const dependencyModuleRecords = await moduleRecord.dependencyRecords;
729
870
  if (dependencyModuleRecords.length > 0) {
730
871
  evaluationMap[moduleRecord.id] = true;
872
+ // evaluate dependencies first
731
873
  await this.evaluateModuleDependencies(dependencyModuleRecords, evaluationMap);
732
874
  }
733
875
  const {
734
876
  exporter,
735
877
  dependencies
736
878
  } = await moduleRecord.instantiation;
879
+ // The exports object automatically gets filled in by the exporter evaluation
737
880
  const exports = {};
738
- const depsMapped = await Promise.all(dependencies.map(async (dep) => {
739
- if (dep === "exports") {
881
+ const depsMapped = await Promise.all(dependencies.map(async dep => {
882
+ if (dep === 'exports') {
740
883
  return exports;
741
884
  }
742
885
  const resolvedDepId = await this.resolve(dep);
743
- const moduleRecord2 = this.moduleRegistry.get(resolvedDepId);
744
- if (!moduleRecord2) {
886
+ const moduleRecord = this.moduleRegistry.get(resolvedDepId);
887
+ if (!moduleRecord) {
745
888
  throw new LoaderError(FAILED_DEP, [resolvedDepId]);
746
889
  }
747
- const module = moduleRecord2.module;
748
- if (!moduleRecord2.evaluated) {
890
+ const module = moduleRecord.module;
891
+ /**
892
+ * Circular dependencies are handled properly when named exports are used,
893
+ * however, for default exports there is a bug: https://github.com/rollup/rollup/issues/3384
894
+ *
895
+ * The workaround below applies for circular dependencies (!moduleRecord.evaluated)
896
+ */
897
+ if (!moduleRecord.evaluated) {
749
898
  return this.getCircularDependencyWrapper(module);
750
899
  }
751
900
  if (module) {
@@ -753,25 +902,36 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
753
902
  }
754
903
  throw new LoaderError(FAILED_DEP, [resolvedDepId]);
755
904
  }));
905
+ // 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
756
906
  if (moduleRecord.evaluated) {
757
907
  return moduleRecord.module;
758
908
  }
909
+ // evaluates the module function
759
910
  let moduleDefault = exporter(...depsMapped);
760
- if (moduleDefault !== void 0) {
911
+ // value is returned from exporter, then we are not using named exports
912
+ if (moduleDefault !== undefined) {
761
913
  moduleDefault = {
762
914
  default: moduleDefault
763
915
  };
764
- Object.defineProperty(moduleDefault, "__defaultInterop", {
916
+ // __defaultInterop is ONLY used to support backwards compatibility
917
+ // of importing default exports the "wrong" way (when not using named exports).
918
+ // See https://github.com/salesforce-experience-platform-emu/lwr/pull/816
919
+ Object.defineProperty(moduleDefault, '__defaultInterop', {
765
920
  value: true
766
921
  });
767
- } else {
922
+ }
923
+ // if no return value, then we are using the exports object
924
+ else {
925
+ // handle only default export with Rollup forced named exports
768
926
  if (this.isNamedExportDefaultOnly(exports)) {
769
- Object.defineProperty(exports, "__useDefault", {
927
+ Object.defineProperty(exports, '__useDefault', {
770
928
  value: true
771
929
  });
772
930
  }
773
931
  }
774
932
  const moduleExports = moduleDefault || exports;
933
+ // update the module record
934
+ // copy over enumerable public methods to module
775
935
  for (const key in moduleExports) {
776
936
  Object.defineProperty(moduleRecord.module, key, {
777
937
  enumerable: true,
@@ -783,18 +943,19 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
783
943
  }
784
944
  });
785
945
  }
946
+ // copy non-enumerable to module
786
947
  if (moduleExports.__useDefault) {
787
- Object.defineProperty(moduleRecord.module, "__useDefault", {
948
+ Object.defineProperty(moduleRecord.module, '__useDefault', {
788
949
  value: true
789
950
  });
790
951
  }
791
952
  if (moduleExports.__defaultInterop) {
792
- Object.defineProperty(moduleRecord.module, "__defaultInterop", {
953
+ Object.defineProperty(moduleRecord.module, '__defaultInterop', {
793
954
  value: true
794
955
  });
795
956
  }
796
957
  if (moduleExports.__esModule) {
797
- Object.defineProperty(moduleRecord.module, "__esModule", {
958
+ Object.defineProperty(moduleRecord.module, '__esModule', {
798
959
  value: true
799
960
  });
800
961
  }
@@ -802,9 +963,12 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
802
963
  Object.freeze(moduleRecord.module);
803
964
  return moduleRecord.module;
804
965
  }
966
+ // Determines if named exports module has only default export
805
967
  isNamedExportDefaultOnly(exports) {
806
- return exports !== void 0 && Object.getOwnPropertyNames(exports).length === 2 && Object.prototype.hasOwnProperty.call(exports, "default") && Object.prototype.hasOwnProperty.call(exports, "__esModule");
968
+ return exports !== undefined && Object.getOwnPropertyNames(exports).length === 2 && Object.prototype.hasOwnProperty.call(exports, 'default') && Object.prototype.hasOwnProperty.call(exports, '__esModule');
807
969
  }
970
+ // Wrap the dependency in a function that can be called and detected by __circular__ property.
971
+ // The LWC engine checks for __circular__ to detect circular dependencies.
808
972
  getCircularDependencyWrapper(module) {
809
973
  const tmp = () => {
810
974
  return module.__useDefault || module.__defaultInterop ? module.default : module;
@@ -817,13 +981,16 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
817
981
  const depRecord = dependencyModuleRecords[i];
818
982
  if (!depRecord.evaluated && !evaluationMap[depRecord.id]) {
819
983
  evaluationMap[depRecord.id] = true;
984
+ // eslint-disable-next-line no-await-in-loop
820
985
  await this.evaluateModule(depRecord, evaluationMap);
821
986
  }
822
987
  }
823
988
  }
824
989
  async getModuleDef(resolvedId, originalId) {
825
- this.lastDefine = void 0;
826
- const moduleName = !isUrl(resolvedId) ? resolvedId : originalId !== resolvedId ? originalId : void 0;
990
+ // reset lastDefine
991
+ this.lastDefine = undefined;
992
+ // the module name can be the resolved ID or the original ID if neither are URL's.
993
+ const moduleName = !isUrl(resolvedId) ? resolvedId : originalId !== resolvedId ? originalId : undefined;
827
994
  let moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
828
995
  if (moduleDef && moduleDef.external) {
829
996
  return moduleDef.external.moduleDefPromise;
@@ -831,7 +998,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
831
998
  if (moduleDef && moduleDef.defined) {
832
999
  return moduleDef;
833
1000
  }
834
- const parentUrl = this.resolver.getBaseUrl();
1001
+ const parentUrl = this.resolver.getBaseUrl(); // only support baseUrl for now
835
1002
  const specifier = moduleName || originalId;
836
1003
  this.profiler.logOperationStart({
837
1004
  id: MODULE_FETCH,
@@ -843,8 +1010,10 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
843
1010
  for (let i = 0; i < loadHooks.length; i++) {
844
1011
  const loadHook = loadHooks[i];
845
1012
  const response = loadHook(resolvedId, parentUrl);
846
- const result = isResponseAPromise(response) ? await evaluateLoadHook(resolvedId, response) : response;
847
- if (result === void 0) {
1013
+ const result = isResponseAPromise(response) ?
1014
+ // eslint-disable-next-line no-await-in-loop
1015
+ await evaluateLoadHook(resolvedId, response) : response;
1016
+ if (result === undefined) {
848
1017
  throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
849
1018
  }
850
1019
  if (result && result !== null) {
@@ -853,15 +1022,18 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
853
1022
  }
854
1023
  }
855
1024
  return false;
856
- }).then((result) => {
1025
+ }).then(result => {
857
1026
  if (result !== true && hasDocument) {
858
1027
  return loadModuleDef(resolvedId);
859
1028
  }
860
1029
  }).then(() => {
1030
+ // Attempt to retrieve the module definition by name first
861
1031
  moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
1032
+ // Fallback to the last loader.define call
862
1033
  if (!moduleDef) {
863
1034
  moduleDef = this.lastDefine;
864
1035
  }
1036
+ // This should not happen
865
1037
  if (!moduleDef) {
866
1038
  throw new LoaderError(FAIL_INSTANTIATE, [resolvedId]);
867
1039
  }
@@ -870,7 +1042,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
870
1042
  specifier
871
1043
  });
872
1044
  return moduleDef;
873
- }).catch((e) => {
1045
+ }).catch(e => {
874
1046
  this.profiler.logOperationStart({
875
1047
  id: MODULE_ERROR,
876
1048
  specifier
@@ -879,7 +1051,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
879
1051
  });
880
1052
  }
881
1053
  addLoaderPlugin(hooks) {
882
- if (typeof hooks !== "object") {
1054
+ if (typeof hooks !== 'object') {
883
1055
  throw new LoaderError(INVALID_HOOK);
884
1056
  }
885
1057
  const {
@@ -918,7 +1090,8 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
918
1090
  newUrl
919
1091
  });
920
1092
  } else {
921
- if (hasConsole) {
1093
+ if (process.env.NODE_ENV !== 'production' && hasConsole) {
1094
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
922
1095
  console.warn(`stale module detected ${name}, current URL:${oldUrl}, new URL:${newUrl}`);
923
1096
  }
924
1097
  }
@@ -931,17 +1104,23 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
931
1104
  }
932
1105
  }
933
1106
  }
1107
+
1108
+ /**
1109
+ * The LWR loader is inspired and borrows from the algorithms and native browser principles of https://github.com/systemjs/systemjs
1110
+ */
934
1111
  class Loader {
935
1112
  constructor(config) {
936
1113
  let baseUrl = config.baseUrl;
937
- const mappingEndpoint = config.endpoints ? config.endpoints.uris.mapping : void 0;
1114
+ const mappingEndpoint = config.endpoints ? config.endpoints.uris.mapping : undefined;
938
1115
  let profiler = config.profiler;
939
1116
  if (!mappingEndpoint) {
940
1117
  throw new LoaderError(NO_MAPPING_URL);
941
1118
  }
942
- config.endpoints.uris.mapping = mappingEndpoint.replace(/\/?$/, "/");
1119
+ // add a trailing slash, if it does not exist
1120
+ config.endpoints.uris.mapping = mappingEndpoint.replace(/\/?$/, '/');
943
1121
  if (baseUrl) {
944
- baseUrl = baseUrl.replace(/\/?$/, "/");
1122
+ // add a trailing slash, if it does not exist
1123
+ baseUrl = baseUrl.replace(/\/?$/, '/');
945
1124
  }
946
1125
  if (!baseUrl) {
947
1126
  baseUrl = getBaseUrl();
@@ -950,10 +1129,13 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
950
1129
  throw new LoaderError(NO_BASE_URL);
951
1130
  }
952
1131
  if (!profiler) {
1132
+ // default noop profiler
953
1133
  profiler = {
954
1134
  logOperationStart: () => {
1135
+ /* noop */
955
1136
  },
956
1137
  logOperationEnd: () => {
1138
+ /* noop */
957
1139
  }
958
1140
  };
959
1141
  }
@@ -962,44 +1144,87 @@ LWR.define("lwr/loader/v/0_9_0-alpha_8", ["exports"], function(exports) {
962
1144
  baseUrl,
963
1145
  profiler
964
1146
  }));
1147
+ // TODO: W-10539691 - temp workaround for LWR-Java -- remove once appId is implemented there
965
1148
  if (config.appMetadata && !config.appMetadata.appId) {
1149
+ // Parse the appId from the bootstrapModule
1150
+ // LWR-Java bootstrap module format: @lwr-bootstrap/my/app/v/0_0_1 -- my/app is the appId
966
1151
  const match = config.appMetadata.bootstrapModule.match(/@lwr-bootstrap\/(.+)\/v\/.+/);
967
1152
  const appId = match && match[1];
968
1153
  config.appMetadata.appId = appId;
969
1154
  }
1155
+ // TODO: https://github.com/salesforce-experience-platform-emu/lwr/issues/1087
970
1156
  this.services = Object.freeze({
971
1157
  addLoaderPlugin: this.registry.addLoaderPlugin.bind(this.registry),
972
1158
  handleStaleModule: this.registry.registerHandleStaleModuleHook.bind(this.registry),
973
1159
  appMetadata: config.appMetadata
974
1160
  });
975
1161
  }
1162
+ /**
1163
+ * Defines/registers a single named AMD module definition.
1164
+ *
1165
+ * @param {string} name The module name
1166
+ * @param {string[]} dependencies A list of module dependencies (module imports)
1167
+ * @param {Function} execute The function containing the module code. AKA exporter as it also returns the modules exports when executed
1168
+ * @return {void}
1169
+ */
976
1170
  define(name, dependencies, execute) {
977
- invariant(typeof name === "string", MISSING_NAME);
1171
+ invariant(typeof name === 'string', MISSING_NAME);
978
1172
  let ctor = execute;
979
1173
  let deps = dependencies;
980
- if (typeof deps === "function") {
1174
+ // Convert no dependencies form `define('name', function(){}, {});` to: `define('name', [], function(){}, {})`
1175
+ if (typeof deps === 'function') {
981
1176
  ctor = dependencies;
982
1177
  deps = [];
983
1178
  }
984
1179
  invariant(Array.isArray(deps), INVALID_DEPS);
985
1180
  this.registry.define(name, deps, ctor);
986
1181
  }
1182
+ /**
1183
+ * Retrieves/loads a module, returning it from the registry if it exists and fetching it if it doesn't.
1184
+ *
1185
+ * @param {string} id - A module identifier or URL
1186
+ * @param {string} importer - The versioned specifier of the module importer
1187
+ * Used when the ID is not versioned (eg: variable dynamic imports)
1188
+ * @return {Promise<Module>}
1189
+ */
987
1190
  async load(id, importer) {
988
1191
  return this.registry.load(id, importer);
989
1192
  }
1193
+ /**
1194
+ * 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).
1195
+ *
1196
+ * @param {string} id - A module identifier or URL
1197
+ * @return {boolean}
1198
+ */
990
1199
  has(id) {
991
1200
  return this.registry.has(id);
992
1201
  }
1202
+ /**
1203
+ * Resolves the module identifier or URL. Returns the module identifier if the moduleDefinition exists, or the full resolved URL if a URL is given.
1204
+ *
1205
+ * @param {string} id - A module identifier or URL
1206
+ * @param {string} importer - The versioned specifier of the module importer
1207
+ * Used when the ID is not versioned (eg: variable dynamic imports)
1208
+ * @return {string}
1209
+ */
993
1210
  async resolve(id, importer) {
994
1211
  return this.registry.resolve(id, importer);
995
1212
  }
996
1213
  async registerImportMappings(mappings, rootSpecifiers) {
997
1214
  this.registry.getImportMetadataResolver().registerImportMappings(mappings, rootSpecifiers);
998
1215
  }
1216
+ /**
1217
+ * Marks modules as "externally" loaded/provided (e.g. preloaded), so that the loader does not attempt to load them.
1218
+ *
1219
+ * @param modules - list of module identifiers
1220
+ */
999
1221
  registerExternalModules(modules) {
1000
1222
  this.registry.registerExternalModules(modules);
1001
1223
  }
1002
1224
  }
1225
+
1003
1226
  exports.Loader = Loader;
1004
- Object.defineProperty(exports, "__esModule", {value: true});
1227
+
1228
+ Object.defineProperty(exports, '__esModule', { value: true });
1229
+
1005
1230
  });