@lwrjs/everywhere 0.9.0-alpha.2 → 0.9.0-alpha.21

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 (61) hide show
  1. package/README.md +2 -7
  2. package/build/__generated_site_amd_modules__/1/application/amd/l/en-US/ai/amd-bootstrap/configuration/ci/-/-/s/1b0754f98a1d222fca718deb5838c625/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-alpha_21/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_33_0/s/90a5f16131da45cef1653112862ca9dc/lwc.js +8969 -0
  5. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/everywhereAmd/v/0_9_0-alpha_21/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-alpha_21/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_2/s/a7fb654bda624ba7d02dcd76e8d1217c → 0_9_0-alpha_21/s/64c5a2bb3dcf1759c879fc87bf2fdaf6}/lwr_loader.js +360 -131
  8. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/metrics/v/0_9_0-alpha_21/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-alpha_21/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-alpha_21/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_2 → 0_9_0-alpha_21/lwr-error-shim.js} +1 -1
  12. package/build/__generated_site_amd_modules__/1/resource/amd/lwr-loader-shim.js/v/{0_9_0-alpha_2 → 0_9_0-alpha_21/lwr-loader-shim.js} +18 -17
  13. package/build/amd-client.js +1 -2
  14. package/build/assets/amd/lwr-everywhere-debug.js +36 -23
  15. package/build/assets/amd/lwr-everywhere-min.js +1 -1
  16. package/build/assets/amd/lwr-everywhere.js +36 -23
  17. package/build/assets/core/lwr-everywhere-debug.js +33 -20
  18. package/build/assets/core/lwr-everywhere-min.js +1 -1
  19. package/build/assets/core/lwr-everywhere.js +33 -20
  20. package/build/assets/esm/lwr-everywhere-debug.js +4 -7
  21. package/build/assets/esm/lwr-everywhere-min.js +1 -1
  22. package/build/assets/esm/lwr-everywhere.js +4 -7
  23. package/build/esm-client.js +1 -2
  24. package/build/generate.js +4 -3
  25. package/build/index.js +2 -2
  26. package/build/modules/@salesforce/lds-default-luvio/lds-default-luvio.d.ts +24 -0
  27. package/build/modules/@salesforce/lds-default-luvio/lds-default-luvio.js +60 -0
  28. package/build/modules/lwr/everywhere/everywhere.d.ts +1 -1
  29. package/build/modules/lwr/everywhere/everywhere.js +8 -6
  30. package/build/modules/lwr/everywhereAmd/everywhereAmd.d.ts +1 -1
  31. package/build/modules/lwr/everywhereAmd/everywhereAmd.js +9 -11
  32. package/build/modules/lwr/everywhereEsm/everywhereEsm.js +1 -2
  33. package/build/modules/lwr/host/host.js +23 -27
  34. package/build/modules/lwr/setupLDS/network.d.ts +3 -0
  35. package/build/modules/lwr/setupLDS/network.js +88 -0
  36. package/build/modules/lwr/setupLDS/setupLDS.d.ts +2 -0
  37. package/build/modules/lwr/setupLDS/setupLDS.js +12 -0
  38. package/build/modules/lwr/setupNodeLDS/network.d.ts +3 -0
  39. package/build/modules/lwr/setupNodeLDS/network.js +88 -0
  40. package/build/modules/lwr/setupNodeLDS/setupNodeLDS.d.ts +2 -0
  41. package/build/modules/lwr/setupNodeLDS/setupNodeLDS.js +14 -0
  42. package/build/modules/lwr/vault/vault.d.ts +1 -1
  43. package/build/modules/lwr/vault/vault.js +3 -1
  44. package/build/utils.d.ts +1 -8
  45. package/build/utils.js +1 -4
  46. package/package.json +15 -8
  47. package/src/amd-client.ts +1 -2
  48. package/src/esm-client.ts +2 -3
  49. package/src/generate.ts +4 -3
  50. package/src/index.ts +2 -2
  51. package/src/utils.ts +2 -13
  52. package/build/__generated_site_amd_modules__/1/application/amd/l/en-US/ai/amd-bootstrap/configuration/ci/-/-/s/68e51659d71a9691c09702509beecf4f/config.js +0 -10
  53. 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_2/s/c40e6caf07454ce13961de8ca76ab7f0/@lwrjs_app-service_amd-bootstrap_module_amd.js +0 -14
  54. 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
  55. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/everywhereAmd/v/0_9_0-alpha_2/s/e66806169480601930ec9cfca972815e/lwr_everywhereAmd.js +0 -48
  56. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/init/v/0_9_0-alpha_2/s/6258bcb20cc2d5d6a9f3c5a6f9d0acaf/lwr_init.js +0 -58
  57. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/metrics/v/0_9_0-alpha_2/s/dfbc827104d50ff7d16b59c9d0e06aca/lwr_metrics.js +0 -56
  58. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/profiler/v/0_9_0-alpha_2/s/5a10236d8c52bc9f6dee22875cd7016d/lwr_profiler.js +0 -51
  59. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/vault/v/0_9_0-alpha_2/s/6cbce1f9b7e815ee862b26f37ff4c76e/lwr_vault.js +0 -13
  60. package/build/__generated_site_amd_modules__/en-US/index.html +0 -26
  61. package/build/__generated_site_amd_modules__/index.html +0 -26
