@parcel/packager-js 2.9.3 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -88,6 +88,11 @@ class ESMOutputFormat {
88
88
  res += `\nexport {${exportSpecifiers.join(', ')}};`;
89
89
  lines++;
90
90
  }
91
+ if (this.packager.needsPrelude && this.packager.shouldBundleQueue(this.packager.bundle)) {
92
+ // Should be last thing the bundle executes on intial eval
93
+ res += `\n$parcel$global.rlb(${JSON.stringify(this.packager.bundle.publicId)})`;
94
+ lines++;
95
+ }
91
96
  return [res, lines];
92
97
  }
93
98
  }
@@ -93,11 +93,13 @@ class ScopeHoistingPackager {
93
93
  hoistedRequires = new Map();
94
94
  needsPrelude = false;
95
95
  usedHelpers = new Set();
96
- constructor(options, bundleGraph, bundle, parcelRequireName) {
96
+ externalAssets = new Set();
97
+ constructor(options, bundleGraph, bundle, parcelRequireName, useAsyncBundleRuntime) {
97
98
  this.options = options;
98
99
  this.bundleGraph = bundleGraph;
99
100
  this.bundle = bundle;
100
101
  this.parcelRequireName = parcelRequireName;
102
+ this.useAsyncBundleRuntime = useAsyncBundleRuntime;
101
103
  let OutputFormat = OUTPUT_FORMATS[this.bundle.env.outputFormat];
102
104
  this.outputFormat = new OutputFormat(this);
103
105
  this.isAsyncBundle = this.bundleGraph.hasParentBundleOfType(this.bundle, 'js') && !this.bundle.env.isIsolated() && this.bundle.bundleBehavior !== 'isolated';
@@ -114,9 +116,23 @@ class ScopeHoistingPackager {
114
116
  // of each bundle group pointing at the sibling bundles. These can be
115
117
  // picked up by another bundler later at which point runtimes will be added.
116
118
  if (this.bundle.env.isLibrary || this.bundle.env.outputFormat === 'commonjs') {
117
- let bundles = this.bundleGraph.getReferencedBundles(this.bundle);
118
- for (let b of bundles) {
119
- this.externals.set((0, _utils().relativeBundlePath)(this.bundle, b), new Map());
119
+ for (let b of this.bundleGraph.getReferencedBundles(this.bundle)) {
120
+ let entry = b.getMainEntry();
121
+ let symbols = new Map();
122
+ if (entry && !this.isAsyncBundle && entry.type === 'js') {
123
+ this.externalAssets.add(entry);
124
+ let usedSymbols = this.bundleGraph.getUsedSymbols(entry) || new Set();
125
+ for (let s of usedSymbols) {
126
+ // If the referenced bundle is ESM, and we are importing '*', use 'default' instead.
127
+ // This matches the logic below in buildExportedSymbols.
128
+ let imported = s;
129
+ if (imported === '*' && b.env.outputFormat === 'esmodule') {
130
+ imported = 'default';
131
+ }
132
+ symbols.set(imported, this.getSymbolResolution(entry, entry, s));
133
+ }
134
+ }
135
+ this.externals.set((0, _utils().relativeBundlePath)(this.bundle, b), symbols);
120
136
  }
121
137
  }
122
138
  let res = '';
@@ -154,7 +170,7 @@ class ScopeHoistingPackager {
154
170
  let [prelude, preludeLines] = this.buildBundlePrelude();
155
171
  res = prelude + res;
156
172
  lineCount += preludeLines;
157
- (_sourceMap = sourceMap) === null || _sourceMap === void 0 ? void 0 : _sourceMap.offsetLines(1, preludeLines);
173
+ (_sourceMap = sourceMap) === null || _sourceMap === void 0 || _sourceMap.offsetLines(1, preludeLines);
158
174
  let entries = this.bundle.getEntryAssets();
159
175
  let mainEntry = this.bundle.getMainEntry();
160
176
  if (this.isAsyncBundle) {
@@ -166,6 +182,7 @@ class ScopeHoistingPackager {
166
182
  });
167
183
  mainEntry = null;
168
184
  }
185
+ let needsBundleQueue = this.shouldBundleQueue(this.bundle);
169
186
 
170
187
  // If any of the entry assets are wrapped, call parcelRequire so they are executed.
171
188
  for (let entry of entries) {
@@ -174,8 +191,12 @@ class ScopeHoistingPackager {
174
191
  let parcelRequire = `parcelRequire(${JSON.stringify(this.bundleGraph.getAssetPublicId(entry))});\n`;
175
192
  let entryExports = (_entry$symbols$get = entry.symbols.get('*')) === null || _entry$symbols$get === void 0 ? void 0 : _entry$symbols$get.local;
176
193
  if (entryExports && entry === mainEntry && this.exportedSymbols.has(entryExports)) {
194
+ (0, _assert().default)(!needsBundleQueue, 'Entry exports are not yet compaitble with async bundles');
177
195
  res += `\nvar ${entryExports} = ${parcelRequire}`;
178
196
  } else {
197
+ if (needsBundleQueue) {
198
+ parcelRequire = this.runWhenReady(this.bundle, parcelRequire);
199
+ }
179
200
  res += `\n${parcelRequire}`;
180
201
  }
181
202
  lineCount += 2;
@@ -210,6 +231,18 @@ class ScopeHoistingPackager {
210
231
  map: sourceMap
211
232
  };
212
233
  }
234
+ shouldBundleQueue(bundle) {
235
+ return this.useAsyncBundleRuntime && bundle.type === 'js' && bundle.bundleBehavior !== 'inline' && bundle.env.outputFormat === 'esmodule' && !bundle.env.isIsolated() && bundle.bundleBehavior !== 'isolated' && !this.bundleGraph.hasParentBundleOfType(bundle, 'js');
236
+ }
237
+ runWhenReady(bundle, codeToRun) {
238
+ let deps = this.bundleGraph.getReferencedBundles(bundle).filter(b => this.shouldBundleQueue(b)).map(b => b.publicId);
239
+ if (deps.length === 0) {
240
+ // If no deps we can safely execute immediately
241
+ return codeToRun;
242
+ }
243
+ let params = [JSON.stringify(this.bundle.publicId), (0, _helpers.fnExpr)(this.bundle.env, [], [codeToRun]), JSON.stringify(deps)];
244
+ return `$parcel$global.rwr(${params.join(', ')});`;
245
+ }
213
246
  async loadAssets() {
214
247
  let queue = new (_utils().PromiseQueue)({
215
248
  maxConcurrent: 32
@@ -224,8 +257,10 @@ class ScopeHoistingPackager {
224
257
  }];
225
258
  });
226
259
  if (asset.meta.shouldWrap || this.isAsyncBundle || this.bundle.env.sourceType === 'script' || this.bundleGraph.isAssetReferenced(this.bundle, asset) || this.bundleGraph.getIncomingDependencies(asset).some(dep => dep.meta.shouldWrap && dep.specifierType !== 'url')) {
227
- this.wrappedAssets.add(asset.id);
228
- wrapped.push(asset);
260
+ if (!asset.meta.isConstantModule) {
261
+ this.wrappedAssets.add(asset.id);
262
+ wrapped.push(asset);
263
+ }
229
264
  }
230
265
  });
231
266
  for (let wrappedAssetRoot of [...wrapped]) {
@@ -237,8 +272,10 @@ class ScopeHoistingPackager {
237
272
  actions.skipChildren();
238
273
  return;
239
274
  }
240
- this.wrappedAssets.add(asset.id);
241
- wrapped.push(asset);
275
+ if (!asset.meta.isConstantModule) {
276
+ this.wrappedAssets.add(asset.id);
277
+ wrapped.push(asset);
278
+ }
242
279
  }, wrappedAssetRoot);
243
280
  }
244
281
  this.assetOutputs = new Map(await queue.run());
@@ -366,7 +403,7 @@ class ScopeHoistingPackager {
366
403
  let [depMap, replacements] = this.buildReplacements(asset, deps);
367
404
  let [prepend, prependLines, append] = this.buildAssetPrelude(asset, deps);
368
405
  if (prependLines > 0) {
369
- sourceMap === null || sourceMap === void 0 ? void 0 : sourceMap.offsetLines(1, prependLines);
406
+ sourceMap === null || sourceMap === void 0 || sourceMap.offsetLines(1, prependLines);
370
407
  code = prepend + code;
371
408
  }
372
409
  code += append;
@@ -462,9 +499,9 @@ class ScopeHoistingPackager {
462
499
  // wrapper. Dependencies must be inserted AFTER the asset is registered so that circular dependencies work.
463
500
  if (shouldWrap) {
464
501
  // Offset by one line for the parcelRequire.register wrapper.
465
- sourceMap === null || sourceMap === void 0 ? void 0 : sourceMap.offsetLines(1, 1);
502
+ sourceMap === null || sourceMap === void 0 || sourceMap.offsetLines(1, 1);
466
503
  lineCount++;
467
- code = `parcelRequire.register(${JSON.stringify(this.bundleGraph.getAssetPublicId(asset))}, function(module, exports) {
504
+ code = `parcelRegister(${JSON.stringify(this.bundleGraph.getAssetPublicId(asset))}, function(module, exports) {
468
505
  ${code}
469
506
  });
470
507
  `;
@@ -479,6 +516,9 @@ ${code}
479
516
  }
480
517
  this.needsPrelude = true;
481
518
  }
519
+ if (!shouldWrap && this.shouldBundleQueue(this.bundle) && this.bundle.getEntryAssets().some(entry => entry.id === asset.id)) {
520
+ code = this.runWhenReady(this.bundle, code);
521
+ }
482
522
  return [code, sourceMap, lineCount];
483
523
  }
484
524
  buildReplacements(asset, deps) {
@@ -602,6 +642,13 @@ ${code}
602
642
  }
603
643
  }
604
644
  }
645
+ isWrapped(resolved, parentAsset) {
646
+ if (resolved.meta.isConstantModule) {
647
+ (0, _assert().default)(this.bundle.hasAsset(resolved), 'Constant module not found in bundle');
648
+ return false;
649
+ }
650
+ return !this.bundle.hasAsset(resolved) && !this.externalAssets.has(resolved) || this.wrappedAssets.has(resolved.id) && resolved !== parentAsset;
651
+ }
605
652
  getSymbolResolution(parentAsset, resolved, imported, dep) {
606
653
  var _resolvedAsset$symbol;
607
654
  let {
@@ -614,10 +661,14 @@ ${code}
614
661
  // that is actually unused but we still need a placeholder value.
615
662
  return '{}';
616
663
  }
617
- let isWrapped = !this.bundle.hasAsset(resolvedAsset) || this.wrappedAssets.has(resolvedAsset.id) && resolvedAsset !== parentAsset;
664
+ let isWrapped = this.isWrapped(resolvedAsset, parentAsset);
618
665
  let staticExports = resolvedAsset.meta.staticExports !== false;
619
666
  let publicId = this.bundleGraph.getAssetPublicId(resolvedAsset);
620
667
 
668
+ // External CommonJS dependencies need to be accessed as an object property rather than imported
669
+ // directly to maintain live binding.
670
+ let isExternalCommonJS = !isWrapped && this.bundle.env.isLibrary && this.bundle.env.outputFormat === 'commonjs' && !this.bundle.hasAsset(resolvedAsset);
671
+
621
672
  // If the resolved asset is wrapped, but imported at the top-level by this asset,
622
673
  // then we hoist parcelRequire calls to the top of this asset so side effects run immediately.
623
674
  if (isWrapped && dep && !(dep !== null && dep !== void 0 && dep.meta.shouldWrap) && symbol !== false && (
@@ -656,7 +707,7 @@ ${code}
656
707
  } else {
657
708
  return obj;
658
709
  }
659
- } else if ((!staticExports || isWrapped || !symbol) && resolvedAsset !== parentAsset) {
710
+ } else if ((!staticExports || isWrapped || !symbol || isExternalCommonJS) && resolvedAsset !== parentAsset) {
660
711
  // If the resolved asset is wrapped or has non-static exports,
661
712
  // we need to use a member access off the namespace object rather
662
713
  // than a direct reference. If importing default from a CJS module,
@@ -681,7 +732,7 @@ ${code}
681
732
  let hoisted = this.hoistedRequires.get(dep.id);
682
733
  let res = '';
683
734
  let lineCount = 0;
684
- let isWrapped = !this.bundle.hasAsset(resolved) || this.wrappedAssets.has(resolved.id) && resolved !== parentAsset;
735
+ let isWrapped = this.isWrapped(resolved, parentAsset);
685
736
 
686
737
  // If the resolved asset is wrapped and is imported in the top-level by this asset,
687
738
  // we need to run side effects when this asset runs. If the resolved asset is not
@@ -821,10 +872,10 @@ ${code}
821
872
  // required to simulate ESM live bindings. It's easier to do it this way rather than inserting
822
873
  // additional assignments after each mutation of the original binding.
823
874
  prepend += `\n${usedExports.map(exp => {
824
- var _asset$symbols$get2, _asset$symbols$get2$m;
875
+ var _asset$symbols$get2;
825
876
  let resolved = this.getSymbolResolution(asset, asset, exp);
826
877
  let get = this.buildFunctionExpression([], resolved);
827
- let isEsmExport = !!((_asset$symbols$get2 = asset.symbols.get(exp)) !== null && _asset$symbols$get2 !== void 0 && (_asset$symbols$get2$m = _asset$symbols$get2.meta) !== null && _asset$symbols$get2$m !== void 0 && _asset$symbols$get2$m.isEsm);
878
+ let isEsmExport = !!((_asset$symbols$get2 = asset.symbols.get(exp)) !== null && _asset$symbols$get2 !== void 0 && (_asset$symbols$get2 = _asset$symbols$get2.meta) !== null && _asset$symbols$get2 !== void 0 && _asset$symbols$get2.isEsm);
828
879
  let set = !isEsmExport && asset.meta.hasCJSExports ? ', ' + this.buildFunctionExpression(['v'], `${resolved} = v`) : '';
829
880
  return `$parcel$export($${assetId}$exports, ${JSON.stringify(exp)}, ${get}${set});`;
830
881
  }).join('\n')}\n`;
@@ -860,9 +911,13 @@ ${code}
860
911
  this.usedHelpers.add('$parcel$global');
861
912
  }
862
913
  for (let helper of this.usedHelpers) {
863
- res += _helpers.helpers[helper];
914
+ let currentHelper = _helpers.helpers[helper];
915
+ if (typeof currentHelper === 'function') {
916
+ currentHelper = _helpers.helpers[helper](this.bundle.env);
917
+ }
918
+ res += currentHelper;
864
919
  if (enableSourceMaps) {
865
- lines += (0, _utils().countLines)(_helpers.helpers[helper]) - 1;
920
+ lines += (0, _utils().countLines)(currentHelper) - 1;
866
921
  }
867
922
  }
868
923
  if (this.needsPrelude) {
@@ -876,9 +931,19 @@ ${code}
876
931
  if (enableSourceMaps) {
877
932
  lines += (0, _utils().countLines)(preludeCode) - 1;
878
933
  }
934
+ if (this.shouldBundleQueue(this.bundle)) {
935
+ let bundleQueuePreludeCode = (0, _helpers.bundleQueuePrelude)(this.bundle.env);
936
+ res += bundleQueuePreludeCode;
937
+ if (enableSourceMaps) {
938
+ lines += (0, _utils().countLines)(bundleQueuePreludeCode) - 1;
939
+ }
940
+ }
879
941
  } else {
880
942
  // Otherwise, get the current parcelRequire global.
881
- res += `var parcelRequire = $parcel$global[${JSON.stringify(this.parcelRequireName)}];\n`;
943
+ const escaped = JSON.stringify(this.parcelRequireName);
944
+ res += `var parcelRequire = $parcel$global[${escaped}];\n`;
945
+ lines++;
946
+ res += `var parcelRegister = parcelRequire.register;\n`;
882
947
  lines++;
883
948
  }
884
949
  }
package/lib/helpers.js CHANGED
@@ -3,11 +3,13 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.prelude = exports.helpers = void 0;
7
- const prelude = parcelRequireName => `var $parcel$modules = {};
6
+ exports.prelude = exports.helpers = exports.fnExpr = exports.bundleQueuePrelude = void 0;
7
+ const prelude = parcelRequireName => `
8
+ var $parcel$modules = {};
8
9
  var $parcel$inits = {};
9
10
 
10
11
  var parcelRequire = $parcel$global[${JSON.stringify(parcelRequireName)}];
12
+
11
13
  if (parcelRequire == null) {
12
14
  parcelRequire = function(id) {
13
15
  if (id in $parcel$modules) {
@@ -32,14 +34,47 @@ if (parcelRequire == null) {
32
34
 
33
35
  $parcel$global[${JSON.stringify(parcelRequireName)}] = parcelRequire;
34
36
  }
37
+
38
+ var parcelRegister = parcelRequire.register;
35
39
  `;
36
40
  exports.prelude = prelude;
37
- const helpers = {
38
- $parcel$export: `function $parcel$export(e, n, v, s) {
41
+ const fnExpr = (env, params, body) => {
42
+ let block = `{ ${body.join(' ')} }`;
43
+ if (env.supports('arrow-functions')) {
44
+ return `(${params.join(', ')}) => ${block}`;
45
+ }
46
+ return `function (${params.join(', ')}) ${block}`;
47
+ };
48
+ exports.fnExpr = fnExpr;
49
+ const bundleQueuePrelude = env => `
50
+ if (!$parcel$global.lb) {
51
+ // Set of loaded bundles
52
+ $parcel$global.lb = new Set();
53
+ // Queue of bundles to execute once they're dep bundles are loaded
54
+ $parcel$global.bq = [];
55
+
56
+ // Register loaded bundle
57
+ $parcel$global.rlb = ${fnExpr(env, ['bundle'], ['$parcel$global.lb.add(bundle);', '$parcel$global.pq();'])}
58
+
59
+ // Run when ready
60
+ $parcel$global.rwr = ${fnExpr(env,
61
+ // b = bundle public id
62
+ // r = run function to execute the bundle entry
63
+ // d = list of dependent bundles this bundle requires before executing
64
+ ['b', 'r', 'd'], ['$parcel$global.bq.push({b, r, d});', '$parcel$global.pq();'])}
65
+
66
+ // Process queue
67
+ $parcel$global.pq = ${fnExpr(env, [], [`var runnableEntry = $parcel$global.bq.find(${fnExpr(env, ['i'], [`return i.d.every(${fnExpr(env, ['dep'], ['return $parcel$global.lb.has(dep);'])});`])});`, 'if (runnableEntry) {', `$parcel$global.bq = $parcel$global.bq.filter(${fnExpr(env, ['i'], ['return i.b !== runnableEntry.b;'])});`, 'runnableEntry.r();', '$parcel$global.pq();', '}'])}
68
+ }
69
+ `;
70
+ exports.bundleQueuePrelude = bundleQueuePrelude;
71
+ const $parcel$export = `
72
+ function $parcel$export(e, n, v, s) {
39
73
  Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
40
74
  }
41
- `,
42
- $parcel$exportWildcard: `function $parcel$exportWildcard(dest, source) {
75
+ `;
76
+ const $parcel$exportWildcard = `
77
+ function $parcel$exportWildcard(dest, source) {
43
78
  Object.keys(source).forEach(function(key) {
44
79
  if (key === 'default' || key === '__esModule' || dest.hasOwnProperty(key)) {
45
80
  return;
@@ -55,25 +90,41 @@ const helpers = {
55
90
 
56
91
  return dest;
57
92
  }
58
- `,
59
- $parcel$interopDefault: `function $parcel$interopDefault(a) {
93
+ `;
94
+ const $parcel$interopDefault = `
95
+ function $parcel$interopDefault(a) {
60
96
  return a && a.__esModule ? a.default : a;
61
97
  }
62
- `,
63
- $parcel$global: `var $parcel$global =
64
- typeof globalThis !== 'undefined'
65
- ? globalThis
66
- : typeof self !== 'undefined'
67
- ? self
68
- : typeof window !== 'undefined'
69
- ? window
70
- : typeof global !== 'undefined'
71
- ? global
72
- : {};
73
- `,
74
- $parcel$defineInteropFlag: `function $parcel$defineInteropFlag(a) {
98
+ `;
99
+ const $parcel$global = env => {
100
+ if (env.supports('global-this')) {
101
+ return `
102
+ var $parcel$global = globalThis;
103
+ `;
104
+ }
105
+ return `
106
+ var $parcel$global =
107
+ typeof globalThis !== 'undefined'
108
+ ? globalThis
109
+ : typeof self !== 'undefined'
110
+ ? self
111
+ : typeof window !== 'undefined'
112
+ ? window
113
+ : typeof global !== 'undefined'
114
+ ? global
115
+ : {};
116
+ `;
117
+ };
118
+ const $parcel$defineInteropFlag = `
119
+ function $parcel$defineInteropFlag(a) {
75
120
  Object.defineProperty(a, '__esModule', {value: true, configurable: true});
76
121
  }
77
- `
122
+ `;
123
+ const helpers = {
124
+ $parcel$export,
125
+ $parcel$exportWildcard,
126
+ $parcel$interopDefault,
127
+ $parcel$global,
128
+ $parcel$defineInteropFlag
78
129
  };
79
130
  exports.helpers = helpers;
package/lib/index.js CHANGED
@@ -18,9 +18,16 @@ function _utils() {
18
18
  };
19
19
  return data;
20
20
  }
21
- function _hash() {
22
- const data = require("@parcel/hash");
23
- _hash = function () {
21
+ function _diagnostic() {
22
+ const data = require("@parcel/diagnostic");
23
+ _diagnostic = function () {
24
+ return data;
25
+ };
26
+ return data;
27
+ }
28
+ function _rust() {
29
+ const data = require("@parcel/rust");
30
+ _rust = function () {
24
31
  return data;
25
32
  };
26
33
  return data;
@@ -42,18 +49,37 @@ function _nullthrows() {
42
49
  var _DevPackager = require("./DevPackager");
43
50
  var _ScopeHoistingPackager = require("./ScopeHoistingPackager");
44
51
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
52
+ const CONFIG_SCHEMA = {
53
+ type: 'object',
54
+ properties: {
55
+ unstable_asyncBundleRuntime: {
56
+ type: 'boolean'
57
+ }
58
+ },
59
+ additionalProperties: false
60
+ };
45
61
  var _default = new (_plugin().Packager)({
46
62
  async loadConfig({
47
63
  config,
48
64
  options
49
65
  }) {
50
- var _pkg$contents$name, _pkg$contents;
66
+ var _pkg$contents$name, _pkg$contents, _pkg$contents$package;
51
67
  // Generate a name for the global parcelRequire function that is unique to this project.
52
68
  // This allows multiple parcel builds to coexist on the same page.
53
69
  let pkg = await config.getConfigFrom(_path().default.join(options.projectRoot, 'index'), ['package.json']);
54
- let name = (_pkg$contents$name = pkg === null || pkg === void 0 ? void 0 : (_pkg$contents = pkg.contents) === null || _pkg$contents === void 0 ? void 0 : _pkg$contents.name) !== null && _pkg$contents$name !== void 0 ? _pkg$contents$name : '';
70
+ let packageKey = '@parcel/packager-js';
71
+ if (pkg !== null && pkg !== void 0 && pkg.contents[packageKey]) {
72
+ _utils().validateSchema.diagnostic(CONFIG_SCHEMA, {
73
+ data: pkg === null || pkg === void 0 ? void 0 : pkg.contents[packageKey],
74
+ source: await options.inputFS.readFile(pkg.filePath, 'utf8'),
75
+ filePath: pkg.filePath,
76
+ prependKey: `/${(0, _diagnostic().encodeJSONKeyComponent)(packageKey)}`
77
+ }, packageKey, `Invalid config for ${packageKey}`);
78
+ }
79
+ let name = (_pkg$contents$name = pkg === null || pkg === void 0 || (_pkg$contents = pkg.contents) === null || _pkg$contents === void 0 ? void 0 : _pkg$contents.name) !== null && _pkg$contents$name !== void 0 ? _pkg$contents$name : '';
55
80
  return {
56
- parcelRequireName: 'parcelRequire' + (0, _hash().hashString)(name).slice(-4)
81
+ parcelRequireName: 'parcelRequire' + (0, _rust().hashString)(name).slice(-4),
82
+ unstable_asyncBundleRuntime: Boolean(pkg === null || pkg === void 0 || (_pkg$contents$package = pkg.contents[packageKey]) === null || _pkg$contents$package === void 0 ? void 0 : _pkg$contents$package.unstable_asyncBundleRuntime)
57
83
  };
58
84
  },
59
85
  async package({
@@ -75,7 +101,7 @@ var _default = new (_plugin().Packager)({
75
101
  }
76
102
  }
77
103
  if (contents == null) {
78
- let packager = bundle.env.shouldScopeHoist ? new _ScopeHoistingPackager.ScopeHoistingPackager(options, bundleGraph, bundle, (0, _nullthrows().default)(config).parcelRequireName) : new _DevPackager.DevPackager(options, bundleGraph, bundle, (0, _nullthrows().default)(config).parcelRequireName);
104
+ let packager = bundle.env.shouldScopeHoist ? new _ScopeHoistingPackager.ScopeHoistingPackager(options, bundleGraph, bundle, (0, _nullthrows().default)(config).parcelRequireName, (0, _nullthrows().default)(config).unstable_asyncBundleRuntime) : new _DevPackager.DevPackager(options, bundleGraph, bundle, (0, _nullthrows().default)(config).parcelRequireName);
79
105
  ({
80
106
  contents,
81
107
  map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parcel/packager-js",
3
- "version": "2.9.3",
3
+ "version": "2.10.0",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -17,16 +17,17 @@
17
17
  "source": "src/index.js",
18
18
  "engines": {
19
19
  "node": ">= 12.0.0",
20
- "parcel": "^2.9.3"
20
+ "parcel": "^2.10.0"
21
21
  },
22
22
  "dependencies": {
23
- "@parcel/diagnostic": "2.9.3",
24
- "@parcel/hash": "2.9.3",
25
- "@parcel/plugin": "2.9.3",
23
+ "@parcel/diagnostic": "2.10.0",
24
+ "@parcel/plugin": "2.10.0",
25
+ "@parcel/rust": "2.10.0",
26
26
  "@parcel/source-map": "^2.1.1",
27
- "@parcel/utils": "2.9.3",
27
+ "@parcel/types": "2.10.0",
28
+ "@parcel/utils": "2.10.0",
28
29
  "globals": "^13.2.0",
29
30
  "nullthrows": "^1.1.1"
30
31
  },
31
- "gitHead": "db3bcae10497fa6a712fd9a135f93f26c5745454"
32
+ "gitHead": "0e235842b5b93301379bdfa626e7a4e2ee42ea98"
32
33
  }
@@ -106,6 +106,17 @@ export class ESMOutputFormat implements OutputFormat {
106
106
  lines++;
107
107
  }
108
108
 
109
+ if (
110
+ this.packager.needsPrelude &&
111
+ this.packager.shouldBundleQueue(this.packager.bundle)
112
+ ) {
113
+ // Should be last thing the bundle executes on intial eval
114
+ res += `\n$parcel$global.rlb(${JSON.stringify(
115
+ this.packager.bundle.publicId,
116
+ )})`;
117
+ lines++;
118
+ }
119
+
109
120
  return [res, lines];
110
121
  }
111
122
  }
@@ -27,7 +27,7 @@ import path from 'path';
27
27
  import {ESMOutputFormat} from './ESMOutputFormat';
28
28
  import {CJSOutputFormat} from './CJSOutputFormat';
29
29
  import {GlobalOutputFormat} from './GlobalOutputFormat';
30
- import {prelude, helpers} from './helpers';
30
+ import {prelude, helpers, bundleQueuePrelude, fnExpr} from './helpers';
31
31
  import {replaceScriptDependencies, getSpecifier} from './utils';
32
32
 
33
33
  // https://262.ecma-international.org/6.0/#sec-names-and-keywords
@@ -74,6 +74,7 @@ export class ScopeHoistingPackager {
74
74
  bundleGraph: BundleGraph<NamedBundle>;
75
75
  bundle: NamedBundle;
76
76
  parcelRequireName: string;
77
+ useAsyncBundleRuntime: boolean;
77
78
  outputFormat: OutputFormat;
78
79
  isAsyncBundle: boolean;
79
80
  globalNames: $ReadOnlySet<string>;
@@ -94,17 +95,20 @@ export class ScopeHoistingPackager {
94
95
  hoistedRequires: Map<string, Map<string, string>> = new Map();
95
96
  needsPrelude: boolean = false;
96
97
  usedHelpers: Set<string> = new Set();
98
+ externalAssets: Set<Asset> = new Set();
97
99
 
98
100
  constructor(
99
101
  options: PluginOptions,
100
102
  bundleGraph: BundleGraph<NamedBundle>,
101
103
  bundle: NamedBundle,
102
104
  parcelRequireName: string,
105
+ useAsyncBundleRuntime: boolean,
103
106
  ) {
104
107
  this.options = options;
105
108
  this.bundleGraph = bundleGraph;
106
109
  this.bundle = bundle;
107
110
  this.parcelRequireName = parcelRequireName;
111
+ this.useAsyncBundleRuntime = useAsyncBundleRuntime;
108
112
 
109
113
  let OutputFormat = OUTPUT_FORMATS[this.bundle.env.outputFormat];
110
114
  this.outputFormat = new OutputFormat(this);
@@ -130,9 +134,25 @@ export class ScopeHoistingPackager {
130
134
  this.bundle.env.isLibrary ||
131
135
  this.bundle.env.outputFormat === 'commonjs'
132
136
  ) {
133
- let bundles = this.bundleGraph.getReferencedBundles(this.bundle);
134
- for (let b of bundles) {
135
- this.externals.set(relativeBundlePath(this.bundle, b), new Map());
137
+ for (let b of this.bundleGraph.getReferencedBundles(this.bundle)) {
138
+ let entry = b.getMainEntry();
139
+ let symbols = new Map();
140
+ if (entry && !this.isAsyncBundle && entry.type === 'js') {
141
+ this.externalAssets.add(entry);
142
+
143
+ let usedSymbols = this.bundleGraph.getUsedSymbols(entry) || new Set();
144
+ for (let s of usedSymbols) {
145
+ // If the referenced bundle is ESM, and we are importing '*', use 'default' instead.
146
+ // This matches the logic below in buildExportedSymbols.
147
+ let imported = s;
148
+ if (imported === '*' && b.env.outputFormat === 'esmodule') {
149
+ imported = 'default';
150
+ }
151
+ symbols.set(imported, this.getSymbolResolution(entry, entry, s));
152
+ }
153
+ }
154
+
155
+ this.externals.set(relativeBundlePath(this.bundle, b), symbols);
136
156
  }
137
157
  }
138
158
 
@@ -185,6 +205,8 @@ export class ScopeHoistingPackager {
185
205
  mainEntry = null;
186
206
  }
187
207
 
208
+ let needsBundleQueue = this.shouldBundleQueue(this.bundle);
209
+
188
210
  // If any of the entry assets are wrapped, call parcelRequire so they are executed.
189
211
  for (let entry of entries) {
190
212
  if (this.wrappedAssets.has(entry.id) && !this.isScriptEntry(entry)) {
@@ -193,13 +215,22 @@ export class ScopeHoistingPackager {
193
215
  )});\n`;
194
216
 
195
217
  let entryExports = entry.symbols.get('*')?.local;
218
+
196
219
  if (
197
220
  entryExports &&
198
221
  entry === mainEntry &&
199
222
  this.exportedSymbols.has(entryExports)
200
223
  ) {
224
+ invariant(
225
+ !needsBundleQueue,
226
+ 'Entry exports are not yet compaitble with async bundles',
227
+ );
201
228
  res += `\nvar ${entryExports} = ${parcelRequire}`;
202
229
  } else {
230
+ if (needsBundleQueue) {
231
+ parcelRequire = this.runWhenReady(this.bundle, parcelRequire);
232
+ }
233
+
203
234
  res += `\n${parcelRequire}`;
204
235
  }
205
236
 
@@ -247,6 +278,38 @@ export class ScopeHoistingPackager {
247
278
  };
248
279
  }
249
280
 
281
+ shouldBundleQueue(bundle: NamedBundle): boolean {
282
+ return (
283
+ this.useAsyncBundleRuntime &&
284
+ bundle.type === 'js' &&
285
+ bundle.bundleBehavior !== 'inline' &&
286
+ bundle.env.outputFormat === 'esmodule' &&
287
+ !bundle.env.isIsolated() &&
288
+ bundle.bundleBehavior !== 'isolated' &&
289
+ !this.bundleGraph.hasParentBundleOfType(bundle, 'js')
290
+ );
291
+ }
292
+
293
+ runWhenReady(bundle: NamedBundle, codeToRun: string): string {
294
+ let deps = this.bundleGraph
295
+ .getReferencedBundles(bundle)
296
+ .filter(b => this.shouldBundleQueue(b))
297
+ .map(b => b.publicId);
298
+
299
+ if (deps.length === 0) {
300
+ // If no deps we can safely execute immediately
301
+ return codeToRun;
302
+ }
303
+
304
+ let params = [
305
+ JSON.stringify(this.bundle.publicId),
306
+ fnExpr(this.bundle.env, [], [codeToRun]),
307
+ JSON.stringify(deps),
308
+ ];
309
+
310
+ return `$parcel$global.rwr(${params.join(', ')});`;
311
+ }
312
+
250
313
  async loadAssets(): Promise<Array<Asset>> {
251
314
  let queue = new PromiseQueue({maxConcurrent: 32});
252
315
  let wrapped = [];
@@ -268,8 +331,10 @@ export class ScopeHoistingPackager {
268
331
  .getIncomingDependencies(asset)
269
332
  .some(dep => dep.meta.shouldWrap && dep.specifierType !== 'url')
270
333
  ) {
271
- this.wrappedAssets.add(asset.id);
272
- wrapped.push(asset);
334
+ if (!asset.meta.isConstantModule) {
335
+ this.wrappedAssets.add(asset.id);
336
+ wrapped.push(asset);
337
+ }
273
338
  }
274
339
  });
275
340
 
@@ -283,9 +348,10 @@ export class ScopeHoistingPackager {
283
348
  actions.skipChildren();
284
349
  return;
285
350
  }
286
-
287
- this.wrappedAssets.add(asset.id);
288
- wrapped.push(asset);
351
+ if (!asset.meta.isConstantModule) {
352
+ this.wrappedAssets.add(asset.id);
353
+ wrapped.push(asset);
354
+ }
289
355
  }, wrappedAssetRoot);
290
356
  }
291
357
 
@@ -561,7 +627,7 @@ export class ScopeHoistingPackager {
561
627
  sourceMap?.offsetLines(1, 1);
562
628
  lineCount++;
563
629
 
564
- code = `parcelRequire.register(${JSON.stringify(
630
+ code = `parcelRegister(${JSON.stringify(
565
631
  this.bundleGraph.getAssetPublicId(asset),
566
632
  )}, function(module, exports) {
567
633
  ${code}
@@ -582,6 +648,14 @@ ${code}
582
648
  this.needsPrelude = true;
583
649
  }
584
650
 
651
+ if (
652
+ !shouldWrap &&
653
+ this.shouldBundleQueue(this.bundle) &&
654
+ this.bundle.getEntryAssets().some(entry => entry.id === asset.id)
655
+ ) {
656
+ code = this.runWhenReady(this.bundle, code);
657
+ }
658
+
585
659
  return [code, sourceMap, lineCount];
586
660
  }
587
661
 
@@ -756,6 +830,20 @@ ${code}
756
830
  }
757
831
  }
758
832
 
833
+ isWrapped(resolved: Asset, parentAsset: Asset): boolean {
834
+ if (resolved.meta.isConstantModule) {
835
+ invariant(
836
+ this.bundle.hasAsset(resolved),
837
+ 'Constant module not found in bundle',
838
+ );
839
+ return false;
840
+ }
841
+ return (
842
+ (!this.bundle.hasAsset(resolved) && !this.externalAssets.has(resolved)) ||
843
+ (this.wrappedAssets.has(resolved.id) && resolved !== parentAsset)
844
+ );
845
+ }
846
+
759
847
  getSymbolResolution(
760
848
  parentAsset: Asset,
761
849
  resolved: Asset,
@@ -777,13 +865,18 @@ ${code}
777
865
  return '{}';
778
866
  }
779
867
 
780
- let isWrapped =
781
- !this.bundle.hasAsset(resolvedAsset) ||
782
- (this.wrappedAssets.has(resolvedAsset.id) &&
783
- resolvedAsset !== parentAsset);
868
+ let isWrapped = this.isWrapped(resolvedAsset, parentAsset);
784
869
  let staticExports = resolvedAsset.meta.staticExports !== false;
785
870
  let publicId = this.bundleGraph.getAssetPublicId(resolvedAsset);
786
871
 
872
+ // External CommonJS dependencies need to be accessed as an object property rather than imported
873
+ // directly to maintain live binding.
874
+ let isExternalCommonJS =
875
+ !isWrapped &&
876
+ this.bundle.env.isLibrary &&
877
+ this.bundle.env.outputFormat === 'commonjs' &&
878
+ !this.bundle.hasAsset(resolvedAsset);
879
+
787
880
  // If the resolved asset is wrapped, but imported at the top-level by this asset,
788
881
  // then we hoist parcelRequire calls to the top of this asset so side effects run immediately.
789
882
  if (
@@ -849,7 +942,7 @@ ${code}
849
942
  return obj;
850
943
  }
851
944
  } else if (
852
- (!staticExports || isWrapped || !symbol) &&
945
+ (!staticExports || isWrapped || !symbol || isExternalCommonJS) &&
853
946
  resolvedAsset !== parentAsset
854
947
  ) {
855
948
  // If the resolved asset is wrapped or has non-static exports,
@@ -887,9 +980,7 @@ ${code}
887
980
  let hoisted = this.hoistedRequires.get(dep.id);
888
981
  let res = '';
889
982
  let lineCount = 0;
890
- let isWrapped =
891
- !this.bundle.hasAsset(resolved) ||
892
- (this.wrappedAssets.has(resolved.id) && resolved !== parentAsset);
983
+ let isWrapped = this.isWrapped(resolved, parentAsset);
893
984
 
894
985
  // If the resolved asset is wrapped and is imported in the top-level by this asset,
895
986
  // we need to run side effects when this asset runs. If the resolved asset is not
@@ -1143,9 +1234,13 @@ ${code}
1143
1234
  }
1144
1235
 
1145
1236
  for (let helper of this.usedHelpers) {
1146
- res += helpers[helper];
1237
+ let currentHelper = helpers[helper];
1238
+ if (typeof currentHelper === 'function') {
1239
+ currentHelper = helpers[helper](this.bundle.env);
1240
+ }
1241
+ res += currentHelper;
1147
1242
  if (enableSourceMaps) {
1148
- lines += countLines(helpers[helper]) - 1;
1243
+ lines += countLines(currentHelper) - 1;
1149
1244
  }
1150
1245
  }
1151
1246
 
@@ -1168,11 +1263,20 @@ ${code}
1168
1263
  if (enableSourceMaps) {
1169
1264
  lines += countLines(preludeCode) - 1;
1170
1265
  }
1266
+
1267
+ if (this.shouldBundleQueue(this.bundle)) {
1268
+ let bundleQueuePreludeCode = bundleQueuePrelude(this.bundle.env);
1269
+ res += bundleQueuePreludeCode;
1270
+ if (enableSourceMaps) {
1271
+ lines += countLines(bundleQueuePreludeCode) - 1;
1272
+ }
1273
+ }
1171
1274
  } else {
1172
1275
  // Otherwise, get the current parcelRequire global.
1173
- res += `var parcelRequire = $parcel$global[${JSON.stringify(
1174
- this.parcelRequireName,
1175
- )}];\n`;
1276
+ const escaped = JSON.stringify(this.parcelRequireName);
1277
+ res += `var parcelRequire = $parcel$global[${escaped}];\n`;
1278
+ lines++;
1279
+ res += `var parcelRegister = parcelRequire.register;\n`;
1176
1280
  lines++;
1177
1281
  }
1178
1282
  }
package/src/helpers.js CHANGED
@@ -1,10 +1,12 @@
1
1
  // @flow strict-local
2
- export const prelude = (
3
- parcelRequireName: string,
4
- ): string => `var $parcel$modules = {};
2
+ import type {Environment} from '@parcel/types';
3
+
4
+ export const prelude = (parcelRequireName: string): string => `
5
+ var $parcel$modules = {};
5
6
  var $parcel$inits = {};
6
7
 
7
8
  var parcelRequire = $parcel$global[${JSON.stringify(parcelRequireName)}];
9
+
8
10
  if (parcelRequire == null) {
9
11
  parcelRequire = function(id) {
10
12
  if (id in $parcel$modules) {
@@ -29,14 +31,86 @@ if (parcelRequire == null) {
29
31
 
30
32
  $parcel$global[${JSON.stringify(parcelRequireName)}] = parcelRequire;
31
33
  }
34
+
35
+ var parcelRegister = parcelRequire.register;
32
36
  `;
33
37
 
34
- export const helpers = {
35
- $parcel$export: `function $parcel$export(e, n, v, s) {
38
+ export const fnExpr = (
39
+ env: Environment,
40
+ params: Array<string>,
41
+ body: Array<string>,
42
+ ): string => {
43
+ let block = `{ ${body.join(' ')} }`;
44
+
45
+ if (env.supports('arrow-functions')) {
46
+ return `(${params.join(', ')}) => ${block}`;
47
+ }
48
+
49
+ return `function (${params.join(', ')}) ${block}`;
50
+ };
51
+
52
+ export const bundleQueuePrelude = (env: Environment): string => `
53
+ if (!$parcel$global.lb) {
54
+ // Set of loaded bundles
55
+ $parcel$global.lb = new Set();
56
+ // Queue of bundles to execute once they're dep bundles are loaded
57
+ $parcel$global.bq = [];
58
+
59
+ // Register loaded bundle
60
+ $parcel$global.rlb = ${fnExpr(
61
+ env,
62
+ ['bundle'],
63
+ ['$parcel$global.lb.add(bundle);', '$parcel$global.pq();'],
64
+ )}
65
+
66
+ // Run when ready
67
+ $parcel$global.rwr = ${fnExpr(
68
+ env,
69
+ // b = bundle public id
70
+ // r = run function to execute the bundle entry
71
+ // d = list of dependent bundles this bundle requires before executing
72
+ ['b', 'r', 'd'],
73
+ ['$parcel$global.bq.push({b, r, d});', '$parcel$global.pq();'],
74
+ )}
75
+
76
+ // Process queue
77
+ $parcel$global.pq = ${fnExpr(
78
+ env,
79
+ [],
80
+ [
81
+ `var runnableEntry = $parcel$global.bq.find(${fnExpr(
82
+ env,
83
+ ['i'],
84
+ [
85
+ `return i.d.every(${fnExpr(
86
+ env,
87
+ ['dep'],
88
+ ['return $parcel$global.lb.has(dep);'],
89
+ )});`,
90
+ ],
91
+ )});`,
92
+ 'if (runnableEntry) {',
93
+ `$parcel$global.bq = $parcel$global.bq.filter(${fnExpr(
94
+ env,
95
+ ['i'],
96
+ ['return i.b !== runnableEntry.b;'],
97
+ )});`,
98
+ 'runnableEntry.r();',
99
+ '$parcel$global.pq();',
100
+ '}',
101
+ ],
102
+ )}
103
+ }
104
+ `;
105
+
106
+ const $parcel$export = `
107
+ function $parcel$export(e, n, v, s) {
36
108
  Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
37
109
  }
38
- `,
39
- $parcel$exportWildcard: `function $parcel$exportWildcard(dest, source) {
110
+ `;
111
+
112
+ const $parcel$exportWildcard = `
113
+ function $parcel$exportWildcard(dest, source) {
40
114
  Object.keys(source).forEach(function(key) {
41
115
  if (key === 'default' || key === '__esModule' || dest.hasOwnProperty(key)) {
42
116
  return;
@@ -52,24 +126,44 @@ export const helpers = {
52
126
 
53
127
  return dest;
54
128
  }
55
- `,
56
- $parcel$interopDefault: `function $parcel$interopDefault(a) {
129
+ `;
130
+
131
+ const $parcel$interopDefault = `
132
+ function $parcel$interopDefault(a) {
57
133
  return a && a.__esModule ? a.default : a;
58
134
  }
59
- `,
60
- $parcel$global: `var $parcel$global =
61
- typeof globalThis !== 'undefined'
62
- ? globalThis
63
- : typeof self !== 'undefined'
64
- ? self
65
- : typeof window !== 'undefined'
66
- ? window
67
- : typeof global !== 'undefined'
68
- ? global
69
- : {};
70
- `,
71
- $parcel$defineInteropFlag: `function $parcel$defineInteropFlag(a) {
135
+ `;
136
+
137
+ const $parcel$global = (env: Environment): string => {
138
+ if (env.supports('global-this')) {
139
+ return `
140
+ var $parcel$global = globalThis;
141
+ `;
142
+ }
143
+ return `
144
+ var $parcel$global =
145
+ typeof globalThis !== 'undefined'
146
+ ? globalThis
147
+ : typeof self !== 'undefined'
148
+ ? self
149
+ : typeof window !== 'undefined'
150
+ ? window
151
+ : typeof global !== 'undefined'
152
+ ? global
153
+ : {};
154
+ `;
155
+ };
156
+
157
+ const $parcel$defineInteropFlag = `
158
+ function $parcel$defineInteropFlag(a) {
72
159
  Object.defineProperty(a, '__esModule', {value: true, configurable: true});
73
160
  }
74
- `,
161
+ `;
162
+
163
+ export const helpers = {
164
+ $parcel$export,
165
+ $parcel$exportWildcard,
166
+ $parcel$interopDefault,
167
+ $parcel$global,
168
+ $parcel$defineInteropFlag,
75
169
  };
package/src/index.js CHANGED
@@ -2,24 +2,65 @@
2
2
  import type {Async} from '@parcel/types';
3
3
  import type SourceMap from '@parcel/source-map';
4
4
  import {Packager} from '@parcel/plugin';
5
- import {replaceInlineReferences, replaceURLReferences} from '@parcel/utils';
6
- import {hashString} from '@parcel/hash';
5
+ import {
6
+ replaceInlineReferences,
7
+ replaceURLReferences,
8
+ validateSchema,
9
+ type SchemaEntity,
10
+ } from '@parcel/utils';
11
+ import {encodeJSONKeyComponent} from '@parcel/diagnostic';
12
+ import {hashString} from '@parcel/rust';
7
13
  import path from 'path';
8
14
  import nullthrows from 'nullthrows';
9
15
  import {DevPackager} from './DevPackager';
10
16
  import {ScopeHoistingPackager} from './ScopeHoistingPackager';
11
17
 
18
+ type JSPackagerConfig = {|
19
+ parcelRequireName: string,
20
+ unstable_asyncBundleRuntime: boolean,
21
+ |};
22
+
23
+ const CONFIG_SCHEMA: SchemaEntity = {
24
+ type: 'object',
25
+ properties: {
26
+ unstable_asyncBundleRuntime: {
27
+ type: 'boolean',
28
+ },
29
+ },
30
+ additionalProperties: false,
31
+ };
32
+
12
33
  export default (new Packager({
13
- async loadConfig({config, options}) {
34
+ async loadConfig({config, options}): Promise<JSPackagerConfig> {
14
35
  // Generate a name for the global parcelRequire function that is unique to this project.
15
36
  // This allows multiple parcel builds to coexist on the same page.
16
37
  let pkg = await config.getConfigFrom(
17
38
  path.join(options.projectRoot, 'index'),
18
39
  ['package.json'],
19
40
  );
41
+
42
+ let packageKey = '@parcel/packager-js';
43
+
44
+ if (pkg?.contents[packageKey]) {
45
+ validateSchema.diagnostic(
46
+ CONFIG_SCHEMA,
47
+ {
48
+ data: pkg?.contents[packageKey],
49
+ source: await options.inputFS.readFile(pkg.filePath, 'utf8'),
50
+ filePath: pkg.filePath,
51
+ prependKey: `/${encodeJSONKeyComponent(packageKey)}`,
52
+ },
53
+ packageKey,
54
+ `Invalid config for ${packageKey}`,
55
+ );
56
+ }
57
+
20
58
  let name = pkg?.contents?.name ?? '';
21
59
  return {
22
60
  parcelRequireName: 'parcelRequire' + hashString(name).slice(-4),
61
+ unstable_asyncBundleRuntime: Boolean(
62
+ pkg?.contents[packageKey]?.unstable_asyncBundleRuntime,
63
+ ),
23
64
  };
24
65
  },
25
66
  async package({
@@ -51,6 +92,7 @@ export default (new Packager({
51
92
  bundleGraph,
52
93
  bundle,
53
94
  nullthrows(config).parcelRequireName,
95
+ nullthrows(config).unstable_asyncBundleRuntime,
54
96
  )
55
97
  : new DevPackager(
56
98
  options,