@lwrjs/loader 0.13.0-alpha.2 → 0.13.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 (119) hide show
  1. package/build/assets/prod/lwr-error-shim.js +2 -2
  2. package/build/assets/prod/lwr-loader-shim-legacy.bundle.js +34 -29
  3. package/build/assets/prod/lwr-loader-shim-legacy.bundle.min.js +3 -3
  4. package/build/assets/prod/lwr-loader-shim-legacy.js +21 -16
  5. package/build/assets/prod/lwr-loader-shim.bundle.js +45 -23
  6. package/build/assets/prod/lwr-loader-shim.bundle.min.js +3 -3
  7. package/build/assets/prod/lwr-loader-shim.js +27 -12
  8. package/build/bundle/prod/lwr/esmLoader/esmLoader.js +1 -1
  9. package/build/cjs/index.cjs +28 -1
  10. package/build/cjs/modules/lwr/esmLoader/esmLoader.cjs +2 -2
  11. package/build/cjs/modules/lwr/esmLoader/importResolver.cjs +0 -17
  12. package/build/cjs/modules/lwr/esmLoader/importResolverLegacy.cjs +1 -18
  13. package/build/cjs/modules/lwr/loader/errors/messages.cjs +7 -1
  14. package/build/cjs/modules/lwr/loader/errors/reportError.cjs +1 -2
  15. package/build/cjs/modules/lwr/loader/hooks/moduleInvalidation.cjs +2 -3
  16. package/build/cjs/modules/lwr/loader/hooks/resolveAndLoadHook.cjs +3 -4
  17. package/build/cjs/modules/lwr/loader/moduleRegistry/importMetadataResolver.cjs +7 -6
  18. package/build/cjs/modules/lwr/loader/moduleRegistry/moduleRegistry.cjs +8 -10
  19. package/build/cjs/modules/lwr/loader/moduleRegistry/scriptLoad.cjs +2 -2
  20. package/build/cjs/modules/lwr/loader/utils/url.cjs +1 -1
  21. package/build/cjs/modules/lwr/loaderLegacy/errors/messages.cjs +1 -1
  22. package/build/cjs/modules/lwr/loaderLegacy/errors/reportError.cjs +1 -2
  23. package/build/cjs/modules/lwr/loaderLegacy/hooks/moduleInvalidation.cjs +2 -3
  24. package/build/cjs/modules/lwr/loaderLegacy/hooks/resolveAndLoadHook.cjs +3 -4
  25. package/build/cjs/modules/lwr/loaderLegacy/importMap/dom.cjs +4 -4
  26. package/build/cjs/modules/lwr/loaderLegacy/importMap/importMap.cjs +2 -2
  27. package/build/cjs/modules/lwr/loaderLegacy/importMap/importMapResolver.cjs +1 -2
  28. package/build/cjs/modules/lwr/loaderLegacy/importMap/utils.cjs +1 -1
  29. package/build/cjs/modules/lwr/loaderLegacy/importResolver/importResolver.cjs +0 -17
  30. package/build/cjs/modules/lwr/loaderLegacy/moduleRegistry/moduleRegistry.cjs +7 -10
  31. package/build/cjs/modules/lwr/loaderLegacy/moduleRegistry/scriptLoad.cjs +2 -2
  32. package/build/cjs/modules/lwr/loaderLegacy/utils/url.cjs +1 -1
  33. package/build/cjs/package.d.cjs +0 -0
  34. package/build/cjs/types.cjs +5 -0
  35. package/build/error-shim/index.d.ts +2 -0
  36. package/build/error-shim/index.js +17 -0
  37. package/build/index.d.ts +1 -1
  38. package/build/index.js +28 -1
  39. package/build/modules/lwr/esmLoader/esmLoader.d.ts +6 -0
  40. package/build/modules/lwr/esmLoader/esmLoader.js +2 -2
  41. package/build/modules/lwr/esmLoader/importResolver.d.ts +17 -0
  42. package/build/modules/lwr/esmLoader/importResolver.js +47 -0
  43. package/build/modules/lwr/esmLoader/importResolverLegacy.d.ts +16 -0
  44. package/build/modules/lwr/esmLoader/importResolverLegacy.js +18 -0
  45. package/build/modules/lwr/loader/constants/constants.d.ts +2 -0
  46. package/build/modules/lwr/loader/constants/constants.js +2 -0
  47. package/build/modules/lwr/loader/errors/messages.d.ts +33 -0
  48. package/build/modules/lwr/loader/errors/messages.js +128 -0
  49. package/build/modules/lwr/loader/errors/reportError.d.ts +4 -0
  50. package/build/modules/lwr/loader/errors/reportError.js +9 -0
  51. package/build/modules/lwr/loader/errors/utils.d.ts +2 -0
  52. package/build/modules/lwr/loader/errors/utils.js +8 -0
  53. package/build/modules/lwr/loader/hooks/moduleInvalidation.d.ts +3 -0
  54. package/build/modules/lwr/loader/hooks/moduleInvalidation.js +19 -0
  55. package/build/modules/lwr/loader/hooks/resolveAndLoadHook.d.ts +7 -0
  56. package/build/modules/lwr/loader/hooks/resolveAndLoadHook.js +94 -0
  57. package/build/modules/lwr/loader/loader.d.ts +53 -0
  58. package/build/modules/lwr/loader/loader.js +18 -11
  59. package/build/modules/lwr/loader/moduleRegistry/importMetadataResolver.d.ts +44 -0
  60. package/build/modules/lwr/loader/moduleRegistry/importMetadataResolver.js +211 -0
  61. package/build/modules/lwr/loader/moduleRegistry/moduleRegistry.d.ts +47 -0
  62. package/build/modules/lwr/loader/moduleRegistry/moduleRegistry.js +530 -0
  63. package/build/modules/lwr/loader/moduleRegistry/scriptLoad.d.ts +3 -0
  64. package/build/modules/lwr/loader/moduleRegistry/scriptLoad.js +43 -0
  65. package/build/modules/lwr/loader/utils/dom.d.ts +4 -0
  66. package/build/modules/lwr/loader/utils/dom.js +6 -0
  67. package/build/modules/lwr/loader/utils/url.d.ts +28 -0
  68. package/build/modules/lwr/loader/utils/url.js +128 -0
  69. package/build/modules/lwr/loaderLegacy/constants/constants.d.ts +2 -0
  70. package/build/modules/lwr/loaderLegacy/constants/constants.js +2 -0
  71. package/build/modules/lwr/loaderLegacy/errors/messages.d.ts +30 -0
  72. package/build/modules/lwr/loaderLegacy/errors/messages.js +113 -0
  73. package/build/modules/lwr/loaderLegacy/errors/reportError.d.ts +4 -0
  74. package/build/modules/lwr/loaderLegacy/errors/reportError.js +9 -0
  75. package/build/modules/lwr/loaderLegacy/errors/utils.d.ts +2 -0
  76. package/build/modules/lwr/loaderLegacy/errors/utils.js +8 -0
  77. package/build/modules/lwr/loaderLegacy/hooks/moduleInvalidation.d.ts +3 -0
  78. package/build/modules/lwr/loaderLegacy/hooks/moduleInvalidation.js +19 -0
  79. package/build/modules/lwr/loaderLegacy/hooks/resolveAndLoadHook.d.ts +7 -0
  80. package/build/modules/lwr/loaderLegacy/hooks/resolveAndLoadHook.js +94 -0
  81. package/build/modules/lwr/loaderLegacy/importMap/dom.d.ts +10 -0
  82. package/build/modules/lwr/loaderLegacy/importMap/dom.js +63 -0
  83. package/build/modules/lwr/loaderLegacy/importMap/importMap.d.ts +22 -0
  84. package/build/modules/lwr/loaderLegacy/importMap/importMap.js +108 -0
  85. package/build/modules/lwr/loaderLegacy/importMap/importMapResolver.d.ts +8 -0
  86. package/build/modules/lwr/loaderLegacy/importMap/importMapResolver.js +11 -0
  87. package/build/modules/lwr/loaderLegacy/importMap/utils.d.ts +4 -0
  88. package/build/modules/lwr/loaderLegacy/importMap/utils.js +23 -0
  89. package/build/modules/lwr/loaderLegacy/importResolver/importResolver.d.ts +6 -0
  90. package/build/modules/lwr/loaderLegacy/importResolver/importResolver.js +2 -0
  91. package/build/modules/lwr/loaderLegacy/loaderLegacy.d.ts +57 -0
  92. package/build/modules/lwr/loaderLegacy/loaderLegacy.js +13 -13
  93. package/build/modules/lwr/loaderLegacy/moduleRegistry/moduleRegistry.d.ts +53 -0
  94. package/build/modules/lwr/loaderLegacy/moduleRegistry/moduleRegistry.js +544 -0
  95. package/build/modules/lwr/loaderLegacy/moduleRegistry/scriptLoad.d.ts +3 -0
  96. package/build/modules/lwr/loaderLegacy/moduleRegistry/scriptLoad.js +43 -0
  97. package/build/modules/lwr/loaderLegacy/utils/dom.d.ts +4 -0
  98. package/build/modules/lwr/loaderLegacy/utils/dom.js +6 -0
  99. package/build/modules/lwr/loaderLegacy/utils/url.d.ts +28 -0
  100. package/build/modules/lwr/loaderLegacy/utils/url.js +128 -0
  101. package/build/shim/constants.d.ts +2 -0
  102. package/build/shim/constants.js +2 -0
  103. package/build/shim/customInit.d.ts +4 -0
  104. package/build/shim/customInit.js +29 -0
  105. package/build/shim/index.d.ts +2 -0
  106. package/build/shim/index.js +9 -0
  107. package/build/shim/loader.d.ts +3 -0
  108. package/build/shim/loader.js +27 -0
  109. package/build/shim/shim.d.ts +31 -0
  110. package/build/shim/shim.js +194 -0
  111. package/build/shim-legacy/index.d.ts +2 -0
  112. package/build/shim-legacy/index.js +9 -0
  113. package/build/shim-legacy/loaderLegacy.d.ts +3 -0
  114. package/build/shim-legacy/loaderLegacy.js +29 -0
  115. package/build/shim-legacy/shimLegacy.d.ts +31 -0
  116. package/build/shim-legacy/shimLegacy.js +188 -0
  117. package/build/types.d.ts +56 -0
  118. package/build/types.js +2 -0
  119. package/package.json +9 -10
