@atlaspack/runtime-js 2.12.1-dev.3401 → 2.12.1-dev.3450

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/JSRuntime.js CHANGED
@@ -39,6 +39,13 @@ function _nullthrows() {
39
39
  };
40
40
  return data;
41
41
  }
42
+ function _featureFlags() {
43
+ const data = require("@atlaspack/feature-flags");
44
+ _featureFlags = function () {
45
+ return data;
46
+ };
47
+ return data;
48
+ }
42
49
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
43
50
  // Used for as="" in preload/prefetch
44
51
  const TYPE_TO_RESOURCE_PRIORITY = {
@@ -131,6 +138,7 @@ var _default = exports.default = new (_plugin().Runtime)({
131
138
  }
132
139
  let {
133
140
  asyncDependencies,
141
+ conditionalDependencies,
134
142
  otherDependencies
135
143
  } = getDependencies(bundle);
136
144
  let assets = [];
@@ -180,6 +188,24 @@ var _default = exports.default = new (_plugin().Runtime)({
180
188
  }
181
189
  }
182
190
  }
191
+ if ((0, _featureFlags().getFeatureFlag)('conditionalBundlingApi')) {
192
+ // For any conditions that are used in this bundle, we want to produce a runtime asset that is used to
193
+ // select the correct dependency that condition maps to at runtime - the conditions in the bundle will then be
194
+ // replaced with a reference to this asset to implement the selection.
195
+ const conditions = bundleGraph.getConditionsForDependencies(conditionalDependencies);
196
+ for (const cond of conditions) {
197
+ const requireName = bundle.env.shouldScopeHoist ? 'parcelRequire' : '__parcel__require__';
198
+ const assetCode = `module.exports = require('../helpers/conditional-loader${options.mode === 'development' ? '-dev' : ''}')('${cond.key}', function (){return ${requireName}('${cond.ifTrueAssetId}')}, function (){return ${requireName}('${cond.ifFalseAssetId}')})`;
199
+ assets.push({
200
+ filePath: _path().default.join(__dirname, `/conditions/${cond.publicId}.js`),
201
+ code: assetCode,
202
+ dependency: cond.ifTrueDependency,
203
+ env: {
204
+ sourceType: 'module'
205
+ }
206
+ });
207
+ }
208
+ }
183
209
  for (let dependency of otherDependencies) {
184
210
  // Resolve the dependency to a bundle. If inline, export the dependency id,
185
211
  // which will be replaced with the contents of that bundle later.
@@ -278,6 +304,7 @@ function getDependencies(bundle) {
278
304
  } else {
279
305
  let asyncDependencies = [];
280
306
  let otherDependencies = [];
307
+ let conditionalDependencies = [];
281
308
  bundle.traverse(node => {
282
309
  if (node.type !== 'dependency') {
283
310
  return;
@@ -285,16 +312,20 @@ function getDependencies(bundle) {
285
312
  let dependency = node.value;
286
313
  if (dependency.priority === 'lazy' && dependency.specifierType !== 'url') {
287
314
  asyncDependencies.push(dependency);
315
+ } else if (dependency.priority === 'conditional') {
316
+ conditionalDependencies.push(dependency);
288
317
  } else {
289
318
  otherDependencies.push(dependency);
290
319
  }
291
320
  });
292
321
  bundleDependencies.set(bundle, {
293
322
  asyncDependencies,
323
+ conditionalDependencies,
294
324
  otherDependencies
295
325
  });
296
326
  return {
297
327
  asyncDependencies,
328
+ conditionalDependencies,
298
329
  otherDependencies
299
330
  };
300
331
  }
@@ -338,28 +369,25 @@ function getLoaderRuntime({
338
369
  let needsDynamicImportPolyfill = !bundle.env.isLibrary && !bundle.env.supports('dynamic-import', true);
339
370
  let needsEsmLoadPrelude = false;
340
371
  let loaderModules = [];
341
- for (let to of externalBundles) {
372
+ function getLoaderForBundle(bundle, to) {
342
373
  let loader = loaders[to.type];
343
374
  if (!loader) {
344
- continue;
375
+ return;
345
376
  }
346
377
  if (to.type === 'js' && to.env.outputFormat === 'esmodule' && !needsDynamicImportPolyfill && shouldUseRuntimeManifest(bundle, options)) {
347
- loaderModules.push(`load(${JSON.stringify(to.publicId)})`);
348
378
  needsEsmLoadPrelude = true;
349
- continue;
379
+ return `load(${JSON.stringify(to.publicId)})`;
350
380
  }
351
381
  let relativePathExpr = getRelativePathExpr(bundle, to, options);
352
382
 
353
383
  // Use esmodule loader if possible
354
384
  if (to.type === 'js' && to.env.outputFormat === 'esmodule') {
355
385
  if (!needsDynamicImportPolyfill) {
356
- loaderModules.push(`__parcel__import__("./" + ${relativePathExpr})`);
357
- continue;
386
+ return `__parcel__import__("./" + ${relativePathExpr})`;
358
387
  }
359
388
  loader = (0, _nullthrows().default)(loaders.IMPORT_POLYFILL, `No import() polyfill available for context '${bundle.env.context}'`);
360
389
  } else if (to.type === 'js' && to.env.outputFormat === 'commonjs') {
361
- loaderModules.push(`Promise.resolve(__parcel__require__("./" + ${relativePathExpr}))`);
362
- continue;
390
+ return `Promise.resolve(__parcel__require__("./" + ${relativePathExpr}))`;
363
391
  }
364
392
  let absoluteUrlExpr = shouldUseRuntimeManifest(bundle, options) ? `require('./helpers/bundle-manifest').resolve(${JSON.stringify(to.publicId)})` : getAbsoluteUrlExpr(relativePathExpr, bundle);
365
393
  let code = `require(${JSON.stringify(loader)})(${absoluteUrlExpr})`;
@@ -369,7 +397,22 @@ function getLoaderRuntime({
369
397
  if (options.mode === 'development' && bundle.env.outputFormat === 'global') {
370
398
  code += '.catch(err => {delete module.bundle.cache[module.id]; throw err;})';
371
399
  }
372
- loaderModules.push(code);
400
+ return code;
401
+ }
402
+ if ((0, _featureFlags().getFeatureFlag)('conditionalBundlingApi')) {
403
+ let conditionalDependencies = externalBundles.flatMap(to => getDependencies(to).conditionalDependencies);
404
+ for (const cond of bundleGraph.getConditionsForDependencies(conditionalDependencies)) {
405
+ // This bundle has a conditional dependency, we need to load it as it may not be present
406
+ let ifTrueBundle = (0, _nullthrows().default)(bundleGraph.getReferencedBundle(cond.ifTrueDependency, bundle), 'ifTrueBundle was null');
407
+ let ifFalseBundle = (0, _nullthrows().default)(bundleGraph.getReferencedBundle(cond.ifFalseDependency, bundle), 'ifFalseBundle was null');
408
+
409
+ // Load conditional bundles with helper (and a dev mode with additional hints)
410
+ loaderModules.push(`require('./helpers/conditional-loader${options.mode === 'development' ? '-dev' : ''}')('${cond.key}', function (){return ${getLoaderForBundle(bundle, ifTrueBundle) ?? `Promise.resolve()`}}, function (){return ${getLoaderForBundle(bundle, ifFalseBundle) ?? `Promise.resolve()`}})`);
411
+ }
412
+ }
413
+ for (let to of externalBundles) {
414
+ let loaderModule = getLoaderForBundle(bundle, to);
415
+ if (loaderModule !== undefined) loaderModules.push(loaderModule);
373
416
  }
374
417
 
375
418
  // Similar to the comment above, this also used to be skipped when shouldBuildLazily was true,
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ module.exports = function (cond, ifTrue, ifFalse) {
4
+ if (typeof globalThis.__MCOND !== 'function') {
5
+ throw new TypeError('"globalThis.__MCOND" was not set to an object. Ensure the function is set to return the key condition for conditional bundles to load with.');
6
+ }
7
+ if (typeof globalThis.__MCOND(cond) === 'undefined') {
8
+ console.error("\"".concat(cond, "\" did not match on globalThis.__MCOND. The conditional dependency will be loaded with the false variant."));
9
+ }
10
+ try {
11
+ return globalThis.__MCOND(cond) ? ifTrue() : ifFalse();
12
+ } catch (err) {
13
+ console.error('Conditional dependency was missing. Ensure the server sends the correct scripts to the client ("conditional-manifest.json").');
14
+ throw err;
15
+ }
16
+ };
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ module.exports = function (cond, ifTrue, ifFalse) {
4
+ return globalThis.__MCOND && globalThis.__MCOND(cond) ? ifTrue() : ifFalse();
5
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atlaspack/runtime-js",
3
- "version": "2.12.1-dev.3401+b483af77f",
4
- "license": "MIT",
3
+ "version": "2.12.1-dev.3450+58845ef87",
4
+ "license": "(MIT OR Apache-2.0)",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -13,13 +13,14 @@
13
13
  "source": "src/JSRuntime.js",
14
14
  "engines": {
15
15
  "node": ">= 16.0.0",
16
- "parcel": "^2.12.1-dev.3401+b483af77f"
16
+ "parcel": "^2.12.1-dev.3450+58845ef87"
17
17
  },
18
18
  "dependencies": {
19
- "@atlaspack/diagnostic": "2.12.1-dev.3401+b483af77f",
20
- "@atlaspack/plugin": "2.12.1-dev.3401+b483af77f",
21
- "@atlaspack/utils": "2.12.1-dev.3401+b483af77f",
19
+ "@atlaspack/diagnostic": "2.12.1-dev.3450+58845ef87",
20
+ "@atlaspack/feature-flags": "2.12.1-dev.3450+58845ef87",
21
+ "@atlaspack/plugin": "2.12.1-dev.3450+58845ef87",
22
+ "@atlaspack/utils": "2.12.1-dev.3450+58845ef87",
22
23
  "nullthrows": "^1.1.1"
23
24
  },
24
- "gitHead": "b483af77f02d1258c8dad156e097b94f83671d8e"
25
+ "gitHead": "58845ef87446fcedb7d7d8876440c64184645cbb"
25
26
  }
package/src/JSRuntime.js CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  import {encodeJSONKeyComponent} from '@atlaspack/diagnostic';
20
20
  import path from 'path';
21
21
  import nullthrows from 'nullthrows';
22
+ import {getFeatureFlag} from '@atlaspack/feature-flags';
22
23
 
23
24
  // Used for as="" in preload/prefetch
24
25
  const TYPE_TO_RESOURCE_PRIORITY = {
@@ -66,6 +67,7 @@ let bundleDependencies = new WeakMap<
66
67
  NamedBundle,
67
68
  {|
68
69
  asyncDependencies: Array<Dependency>,
70
+ conditionalDependencies: Array<Dependency>,
69
71
  otherDependencies: Array<Dependency>,
70
72
  |},
71
73
  >();
@@ -127,7 +129,8 @@ export default (new Runtime({
127
129
  return;
128
130
  }
129
131
 
130
- let {asyncDependencies, otherDependencies} = getDependencies(bundle);
132
+ let {asyncDependencies, conditionalDependencies, otherDependencies} =
133
+ getDependencies(bundle);
131
134
 
132
135
  let assets = [];
133
136
  for (let dependency of asyncDependencies) {
@@ -186,6 +189,33 @@ export default (new Runtime({
186
189
  }
187
190
  }
188
191
 
192
+ if (getFeatureFlag('conditionalBundlingApi')) {
193
+ // For any conditions that are used in this bundle, we want to produce a runtime asset that is used to
194
+ // select the correct dependency that condition maps to at runtime - the conditions in the bundle will then be
195
+ // replaced with a reference to this asset to implement the selection.
196
+ const conditions = bundleGraph.getConditionsForDependencies(
197
+ conditionalDependencies,
198
+ );
199
+ for (const cond of conditions) {
200
+ const requireName = bundle.env.shouldScopeHoist
201
+ ? 'parcelRequire'
202
+ : '__parcel__require__';
203
+
204
+ const assetCode = `module.exports = require('../helpers/conditional-loader${
205
+ options.mode === 'development' ? '-dev' : ''
206
+ }')('${cond.key}', function (){return ${requireName}('${
207
+ cond.ifTrueAssetId
208
+ }')}, function (){return ${requireName}('${cond.ifFalseAssetId}')})`;
209
+
210
+ assets.push({
211
+ filePath: path.join(__dirname, `/conditions/${cond.publicId}.js`),
212
+ code: assetCode,
213
+ dependency: cond.ifTrueDependency,
214
+ env: {sourceType: 'module'},
215
+ });
216
+ }
217
+ }
218
+
189
219
  for (let dependency of otherDependencies) {
190
220
  // Resolve the dependency to a bundle. If inline, export the dependency id,
191
221
  // which will be replaced with the contents of that bundle later.
@@ -299,6 +329,7 @@ export default (new Runtime({
299
329
 
300
330
  function getDependencies(bundle: NamedBundle): {|
301
331
  asyncDependencies: Array<Dependency>,
332
+ conditionalDependencies: Array<Dependency>,
302
333
  otherDependencies: Array<Dependency>,
303
334
  |} {
304
335
  let cachedDependencies = bundleDependencies.get(bundle);
@@ -308,6 +339,7 @@ function getDependencies(bundle: NamedBundle): {|
308
339
  } else {
309
340
  let asyncDependencies = [];
310
341
  let otherDependencies = [];
342
+ let conditionalDependencies = [];
311
343
  bundle.traverse(node => {
312
344
  if (node.type !== 'dependency') {
313
345
  return;
@@ -319,12 +351,18 @@ function getDependencies(bundle: NamedBundle): {|
319
351
  dependency.specifierType !== 'url'
320
352
  ) {
321
353
  asyncDependencies.push(dependency);
354
+ } else if (dependency.priority === 'conditional') {
355
+ conditionalDependencies.push(dependency);
322
356
  } else {
323
357
  otherDependencies.push(dependency);
324
358
  }
325
359
  });
326
- bundleDependencies.set(bundle, {asyncDependencies, otherDependencies});
327
- return {asyncDependencies, otherDependencies};
360
+ bundleDependencies.set(bundle, {
361
+ asyncDependencies,
362
+ conditionalDependencies,
363
+ otherDependencies,
364
+ });
365
+ return {asyncDependencies, conditionalDependencies, otherDependencies};
328
366
  }
329
367
  }
330
368
 
@@ -378,10 +416,13 @@ function getLoaderRuntime({
378
416
  let needsEsmLoadPrelude = false;
379
417
  let loaderModules = [];
380
418
 
381
- for (let to of externalBundles) {
419
+ function getLoaderForBundle(
420
+ bundle: NamedBundle,
421
+ to: NamedBundle,
422
+ ): string | void {
382
423
  let loader = loaders[to.type];
383
424
  if (!loader) {
384
- continue;
425
+ return;
385
426
  }
386
427
 
387
428
  if (
@@ -390,9 +431,8 @@ function getLoaderRuntime({
390
431
  !needsDynamicImportPolyfill &&
391
432
  shouldUseRuntimeManifest(bundle, options)
392
433
  ) {
393
- loaderModules.push(`load(${JSON.stringify(to.publicId)})`);
394
434
  needsEsmLoadPrelude = true;
395
- continue;
435
+ return `load(${JSON.stringify(to.publicId)})`;
396
436
  }
397
437
 
398
438
  let relativePathExpr = getRelativePathExpr(bundle, to, options);
@@ -400,8 +440,7 @@ function getLoaderRuntime({
400
440
  // Use esmodule loader if possible
401
441
  if (to.type === 'js' && to.env.outputFormat === 'esmodule') {
402
442
  if (!needsDynamicImportPolyfill) {
403
- loaderModules.push(`__parcel__import__("./" + ${relativePathExpr})`);
404
- continue;
443
+ return `__parcel__import__("./" + ${relativePathExpr})`;
405
444
  }
406
445
 
407
446
  loader = nullthrows(
@@ -409,10 +448,7 @@ function getLoaderRuntime({
409
448
  `No import() polyfill available for context '${bundle.env.context}'`,
410
449
  );
411
450
  } else if (to.type === 'js' && to.env.outputFormat === 'commonjs') {
412
- loaderModules.push(
413
- `Promise.resolve(__parcel__require__("./" + ${relativePathExpr}))`,
414
- );
415
- continue;
451
+ return `Promise.resolve(__parcel__require__("./" + ${relativePathExpr}))`;
416
452
  }
417
453
 
418
454
  let absoluteUrlExpr = shouldUseRuntimeManifest(bundle, options)
@@ -431,7 +467,42 @@ function getLoaderRuntime({
431
467
  code +=
432
468
  '.catch(err => {delete module.bundle.cache[module.id]; throw err;})';
433
469
  }
434
- loaderModules.push(code);
470
+ return code;
471
+ }
472
+
473
+ if (getFeatureFlag('conditionalBundlingApi')) {
474
+ let conditionalDependencies = externalBundles.flatMap(
475
+ to => getDependencies(to).conditionalDependencies,
476
+ );
477
+ for (const cond of bundleGraph.getConditionsForDependencies(
478
+ conditionalDependencies,
479
+ )) {
480
+ // This bundle has a conditional dependency, we need to load it as it may not be present
481
+ let ifTrueBundle = nullthrows(
482
+ bundleGraph.getReferencedBundle(cond.ifTrueDependency, bundle),
483
+ 'ifTrueBundle was null',
484
+ );
485
+ let ifFalseBundle = nullthrows(
486
+ bundleGraph.getReferencedBundle(cond.ifFalseDependency, bundle),
487
+ 'ifFalseBundle was null',
488
+ );
489
+
490
+ // Load conditional bundles with helper (and a dev mode with additional hints)
491
+ loaderModules.push(
492
+ `require('./helpers/conditional-loader${
493
+ options.mode === 'development' ? '-dev' : ''
494
+ }')('${cond.key}', function (){return ${
495
+ getLoaderForBundle(bundle, ifTrueBundle) ?? `Promise.resolve()`
496
+ }}, function (){return ${
497
+ getLoaderForBundle(bundle, ifFalseBundle) ?? `Promise.resolve()`
498
+ }})`,
499
+ );
500
+ }
501
+ }
502
+
503
+ for (let to of externalBundles) {
504
+ let loaderModule = getLoaderForBundle(bundle, to);
505
+ if (loaderModule !== undefined) loaderModules.push(loaderModule);
435
506
  }
436
507
 
437
508
  // Similar to the comment above, this also used to be skipped when shouldBuildLazily was true,
@@ -0,0 +1,23 @@
1
+ module.exports = function loadCond(cond, ifTrue, ifFalse) {
2
+ if (typeof globalThis.__MCOND !== 'function') {
3
+ throw new TypeError(
4
+ '"globalThis.__MCOND" was not set to an object. Ensure the function is set to return the key condition for conditional bundles to load with.',
5
+ );
6
+ }
7
+
8
+ if (typeof globalThis.__MCOND(cond) === 'undefined') {
9
+ console.error(
10
+ `"${cond}" did not match on globalThis.__MCOND. The conditional dependency will be loaded with the false variant.`,
11
+ );
12
+ }
13
+
14
+ try {
15
+ return globalThis.__MCOND(cond) ? ifTrue() : ifFalse();
16
+ } catch (err) {
17
+ console.error(
18
+ 'Conditional dependency was missing. Ensure the server sends the correct scripts to the client ("conditional-manifest.json").',
19
+ );
20
+
21
+ throw err;
22
+ }
23
+ };
@@ -0,0 +1,3 @@
1
+ module.exports = function loadCond(cond, ifTrue, ifFalse) {
2
+ return globalThis.__MCOND && globalThis.__MCOND(cond) ? ifTrue() : ifFalse();
3
+ };