@@ -1,11 +1,21 @@
1
- LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
2
- "use strict";
1
+ LWR.define('lwr/loader/v/0_9_0-alpha_21', ['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-alpha.21 */
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_2", ["exports"], function(exports) {
15
25
  super();
16
26
  this.message = generateErrorMessage(errorInfo, errorArgs);
17
27
  }
28
+ /*LWC compiler v2.33.0*/
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_2", ["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: {0}'
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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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_2", ["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,9 +737,14 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["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
746
  const alreadyRegistered = [];
617
- modules.map((id) => {
747
+ modules.map(id => {
618
748
  if (this.namedDefineRegistry.has(id)) {
619
749
  alreadyRegistered.push(id);
620
750
  } else {
@@ -622,10 +752,13 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
622
752
  let timer;
623
753
  const moduleDefPromise = new Promise((resolve, reject) => {
624
754
  resolveExternal = resolve;
755
+ // watch the external for timeout
756
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
625
757
  timer = setTimeout(() => {
626
758
  reject(new LoaderError(MODULE_LOAD_TIMEOUT, [id]));
627
759
  }, MODULE_LOAD_TIMEOUT_TIMER);
628
760
  }).finally(() => {
761
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
629
762
  clearTimeout(timer);
630
763
  });
631
764
  const moduleDef = {
@@ -639,19 +772,22 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
639
772
  this.namedDefineRegistry.set(id, moduleDef);
640
773
  }
641
774
  });
775
+ // throw error for modules that were already registered
642
776
  if (alreadyRegistered.length) {
643
- throw new LoaderError(MODULE_ALREADY_LOADED, [alreadyRegistered.join(", ")]);
777
+ throw new LoaderError(MODULE_ALREADY_LOADED, [alreadyRegistered.join(', ')]);
644
778
  }
645
779
  }
646
780
  getImportMetadataResolver() {
647
781
  return this.resolver;
648
782
  }
783
+ // Returns an existing module record by the resolvedId or aliased id
649
784
  getExistingModuleRecord(resolvedId, aliasId) {
650
785
  const moduleRecord = this.moduleRegistry.get(resolvedId);
651
786
  if (moduleRecord) {
652
787
  this.storeModuleAlias(aliasId, resolvedId);
653
788
  return moduleRecord;
654
789
  }
790
+ // Check if this is a known alias
655
791
  if (resolvedId !== aliasId) {
656
792
  const alias = this.aliases.get(aliasId);
657
793
  if (alias) {
@@ -664,20 +800,24 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
664
800
  return moduleRecord;
665
801
  }
666
802
  getModuleRecord(resolvedId, id) {
803
+ // Look for an existing record
667
804
  const existingRecord = this.getExistingModuleRecord(resolvedId, id);
668
805
  if (existingRecord) {
806
+ // return existing
669
807
  return existingRecord;
670
808
  }
809
+ // Create a new Module Record
671
810
  const instantiation = this.getModuleDef(resolvedId, id);
672
- const dependencyRecords = instantiation.then((moduleDef) => {
811
+ const dependencyRecords = instantiation.then(moduleDef => {
673
812
  const dependencies = moduleDef.dependencies;
674
- const filtered = dependencies.map((dep) => {
675
- if (dep === "exports") {
813
+ // get dep and filter out exports
814
+ const filtered = dependencies.map(dep => {
815
+ if (dep === 'exports') {
676
816
  return;
677
817
  }
678
- invariant(dep !== "require", NO_AMD_REQUIRE);
818
+ invariant(dep !== 'require', NO_AMD_REQUIRE);
679
819
  return this.getModuleDependencyRecord.call(this, dep);
680
- }).filter((depRecord) => depRecord !== void 0);
820
+ }).filter(depRecord => depRecord !== undefined);
681
821
  return Promise.all(filtered);
682
822
  });
683
823
  const newModuleRecord = {
@@ -696,9 +836,11 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
696
836
  if (aliasId !== resolvedId) {
697
837
  if (!this.aliases.has(aliasId)) {
698
838
  this.aliases.set(aliasId, resolvedId);
699
- } else if (hasConsole) {
839
+ } else if (process.env.NODE_ENV !== 'production' && hasConsole) {
840
+ // Warn the user if they were not aliasing to the resolvedId
700
841
  const currentResolvedId = this.aliases.get(aliasId);
701
842
  if (currentResolvedId !== resolvedId) {
843
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
702
844
  console.warn(`Alias update attempt: ${aliasId}=>${currentResolvedId}, ${resolvedId}`);
703
845
  }
704
846
  }
@@ -708,10 +850,12 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
708
850
  const resolvedDepId = await this.resolve(dependency);
709
851
  return this.getModuleRecord(resolvedDepId, dependency);
710
852
  }
853
+ // execute the "top-level code" (the code outside of functions) of a module
711
854
  async topLevelEvaluation(moduleRecord) {
712
855
  await this.instantiateAll(moduleRecord, {});
713
856
  return this.evaluateModule(moduleRecord, {});
714
857
  }
858
+ // Returns a promise when a module and all of it's dependencies have finished instantiation
715
859
  async instantiateAll(moduleRecord, instantiatedMap) {
716
860
  if (!instantiatedMap[moduleRecord.id]) {
717
861
  instantiatedMap[moduleRecord.id] = true;
@@ -719,6 +863,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
719
863
  if (dependencyModuleRecords) {
720
864
  for (let i = 0; i < dependencyModuleRecords.length; i++) {
721
865
  const depRecord = dependencyModuleRecords[i];
866
+ // eslint-disable-next-line no-await-in-loop
722
867
  await this.instantiateAll(depRecord, instantiatedMap);
723
868
  }
724
869
  }
@@ -728,24 +873,32 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
728
873
  const dependencyModuleRecords = await moduleRecord.dependencyRecords;
729
874
  if (dependencyModuleRecords.length > 0) {
730
875
  evaluationMap[moduleRecord.id] = true;
876
+ // evaluate dependencies first
731
877
  await this.evaluateModuleDependencies(dependencyModuleRecords, evaluationMap);
732
878
  }
733
879
  const {
734
880
  exporter,
735
881
  dependencies
736
882
  } = await moduleRecord.instantiation;
883
+ // The exports object automatically gets filled in by the exporter evaluation
737
884
  const exports = {};
738
- const depsMapped = await Promise.all(dependencies.map(async (dep) => {
739
- if (dep === "exports") {
885
+ const depsMapped = await Promise.all(dependencies.map(async dep => {
886
+ if (dep === 'exports') {
740
887
  return exports;
741
888
  }
742
889
  const resolvedDepId = await this.resolve(dep);
743
- const moduleRecord2 = this.moduleRegistry.get(resolvedDepId);
744
- if (!moduleRecord2) {
890
+ const moduleRecord = this.moduleRegistry.get(resolvedDepId);
891
+ if (!moduleRecord) {
745
892
  throw new LoaderError(FAILED_DEP, [resolvedDepId]);
746
893
  }
747
- const module = moduleRecord2.module;
748
- if (!moduleRecord2.evaluated) {
894
+ const module = moduleRecord.module;
895
+ /**
896
+ * Circular dependencies are handled properly when named exports are used,
897
+ * however, for default exports there is a bug: https://github.com/rollup/rollup/issues/3384
898
+ *
899
+ * The workaround below applies for circular dependencies (!moduleRecord.evaluated)
900
+ */
901
+ if (!moduleRecord.evaluated) {
749
902
  return this.getCircularDependencyWrapper(module);
750
903
  }
751
904
  if (module) {
@@ -753,25 +906,36 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
753
906
  }
754
907
  throw new LoaderError(FAILED_DEP, [resolvedDepId]);
755
908
  }));
909
+ // 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
910
  if (moduleRecord.evaluated) {
757
911
  return moduleRecord.module;
758
912
  }
913
+ // evaluates the module function
759
914
  let moduleDefault = exporter(...depsMapped);
760
- if (moduleDefault !== void 0) {
915
+ // value is returned from exporter, then we are not using named exports
916
+ if (moduleDefault !== undefined) {
761
917
  moduleDefault = {
762
918
  default: moduleDefault
763
919
  };
764
- Object.defineProperty(moduleDefault, "__defaultInterop", {
920
+ // __defaultInterop is ONLY used to support backwards compatibility
921
+ // of importing default exports the "wrong" way (when not using named exports).
922
+ // See https://github.com/salesforce-experience-platform-emu/lwr/pull/816
923
+ Object.defineProperty(moduleDefault, '__defaultInterop', {
765
924
  value: true
766
925
  });
767
- } else {
926
+ }
927
+ // if no return value, then we are using the exports object
928
+ else {
929
+ // handle only default export with Rollup forced named exports
768
930
  if (this.isNamedExportDefaultOnly(exports)) {
769
- Object.defineProperty(exports, "__useDefault", {
931
+ Object.defineProperty(exports, '__useDefault', {
770
932
  value: true
771
933
  });
772
934
  }
773
935
  }
774
936
  const moduleExports = moduleDefault || exports;
937
+ // update the module record
938
+ // copy over enumerable public methods to module
775
939
  for (const key in moduleExports) {
776
940
  Object.defineProperty(moduleRecord.module, key, {
777
941
  enumerable: true,
@@ -783,18 +947,19 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
783
947
  }
784
948
  });
785
949
  }
950
+ // copy non-enumerable to module
786
951
  if (moduleExports.__useDefault) {
787
- Object.defineProperty(moduleRecord.module, "__useDefault", {
952
+ Object.defineProperty(moduleRecord.module, '__useDefault', {
788
953
  value: true
789
954
  });
790
955
  }
791
956
  if (moduleExports.__defaultInterop) {
792
- Object.defineProperty(moduleRecord.module, "__defaultInterop", {
957
+ Object.defineProperty(moduleRecord.module, '__defaultInterop', {
793
958
  value: true
794
959
  });
795
960
  }
796
961
  if (moduleExports.__esModule) {
797
- Object.defineProperty(moduleRecord.module, "__esModule", {
962
+ Object.defineProperty(moduleRecord.module, '__esModule', {
798
963
  value: true
799
964
  });
800
965
  }
@@ -802,9 +967,12 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
802
967
  Object.freeze(moduleRecord.module);
803
968
  return moduleRecord.module;
804
969
  }
970
+ // Determines if named exports module has only default export
805
971
  isNamedExportDefaultOnly(exports) {
806
- return exports !== void 0 && Object.getOwnPropertyNames(exports).length === 2 && Object.prototype.hasOwnProperty.call(exports, "default") && Object.prototype.hasOwnProperty.call(exports, "__esModule");
972
+ return exports !== undefined && Object.getOwnPropertyNames(exports).length === 2 && Object.prototype.hasOwnProperty.call(exports, 'default') && Object.prototype.hasOwnProperty.call(exports, '__esModule');
807
973
  }
974
+ // Wrap the dependency in a function that can be called and detected by __circular__ property.
975
+ // The LWC engine checks for __circular__ to detect circular dependencies.
808
976
  getCircularDependencyWrapper(module) {
809
977
  const tmp = () => {
810
978
  return module.__useDefault || module.__defaultInterop ? module.default : module;
@@ -817,13 +985,16 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
817
985
  const depRecord = dependencyModuleRecords[i];
818
986
  if (!depRecord.evaluated && !evaluationMap[depRecord.id]) {
819
987
  evaluationMap[depRecord.id] = true;
988
+ // eslint-disable-next-line no-await-in-loop
820
989
  await this.evaluateModule(depRecord, evaluationMap);
821
990
  }
822
991
  }
823
992
  }
824
993
  async getModuleDef(resolvedId, originalId) {
825
- this.lastDefine = void 0;
826
- const moduleName = !isUrl(resolvedId) ? resolvedId : originalId !== resolvedId ? originalId : void 0;
994
+ // reset lastDefine
995
+ this.lastDefine = undefined;
996
+ // the module name can be the resolved ID or the original ID if neither are URL's.
997
+ const moduleName = !isUrl(resolvedId) ? resolvedId : originalId !== resolvedId ? originalId : undefined;
827
998
  let moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
828
999
  if (moduleDef && moduleDef.external) {
829
1000
  return moduleDef.external.moduleDefPromise;
@@ -831,7 +1002,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
831
1002
  if (moduleDef && moduleDef.defined) {
832
1003
  return moduleDef;
833
1004
  }
834
- const parentUrl = this.resolver.getBaseUrl();
1005
+ const parentUrl = this.resolver.getBaseUrl(); // only support baseUrl for now
835
1006
  const specifier = moduleName || originalId;
836
1007
  this.profiler.logOperationStart({
837
1008
  id: MODULE_FETCH,
@@ -843,8 +1014,10 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
843
1014
  for (let i = 0; i < loadHooks.length; i++) {
844
1015
  const loadHook = loadHooks[i];
845
1016
  const response = loadHook(resolvedId, parentUrl);
846
- const result = isResponseAPromise(response) ? await evaluateLoadHook(resolvedId, response) : response;
847
- if (result === void 0) {
1017
+ const result = isResponseAPromise(response) ?
1018
+ // eslint-disable-next-line no-await-in-loop
1019
+ await evaluateLoadHook(resolvedId, response) : response;
1020
+ if (result === undefined) {
848
1021
  throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
849
1022
  }
850
1023
  if (result && result !== null) {
@@ -853,15 +1026,18 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
853
1026
  }
854
1027
  }
855
1028
  return false;
856
- }).then((result) => {
1029
+ }).then(result => {
857
1030
  if (result !== true && hasDocument) {
858
1031
  return loadModuleDef(resolvedId);
859
1032
  }
860
1033
  }).then(() => {
1034
+ // Attempt to retrieve the module definition by name first
861
1035
  moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
1036
+ // Fallback to the last loader.define call
862
1037
  if (!moduleDef) {
863
1038
  moduleDef = this.lastDefine;
864
1039
  }
1040
+ // This should not happen
865
1041
  if (!moduleDef) {
866
1042
  throw new LoaderError(FAIL_INSTANTIATE, [resolvedId]);
867
1043
  }
@@ -870,7 +1046,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
870
1046
  specifier
871
1047
  });
872
1048
  return moduleDef;
873
- }).catch((e) => {
1049
+ }).catch(e => {
874
1050
  this.profiler.logOperationStart({
875
1051
  id: MODULE_ERROR,
876
1052
  specifier
@@ -879,7 +1055,7 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
879
1055
  });
880
1056
  }
881
1057
  addLoaderPlugin(hooks) {
882
- if (typeof hooks !== "object") {
1058
+ if (typeof hooks !== 'object') {
883
1059
  throw new LoaderError(INVALID_HOOK);
884
1060
  }
885
1061
  const {
@@ -918,7 +1094,8 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
918
1094
  newUrl
919
1095
  });
920
1096
  } else {
921
- if (hasConsole) {
1097
+ if (process.env.NODE_ENV !== 'production' && hasConsole) {
1098
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
922
1099
  console.warn(`stale module detected ${name}, current URL:${oldUrl}, new URL:${newUrl}`);
923
1100
  }
924
1101
  }
@@ -931,17 +1108,23 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
931
1108
  }
932
1109
  }
933
1110
  }
1111
+
1112
+ /**
1113
+ * The LWR loader is inspired and borrows from the algorithms and native browser principles of https://github.com/systemjs/systemjs
1114
+ */
934
1115
  class Loader {
935
1116
  constructor(config) {
936
1117
  let baseUrl = config.baseUrl;
937
- const mappingEndpoint = config.endpoints ? config.endpoints.uris.mapping : void 0;
1118
+ const mappingEndpoint = config.endpoints ? config.endpoints.uris.mapping : undefined;
938
1119
  let profiler = config.profiler;
939
1120
  if (!mappingEndpoint) {
940
1121
  throw new LoaderError(NO_MAPPING_URL);
941
1122
  }
942
- config.endpoints.uris.mapping = mappingEndpoint.replace(/\/?$/, "/");
1123
+ // add a trailing slash, if it does not exist
1124
+ config.endpoints.uris.mapping = mappingEndpoint.replace(/\/?$/, '/');
943
1125
  if (baseUrl) {
944
- baseUrl = baseUrl.replace(/\/?$/, "/");
1126
+ // add a trailing slash, if it does not exist
1127
+ baseUrl = baseUrl.replace(/\/?$/, '/');
945
1128
  }
946
1129
  if (!baseUrl) {
947
1130
  baseUrl = getBaseUrl();
@@ -950,10 +1133,13 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
950
1133
  throw new LoaderError(NO_BASE_URL);
951
1134
  }
952
1135
  if (!profiler) {
1136
+ // default noop profiler
953
1137
  profiler = {
954
1138
  logOperationStart: () => {
1139
+ /* noop */
955
1140
  },
956
1141
  logOperationEnd: () => {
1142
+ /* noop */
957
1143
  }
958
1144
  };
959
1145
  }
@@ -962,44 +1148,87 @@ LWR.define("lwr/loader/v/0_9_0-alpha_2", ["exports"], function(exports) {
962
1148
  baseUrl,
963
1149
  profiler
964
1150
  }));
1151
+ // TODO: W-10539691 - temp workaround for LWR-Java -- remove once appId is implemented there
965
1152
  if (config.appMetadata && !config.appMetadata.appId) {
1153
+ // Parse the appId from the bootstrapModule
1154
+ // LWR-Java bootstrap module format: @lwr-bootstrap/my/app/v/0_0_1 -- my/app is the appId
966
1155
  const match = config.appMetadata.bootstrapModule.match(/@lwr-bootstrap\/(.+)\/v\/.+/);
967
1156
  const appId = match && match[1];
968
1157
  config.appMetadata.appId = appId;
969
1158
  }
1159
+ // TODO: https://github.com/salesforce-experience-platform-emu/lwr/issues/1087
970
1160
  this.services = Object.freeze({
971
1161
  addLoaderPlugin: this.registry.addLoaderPlugin.bind(this.registry),
972
1162
  handleStaleModule: this.registry.registerHandleStaleModuleHook.bind(this.registry),
973
1163
  appMetadata: config.appMetadata
974
1164
  });
975
1165
  }
1166
+ /**
1167
+ * Defines/registers a single named AMD module definition.
1168
+ *
1169
+ * @param {string} name The module name
1170
+ * @param {string[]} dependencies A list of module dependencies (module imports)
1171
+ * @param {Function} execute The function containing the module code. AKA exporter as it also returns the modules exports when executed
1172
+ * @return {void}
1173
+ */
976
1174
  define(name, dependencies, execute) {
977
- invariant(typeof name === "string", MISSING_NAME);
1175
+ invariant(typeof name === 'string', MISSING_NAME);
978
1176
  let ctor = execute;
979
1177
  let deps = dependencies;
980
- if (typeof deps === "function") {
1178
+ // Convert no dependencies form `define('name', function(){}, {});` to: `define('name', [], function(){}, {})`
1179
+ if (typeof deps === 'function') {
981
1180
  ctor = dependencies;
982
1181
  deps = [];
983
1182
  }
984
1183
  invariant(Array.isArray(deps), INVALID_DEPS);
985
1184
  this.registry.define(name, deps, ctor);
986
1185
  }
1186
+ /**
1187
+ * Retrieves/loads a module, returning it from the registry if it exists and fetching it if it doesn't.
1188
+ *
1189
+ * @param {string} id - A module identifier or URL
1190
+ * @param {string} importer - The versioned specifier of the module importer
1191
+ * Used when the ID is not versioned (eg: variable dynamic imports)
1192
+ * @return {Promise<Module>}
1193
+ */
987
1194
  async load(id, importer) {
988
1195
  return this.registry.load(id, importer);
989
1196
  }
1197
+ /**
1198
+ * 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).
1199
+ *
1200
+ * @param {string} id - A module identifier or URL
1201
+ * @return {boolean}
1202
+ */
990
1203
  has(id) {
991
1204
  return this.registry.has(id);
992
1205
  }
1206
+ /**
1207
+ * Resolves the module identifier or URL. Returns the module identifier if the moduleDefinition exists, or the full resolved URL if a URL is given.
1208
+ *
1209
+ * @param {string} id - A module identifier or URL
1210
+ * @param {string} importer - The versioned specifier of the module importer
1211
+ * Used when the ID is not versioned (eg: variable dynamic imports)
1212
+ * @return {string}
1213
+ */
993
1214
  async resolve(id, importer) {
994
1215
  return this.registry.resolve(id, importer);
995
1216
  }
996
1217
  async registerImportMappings(mappings, rootSpecifiers) {
997
1218
  this.registry.getImportMetadataResolver().registerImportMappings(mappings, rootSpecifiers);
998
1219
  }
1220
+ /**
1221
+ * Marks modules as "externally" loaded/provided (e.g. preloaded), so that the loader does not attempt to load them.
1222
+ *
1223
+ * @param modules - list of module identifiers
1224
+ */
999
1225
  registerExternalModules(modules) {
1000
1226
  this.registry.registerExternalModules(modules);
1001
1227
  }
1002
1228
  }
1229
+
1003
1230
  exports.Loader = Loader;
1004
- Object.defineProperty(exports, "__esModule", {value: true});
1231
+
1232
+ Object.defineProperty(exports, '__esModule', { value: true });
1233
+
1005
1234
  });