@@ -0,0 +1,530 @@
1
+ /* global console,process */
2
+ import { invariant, NO_AMD_REQUIRE, LoaderError, FAIL_INSTANTIATE, FAILED_DEP, UNRESOLVED, INVALID_HOOK, INVALID_LOADER_SERVICE_RESPONSE, MODULE_ALREADY_LOADED, MODULE_LOAD_TIMEOUT, EXPORTER_ERROR, } from '../errors/messages.js';
3
+ import { resolveIfNotPlainOrUrl, isUrl } from '../utils/url.js';
4
+ import { hasDocument, hasConsole } from '../utils/dom.js';
5
+ import { loadModuleDef } from './scriptLoad.js';
6
+ import { ImportMetadataResolver } from './importMetadataResolver.js';
7
+ import { evaluateHandleStaleModuleHooks } from '../hooks/moduleInvalidation.js';
8
+ import { evaluateLoadHookResponse, evaluateLoadHook, isResponseAPromise, } from '../hooks/resolveAndLoadHook.js';
9
+ import { MODULE_DEFINE, MODULE_ERROR, MODULE_FETCH, MODULE_DYNAMIC_LOAD } from 'lwr/metrics';
10
+ import { MODULE_LOAD_TIMEOUT_TIMER } from '../constants/constants.js';
11
+ export class ModuleRegistry {
12
+ constructor(config) {
13
+ // A registry for named AMD defines containing the *metadata* of AMD module
14
+ this.namedDefineRegistry = new Map();
15
+ // The evaluated module registry where the module identifier (name or URL?) is the key
16
+ this.moduleRegistry = new Map();
17
+ // Aliases of modules in the registry
18
+ this.aliases = new Map();
19
+ this.profiler = config.profiler;
20
+ this.resolver = new ImportMetadataResolver(config, this.importMetadataInvalidationCallback.bind(this));
21
+ }
22
+ async load(id, importer) {
23
+ const metadata = importer ? { importer } : {};
24
+ this.profiler.logOperationStart({
25
+ id: MODULE_DYNAMIC_LOAD,
26
+ specifier: id,
27
+ metadata,
28
+ });
29
+ const resolvedId = await this.resolve(id, importer);
30
+ const moduleRecord = await this.getModuleRecord(resolvedId, id);
31
+ if (moduleRecord.evaluated) {
32
+ return moduleRecord.module;
33
+ }
34
+ else {
35
+ if (!moduleRecord.evaluationPromise) {
36
+ moduleRecord.evaluationPromise = this.topLevelEvaluation(moduleRecord);
37
+ }
38
+ return moduleRecord.evaluationPromise;
39
+ }
40
+ }
41
+ async resolve(id, importer) {
42
+ const parentUrl = this.resolver.getBaseUrl(); // only support baseUrl for now
43
+ let resolved;
44
+ let aliasedId = id;
45
+ const resolveHooks = this.resolveHook;
46
+ if (resolveHooks) {
47
+ for (let i = 0; i < resolveHooks.length; i++) {
48
+ const resolveHook = resolveHooks[i];
49
+ const response = resolveHook(aliasedId, { parentUrl });
50
+ let result;
51
+ if (response || response === null) {
52
+ // eslint-disable-next-line no-await-in-loop
53
+ result = isResponseAPromise(response) ? await response : response;
54
+ }
55
+ if (!this.isValidResolveResponse(result)) {
56
+ throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
57
+ }
58
+ // if result is not null, attempt resolution
59
+ if (result !== null) {
60
+ if (typeof result === 'string') {
61
+ if (resolveIfNotPlainOrUrl(result, parentUrl)) {
62
+ // string response can't be a URL
63
+ throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
64
+ }
65
+ aliasedId = result; // the next hook will receive the new id
66
+ continue;
67
+ }
68
+ resolved =
69
+ result && result.url && (resolveIfNotPlainOrUrl(result.url, parentUrl) || result.url);
70
+ if (!resolved) {
71
+ throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
72
+ }
73
+ // Don't process any more hooks if we have resolved
74
+ break;
75
+ }
76
+ }
77
+ if (aliasedId !== id) {
78
+ // resolved module id is the aliased module if it has already been defined
79
+ if (!resolved && this.namedDefineRegistry.has(aliasedId)) {
80
+ return aliasedId;
81
+ }
82
+ else {
83
+ id = aliasedId;
84
+ }
85
+ }
86
+ }
87
+ if (!resolved) {
88
+ const resolvedOrPlain = resolveIfNotPlainOrUrl(id, parentUrl) || id;
89
+ // if module registry already has named module the resolved id is the plain id
90
+ if (this.moduleRegistry.has(resolvedOrPlain)) {
91
+ return resolvedOrPlain;
92
+ }
93
+ const resolvedUrl = this.resolver.resolveLocal(resolvedOrPlain);
94
+ if (resolvedUrl) {
95
+ // resolve to the bare specifier if conditions are met
96
+ if (this.namedDefineRegistry.has(resolvedOrPlain)) {
97
+ const namedDefineRecord = this.namedDefineRegistry.get(resolvedOrPlain);
98
+ if (namedDefineRecord.external || namedDefineRecord.defined) {
99
+ const record = this.moduleRegistry.get(resolvedUrl);
100
+ if (!record || !this.aliases.has(resolvedOrPlain)) {
101
+ return resolvedOrPlain;
102
+ }
103
+ }
104
+ }
105
+ return resolvedUrl;
106
+ }
107
+ if (this.namedDefineRegistry.has(resolvedOrPlain)) {
108
+ return resolvedOrPlain;
109
+ }
110
+ try {
111
+ resolved = await this.resolver.resolve(resolvedOrPlain);
112
+ }
113
+ catch (e) {
114
+ // defer to error handling below for unresolved
115
+ }
116
+ }
117
+ if (!resolved || !isUrl(resolved)) {
118
+ if (this.namedDefineRegistry.has(id)) {
119
+ return id;
120
+ }
121
+ throw new LoaderError(UNRESOLVED, [id]);
122
+ }
123
+ if (importer && isUrl(resolved)) {
124
+ resolved += `?importer=${encodeURIComponent(importer)}`;
125
+ }
126
+ return resolved;
127
+ }
128
+ has(id) {
129
+ return this.moduleRegistry.has(id);
130
+ }
131
+ define(name, dependencies, exporter) {
132
+ const mod = this.namedDefineRegistry.get(name);
133
+ // Don't allow redefining a module.
134
+ if (mod && mod.defined) {
135
+ if (process.env.NODE_ENV !== 'production' && hasConsole) {
136
+ // eslint-disable-next-line lwr/no-unguarded-apis
137
+ console.warn(`Module redefine attempted: ${name}`);
138
+ }
139
+ this.lastDefine = mod;
140
+ return;
141
+ }
142
+ const moduleDef = {
143
+ name,
144
+ dependencies,
145
+ exporter,
146
+ defined: true,
147
+ };
148
+ if (mod && mod.external) {
149
+ // if module is "external", resolve the external promise to notify any dependees
150
+ mod.external.resolveExternal(moduleDef);
151
+ }
152
+ this.profiler.logOperationStart({ id: MODULE_DEFINE, specifier: name });
153
+ this.namedDefineRegistry.set(name, moduleDef);
154
+ this.lastDefine = moduleDef;
155
+ }
156
+ /**
157
+ * Marks modules as "externally" loaded/provided, so that the loader does not attempt to fetch them.
158
+ *
159
+ * @param modules - list of module identifiers
160
+ */
161
+ registerExternalModules(modules) {
162
+ modules.map((id) => {
163
+ if (!this.namedDefineRegistry.has(id)) {
164
+ let resolveExternal;
165
+ let timer;
166
+ const moduleDefPromise = new Promise((resolve, reject) => {
167
+ resolveExternal = resolve;
168
+ // watch the external for timeout
169
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
170
+ timer = setTimeout(() => {
171
+ reject(new LoaderError(MODULE_LOAD_TIMEOUT, [id]));
172
+ }, MODULE_LOAD_TIMEOUT_TIMER);
173
+ }).finally(() => {
174
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
175
+ clearTimeout(timer);
176
+ });
177
+ const moduleDef = {
178
+ name: id,
179
+ defined: false,
180
+ external: {
181
+ resolveExternal,
182
+ moduleDefPromise,
183
+ },
184
+ };
185
+ this.namedDefineRegistry.set(id, moduleDef);
186
+ }
187
+ else if (process.env.NODE_ENV !== 'production' && hasConsole) {
188
+ // eslint-disable-next-line lwr/no-unguarded-apis
189
+ console.warn(MODULE_ALREADY_LOADED.message, id);
190
+ }
191
+ });
192
+ }
193
+ getImportMetadataResolver() {
194
+ return this.resolver;
195
+ }
196
+ // Returns an existing module record by the resolvedId or aliased id
197
+ getExistingModuleRecord(resolvedId, aliasId) {
198
+ const moduleRecord = this.moduleRegistry.get(resolvedId);
199
+ if (moduleRecord) {
200
+ this.storeModuleAlias(aliasId, resolvedId);
201
+ return moduleRecord;
202
+ }
203
+ // Check if this is a known alias
204
+ if (resolvedId !== aliasId) {
205
+ const alias = this.aliases.get(aliasId);
206
+ if (alias) {
207
+ const aliasedModule = this.moduleRegistry.get(alias);
208
+ if (aliasedModule) {
209
+ return aliasedModule;
210
+ }
211
+ }
212
+ }
213
+ return moduleRecord;
214
+ }
215
+ async getModuleRecord(resolvedId, id) {
216
+ // Look for an existing record
217
+ const existingRecord = this.getExistingModuleRecord(resolvedId, id);
218
+ if (existingRecord) {
219
+ // return existing
220
+ return existingRecord;
221
+ }
222
+ // Create a new Module Record
223
+ const instantiation = this.getModuleDef(resolvedId, id);
224
+ const dependencyRecords = instantiation.then((moduleDef) => {
225
+ const dependencies = moduleDef.dependencies || [];
226
+ // get dep and filter out exports
227
+ const filtered = dependencies
228
+ .map((dep) => {
229
+ if (dep === 'exports') {
230
+ return;
231
+ }
232
+ invariant(dep !== 'require', NO_AMD_REQUIRE);
233
+ return this.getModuleDependencyRecord.call(this, dep);
234
+ })
235
+ .filter((depRecord) => depRecord !== undefined);
236
+ return Promise.all(filtered);
237
+ });
238
+ const newModuleRecord = {
239
+ id: resolvedId,
240
+ module: Object.create(null),
241
+ dependencyRecords,
242
+ instantiation,
243
+ evaluated: false,
244
+ evaluationPromise: null,
245
+ };
246
+ this.moduleRegistry.set(resolvedId, newModuleRecord);
247
+ this.storeModuleAlias(id, resolvedId);
248
+ // Wait for the dependencies to resolve the return the moduleRecord
249
+ return dependencyRecords.then(() => newModuleRecord);
250
+ }
251
+ storeModuleAlias(aliasId, resolvedId) {
252
+ if (aliasId !== resolvedId) {
253
+ if (!this.aliases.has(aliasId)) {
254
+ this.aliases.set(aliasId, resolvedId);
255
+ }
256
+ else if (process.env.NODE_ENV !== 'production' && hasConsole) {
257
+ // Warn the user if they were not aliasing to the resolvedId
258
+ const currentResolvedId = this.aliases.get(aliasId);
259
+ if (currentResolvedId !== resolvedId) {
260
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
261
+ if (process.env.NODE_ENV !== 'production' && hasConsole) {
262
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
263
+ console.warn(`Alias update attempt: ${aliasId}=>${currentResolvedId}, ${resolvedId}`);
264
+ }
265
+ }
266
+ }
267
+ }
268
+ }
269
+ async getModuleDependencyRecord(dependency) {
270
+ const resolvedDepId = await this.resolve(dependency);
271
+ return this.getModuleRecord(resolvedDepId, dependency);
272
+ }
273
+ // execute the "top-level code" (the code outside of functions) of a module
274
+ async topLevelEvaluation(moduleRecord) {
275
+ await this.instantiateAll(moduleRecord, {});
276
+ return this.evaluateModule(moduleRecord, {});
277
+ }
278
+ // Returns a promise when a module and all of it's dependencies have finished instantiation
279
+ async instantiateAll(moduleRecord, instantiatedMap) {
280
+ if (!instantiatedMap[moduleRecord.id]) {
281
+ instantiatedMap[moduleRecord.id] = true;
282
+ const dependencyModuleRecords = await moduleRecord.dependencyRecords;
283
+ if (dependencyModuleRecords) {
284
+ for (let i = 0; i < dependencyModuleRecords.length; i++) {
285
+ const depRecord = dependencyModuleRecords[i];
286
+ // eslint-disable-next-line no-await-in-loop
287
+ await this.instantiateAll(depRecord, instantiatedMap);
288
+ }
289
+ }
290
+ }
291
+ }
292
+ async evaluateModule(moduleRecord, evaluationMap) {
293
+ const dependencyModuleRecords = await moduleRecord.dependencyRecords;
294
+ if (dependencyModuleRecords.length > 0) {
295
+ evaluationMap[moduleRecord.id] = true;
296
+ // evaluate dependencies first
297
+ await this.evaluateModuleDependencies(dependencyModuleRecords, evaluationMap);
298
+ }
299
+ const { exporter, dependencies } = await moduleRecord.instantiation;
300
+ // The exports object automatically gets filled in by the exporter evaluation
301
+ const exports = {};
302
+ const depsMapped = dependencies
303
+ ? await Promise.all(dependencies.map(async (dep) => {
304
+ if (dep === 'exports') {
305
+ return exports;
306
+ }
307
+ const resolvedDepId = await this.resolve(dep);
308
+ const moduleRecord = this.moduleRegistry.get(resolvedDepId);
309
+ if (!moduleRecord) {
310
+ throw new LoaderError(FAILED_DEP, [resolvedDepId]);
311
+ }
312
+ const module = moduleRecord.module;
313
+ /**
314
+ * Circular dependencies are handled properly when named exports are used,
315
+ * however, for default exports there is a bug: https://github.com/rollup/rollup/issues/3384
316
+ *
317
+ * The workaround below applies for circular dependencies (!moduleRecord.evaluated)
318
+ */
319
+ if (!moduleRecord.evaluated) {
320
+ return this.getCircularDependencyWrapper(module);
321
+ }
322
+ if (module) {
323
+ return module.__defaultInterop ? module.default : module;
324
+ }
325
+ throw new LoaderError(FAILED_DEP, [resolvedDepId]);
326
+ }))
327
+ : [];
328
+ // 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
329
+ if (moduleRecord.evaluated) {
330
+ return moduleRecord.module;
331
+ }
332
+ // evaluates the module function
333
+ let moduleDefault;
334
+ try {
335
+ moduleDefault = exporter(...depsMapped);
336
+ }
337
+ catch (e) {
338
+ throw new LoaderError(EXPORTER_ERROR, [moduleRecord.id, e.message || e]);
339
+ }
340
+ // value is returned from exporter, then we are not using named exports
341
+ if (moduleDefault !== undefined) {
342
+ moduleDefault = { default: moduleDefault };
343
+ // __defaultInterop is ONLY used to support backwards compatibility
344
+ // of importing default exports the "wrong" way (when not using named exports).
345
+ // See https://github.com/salesforce-experience-platform-emu/lwr/pull/816
346
+ Object.defineProperty(moduleDefault, '__defaultInterop', { value: true });
347
+ }
348
+ // if no return value, then we are using the exports object
349
+ else {
350
+ // handle only default export with Rollup forced named exports
351
+ if (this.isNamedExportDefaultOnly(exports)) {
352
+ Object.defineProperty(exports, '__useDefault', { value: true });
353
+ }
354
+ }
355
+ const moduleExports = moduleDefault || exports;
356
+ // update the module record
357
+ // copy over enumerable public methods to module
358
+ for (const key in moduleExports) {
359
+ Object.defineProperty(moduleRecord.module, key, {
360
+ enumerable: true,
361
+ set(value) {
362
+ moduleExports[key] = value;
363
+ },
364
+ get() {
365
+ return moduleExports[key];
366
+ },
367
+ });
368
+ }
369
+ // copy non-enumerable to module
370
+ if (moduleExports.__useDefault) {
371
+ Object.defineProperty(moduleRecord.module, '__useDefault', { value: true });
372
+ }
373
+ if (moduleExports.__defaultInterop) {
374
+ Object.defineProperty(moduleRecord.module, '__defaultInterop', { value: true });
375
+ }
376
+ if (moduleExports.__esModule) {
377
+ Object.defineProperty(moduleRecord.module, '__esModule', { value: true });
378
+ }
379
+ moduleRecord.evaluated = true;
380
+ Object.freeze(moduleRecord.module);
381
+ return moduleRecord.module;
382
+ }
383
+ // Determines if named exports module has only default export
384
+ isNamedExportDefaultOnly(exports) {
385
+ return (exports !== undefined &&
386
+ Object.getOwnPropertyNames(exports).length === 2 &&
387
+ Object.prototype.hasOwnProperty.call(exports, 'default') &&
388
+ Object.prototype.hasOwnProperty.call(exports, '__esModule'));
389
+ }
390
+ // Wrap the dependency in a function that can be called and detected by __circular__ property.
391
+ // The LWC engine checks for __circular__ to detect circular dependencies.
392
+ getCircularDependencyWrapper(module) {
393
+ const tmp = () => {
394
+ return module.__useDefault || module.__defaultInterop ? module.default : module;
395
+ };
396
+ tmp.__circular__ = true;
397
+ return tmp;
398
+ }
399
+ async evaluateModuleDependencies(dependencyModuleRecords, evaluationMap) {
400
+ for (let i = 0; i < dependencyModuleRecords.length; i++) {
401
+ const depRecord = dependencyModuleRecords[i];
402
+ if (!depRecord.evaluated && !evaluationMap[depRecord.id]) {
403
+ evaluationMap[depRecord.id] = true;
404
+ // eslint-disable-next-line no-await-in-loop
405
+ await this.evaluateModule(depRecord, evaluationMap);
406
+ }
407
+ }
408
+ }
409
+ async getModuleDef(resolvedId, originalId) {
410
+ // reset lastDefine
411
+ this.lastDefine = undefined;
412
+ // the module name can be the resolved ID or the original ID if neither are URL's.
413
+ const moduleName = !isUrl(resolvedId)
414
+ ? resolvedId
415
+ : originalId !== resolvedId
416
+ ? originalId
417
+ : undefined;
418
+ let moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
419
+ if (moduleDef && moduleDef.external) {
420
+ return moduleDef.external.moduleDefPromise;
421
+ }
422
+ if (moduleDef && moduleDef.defined) {
423
+ return moduleDef;
424
+ }
425
+ const parentUrl = this.resolver.getBaseUrl(); // only support baseUrl for now
426
+ const specifier = moduleName || originalId;
427
+ this.profiler.logOperationStart({ id: MODULE_FETCH, specifier });
428
+ return Promise.resolve()
429
+ .then(async () => {
430
+ const loadHooks = this.loadHook;
431
+ if (loadHooks) {
432
+ for (let i = 0; i < loadHooks.length; i++) {
433
+ const loadHook = loadHooks[i];
434
+ const response = loadHook(resolvedId, parentUrl);
435
+ const result = (isResponseAPromise(response)
436
+ ? // eslint-disable-next-line no-await-in-loop
437
+ await evaluateLoadHook(resolvedId, response)
438
+ : response);
439
+ if (result === undefined) {
440
+ throw new LoaderError(INVALID_LOADER_SERVICE_RESPONSE);
441
+ }
442
+ if (result && result !== null) {
443
+ return evaluateLoadHookResponse(result, resolvedId);
444
+ }
445
+ }
446
+ }
447
+ return false;
448
+ })
449
+ .then((result) => {
450
+ if (result !== true && hasDocument) {
451
+ return loadModuleDef(resolvedId);
452
+ }
453
+ })
454
+ .then(() => {
455
+ // Attempt to retrieve the module definition by name first
456
+ moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
457
+ // Fallback to the last loader.define call
458
+ if (!moduleDef) {
459
+ moduleDef = this.lastDefine;
460
+ }
461
+ // This should not happen
462
+ if (!moduleDef) {
463
+ throw new LoaderError(FAIL_INSTANTIATE, [resolvedId]);
464
+ }
465
+ this.profiler.logOperationEnd({ id: MODULE_FETCH, specifier });
466
+ return moduleDef;
467
+ })
468
+ .catch((e) => {
469
+ // Create module error marks for all errors caused by the loader
470
+ // Note: these marks do not include errors caused by invalid server responses or loader hooks
471
+ if (!(e instanceof LoaderError)) {
472
+ this.profiler.logOperationStart({ id: MODULE_ERROR, specifier });
473
+ }
474
+ throw e;
475
+ });
476
+ }
477
+ addLoaderPlugin(hooks) {
478
+ if (typeof hooks !== 'object') {
479
+ throw new LoaderError(INVALID_HOOK);
480
+ }
481
+ const { loadModule: loadHook, resolveModule: resolveHook, loadMapping } = hooks;
482
+ if (resolveHook) {
483
+ if (this.resolveHook) {
484
+ this.resolveHook.push(resolveHook);
485
+ }
486
+ else {
487
+ this.resolveHook = [resolveHook];
488
+ }
489
+ }
490
+ if (loadHook) {
491
+ if (this.loadHook) {
492
+ this.loadHook.push(loadHook);
493
+ }
494
+ else {
495
+ this.loadHook = [loadHook];
496
+ }
497
+ }
498
+ if (loadMapping) {
499
+ this.resolver.addLoadMappingHook(loadMapping);
500
+ }
501
+ }
502
+ importMetadataInvalidationCallback({ name, oldUrl, newUrl }) {
503
+ const handleStaleModuleHooks = this.handleStaleModuleHook;
504
+ if (handleStaleModuleHooks) {
505
+ evaluateHandleStaleModuleHooks(handleStaleModuleHooks, {
506
+ name,
507
+ oldUrl,
508
+ newUrl,
509
+ });
510
+ }
511
+ else {
512
+ if (process.env.NODE_ENV !== 'production' && hasConsole) {
513
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
514
+ console.warn(`stale module detected ${name}, current URL:${oldUrl}, new URL:${newUrl}`);
515
+ }
516
+ }
517
+ }
518
+ registerHandleStaleModuleHook(handleStaleModule) {
519
+ if (this.handleStaleModuleHook) {
520
+ this.handleStaleModuleHook.push(handleStaleModule);
521
+ }
522
+ else {
523
+ this.handleStaleModuleHook = [handleStaleModule];
524
+ }
525
+ }
526
+ isValidResolveResponse(res) {
527
+ return (res === null || typeof res === 'string' || (res && typeof res.url === 'string'));
528
+ }
529
+ }
530
+ //# sourceMappingURL=moduleRegistry.js.map
@@ -0,0 +1,3 @@
1
+ declare function loadModuleDef(url: string): Promise<void>;
2
+ export { loadModuleDef };
3
+ //# sourceMappingURL=scriptLoad.d.ts.map
@@ -0,0 +1,43 @@
1
+ import { LoaderError, FAIL_LOAD } from '../errors/messages.js';
2
+ import { hasDocument } from '../utils/dom.js';
3
+ function createScript(url) {
4
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
5
+ const script = document.createElement('script');
6
+ script.async = true;
7
+ script.crossOrigin = 'anonymous';
8
+ script.src = url;
9
+ return script;
10
+ }
11
+ let lastWindowError, lastWindowErrorUrl;
12
+ function loadModuleDef(url) {
13
+ return new Promise(function (resolve, reject) {
14
+ if (hasDocument) {
15
+ /* eslint-disable lwr/no-unguarded-apis, no-undef */
16
+ const script = createScript(url);
17
+ script.addEventListener('error', () => {
18
+ reject(new LoaderError(FAIL_LOAD, [url]));
19
+ });
20
+ script.addEventListener('load', () => {
21
+ document.head.removeChild(script);
22
+ if (lastWindowErrorUrl === url) {
23
+ reject(lastWindowError);
24
+ }
25
+ else {
26
+ resolve();
27
+ }
28
+ });
29
+ document.head.appendChild(script);
30
+ /* eslint-enable lwr/no-unguarded-apis, no-undef */
31
+ }
32
+ });
33
+ }
34
+ if (hasDocument) {
35
+ // When a script is executed, runtime errors are on the global/window scope which are NOT caught by the script's onerror handler.
36
+ // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
37
+ window.addEventListener('error', (evt) => {
38
+ lastWindowErrorUrl = evt.filename;
39
+ lastWindowError = evt.error;
40
+ });
41
+ }
42
+ export { loadModuleDef };
43
+ //# sourceMappingURL=scriptLoad.js.map
@@ -0,0 +1,4 @@
1
+ export declare const hasDocument: boolean;
2
+ export declare const hasSetTimeout: boolean;
3
+ export declare const hasConsole: boolean;
4
+ //# sourceMappingURL=dom.d.ts.map
@@ -0,0 +1,6 @@
1
+ /* eslint-disable lwr/no-unguarded-apis */
2
+ export const hasDocument = typeof document !== 'undefined';
3
+ export const hasSetTimeout = typeof setTimeout === 'function';
4
+ export const hasConsole = typeof console !== 'undefined';
5
+ /* eslint-enable lwr/no-unguarded-apis */
6
+ //# sourceMappingURL=dom.js.map
@@ -0,0 +1,28 @@
1
+ export declare function getBaseUrl(): string | undefined;
2
+ /**
3
+ * Check if a string is a URL based on Common Internet Scheme Syntax
4
+ * https://www.ietf.org/rfc/rfc1738.txt
5
+ *
6
+ * URL Format:
7
+ * <scheme>:<scheme-specific-part>
8
+ * Common Internet Scheme Syntax:
9
+ * The scheme specific part starts with a double slash('//')
10
+ *
11
+ * A valid URL has a colon that is followed by a double slash.
12
+ *
13
+ * @param url - the url that is being checked
14
+ * @returns boolean
15
+ *
16
+ * @example Valid URLs
17
+ * 'https://salesforce.com'
18
+ * 'http://localhost:3000'
19
+ *
20
+ * @example Invalid URLs
21
+ * 'salesforce.com'
22
+ * 'localhost:3000'
23
+ * '@salesforce/label/type:namespace:name'
24
+ */
25
+ export declare function isUrl(url: string): boolean;
26
+ export declare function resolveIfNotPlainOrUrl(relUrl: string, parentUrl: string): string | undefined;
27
+ export declare function resolveUrl(relUrl: string, parentUrl: string): string | undefined;
28
+ //# sourceMappingURL=url.d.ts.map