@atlaspack/packager-js 2.14.5-canary.36 → 2.14.5-canary.361

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.
@@ -1,5 +1,3 @@
1
- // @flow
2
-
3
1
  import type {
4
2
  Asset,
5
3
  BundleGraph,
@@ -15,8 +13,10 @@ import {
15
13
  relativeBundlePath,
16
14
  countLines,
17
15
  normalizeSeparators,
16
+ debugTools,
17
+ globToRegex,
18
18
  } from '@atlaspack/utils';
19
- import SourceMap from '@parcel/source-map';
19
+ import SourceMap from '@atlaspack/source-map';
20
20
  import nullthrows from 'nullthrows';
21
21
  import invariant, {AssertionError} from 'assert';
22
22
  import ThrowableDiagnostic, {
@@ -25,11 +25,18 @@ import ThrowableDiagnostic, {
25
25
  import globals from 'globals';
26
26
  import path from 'path';
27
27
  import {getFeatureFlag} from '@atlaspack/feature-flags';
28
+ import {outdent} from 'outdent';
28
29
 
29
30
  import {ESMOutputFormat} from './ESMOutputFormat';
30
31
  import {CJSOutputFormat} from './CJSOutputFormat';
31
32
  import {GlobalOutputFormat} from './GlobalOutputFormat';
32
- import {prelude, helpers, bundleQueuePrelude, fnExpr} from './helpers';
33
+ import {
34
+ preludeOld,
35
+ preludeNew,
36
+ helpers,
37
+ bundleQueuePrelude,
38
+ fnExpr,
39
+ } from './helpers';
33
40
  import {
34
41
  replaceScriptDependencies,
35
42
  getSpecifier,
@@ -39,7 +46,6 @@ import {
39
46
 
40
47
  // General regex used to replace imports with the resolved code, references with resolutions,
41
48
  // and count the number of newlines in the file for source maps.
42
- //
43
49
  // For conditional bundling the only difference in this regex is adding `importCond` where we have `importAsync` etc..
44
50
  const REPLACEMENT_RE_CONDITIONAL =
45
51
  /\n|import\s+"([0-9a-f]{16,20}:.+?)";|(?:\$[0-9a-f]{16,20}\$exports)|(?:\$[0-9a-f]{16,20}\$(?:import|importAsync|require|importCond)\$[0-9a-f]+(?:\$[0-9a-f]+)?)/g;
@@ -55,6 +61,7 @@ const GLOBALS_BY_CONTEXT = {
55
61
  ...Object.keys(globals.serviceworker),
56
62
  ]),
57
63
  worklet: new Set([...BUILTINS]),
64
+ tesseract: new Set([...BUILTINS, ...Object.keys(globals.worker)]),
58
65
  node: new Set([...BUILTINS, ...Object.keys(globals.node)]),
59
66
  'electron-main': new Set([...BUILTINS, ...Object.keys(globals.node)]),
60
67
  'electron-renderer': new Set([
@@ -62,19 +69,28 @@ const GLOBALS_BY_CONTEXT = {
62
69
  ...Object.keys(globals.node),
63
70
  ...Object.keys(globals.browser),
64
71
  ]),
65
- };
72
+ } as const;
66
73
 
67
74
  const OUTPUT_FORMATS = {
68
75
  esmodule: ESMOutputFormat,
69
76
  commonjs: CJSOutputFormat,
70
77
  global: GlobalOutputFormat,
71
- };
78
+ } as const;
72
79
 
73
80
  export interface OutputFormat {
74
81
  buildBundlePrelude(): [string, number];
75
82
  buildBundlePostlude(): [string, number];
76
83
  }
77
84
 
85
+ export type PackageResult = {
86
+ contents: string;
87
+ map: SourceMap | null | undefined;
88
+ scopeHoistingStats?: {
89
+ totalAssets: number;
90
+ wrappedAssets: number;
91
+ };
92
+ };
93
+
78
94
  export class ScopeHoistingPackager {
79
95
  options: PluginOptions;
80
96
  bundleGraph: BundleGraph<NamedBundle>;
@@ -83,27 +99,39 @@ export class ScopeHoistingPackager {
83
99
  useAsyncBundleRuntime: boolean;
84
100
  outputFormat: OutputFormat;
85
101
  isAsyncBundle: boolean;
86
- globalNames: $ReadOnlySet<string>;
87
- assetOutputs: Map<string, {|code: string, map: ?Buffer|}>;
102
+ globalNames: ReadonlySet<string>;
103
+ manualStaticBindingExports: RegExp[] | null;
104
+ assetOutputs: Map<
105
+ Asset,
106
+ {
107
+ code: string;
108
+ map: Buffer | null | undefined;
109
+ }
110
+ > = new Map();
88
111
  exportedSymbols: Map<
89
112
  string,
90
- {|
91
- asset: Asset,
92
- exportSymbol: string,
93
- local: string,
94
- exportAs: Array<string>,
95
- |},
113
+ {
114
+ asset: Asset;
115
+ exportSymbol: string;
116
+ local: string;
117
+ exportAs: Array<string>;
118
+ }
96
119
  > = new Map();
97
120
  externals: Map<string, Map<string, string>> = new Map();
98
121
  topLevelNames: Map<string, number> = new Map();
99
- seenAssets: Set<string> = new Set();
100
- wrappedAssets: Set<string> = new Set();
101
- hoistedRequires: Map<string, Map<string, string>> = new Map();
122
+ seenAssets: Set<Asset> = new Set();
123
+ wrappedAssets: Set<Asset> = new Set();
124
+ constantAssets: Set<Asset> = new Set();
125
+ hoistedRequires: Map<Dependency, Map<Asset, string>> = new Map();
126
+ seenHoistedRequires: Set<string> = new Set();
102
127
  needsPrelude: boolean = false;
103
128
  usedHelpers: Set<string> = new Set();
104
129
  externalAssets: Set<Asset> = new Set();
105
- forceSkipWrapAssets: Array<string> = [];
106
130
  logger: PluginLogger;
131
+ useBothScopeHoistingImprovements: boolean =
132
+ getFeatureFlag('applyScopeHoistingImprovementV2') ||
133
+ getFeatureFlag('applyScopeHoistingImprovement');
134
+ referencedAssetsCache: Map<string, Set<Asset>> = new Map();
107
135
 
108
136
  constructor(
109
137
  options: PluginOptions,
@@ -111,7 +139,7 @@ export class ScopeHoistingPackager {
111
139
  bundle: NamedBundle,
112
140
  parcelRequireName: string,
113
141
  useAsyncBundleRuntime: boolean,
114
- forceSkipWrapAssets: Array<string>,
142
+ manualStaticBindingExports: string[] | null,
115
143
  logger: PluginLogger,
116
144
  ) {
117
145
  this.options = options;
@@ -119,7 +147,8 @@ export class ScopeHoistingPackager {
119
147
  this.bundle = bundle;
120
148
  this.parcelRequireName = parcelRequireName;
121
149
  this.useAsyncBundleRuntime = useAsyncBundleRuntime;
122
- this.forceSkipWrapAssets = forceSkipWrapAssets ?? [];
150
+ this.manualStaticBindingExports =
151
+ manualStaticBindingExports?.map((glob) => globToRegex(glob)) ?? null;
123
152
  this.logger = logger;
124
153
 
125
154
  let OutputFormat = OUTPUT_FORMATS[this.bundle.env.outputFormat];
@@ -128,13 +157,14 @@ export class ScopeHoistingPackager {
128
157
  this.isAsyncBundle =
129
158
  this.bundleGraph.hasParentBundleOfType(this.bundle, 'js') &&
130
159
  !this.bundle.env.isIsolated() &&
131
- this.bundle.bundleBehavior !== 'isolated';
160
+ this.bundle.bundleBehavior !== 'isolated' &&
161
+ this.bundle.bundleBehavior !== 'inlineIsolated';
132
162
 
133
163
  this.globalNames = GLOBALS_BY_CONTEXT[bundle.env.context];
134
164
  }
135
165
 
136
- async package(): Promise<{|contents: string, map: ?SourceMap|}> {
137
- let wrappedAssets = await this.loadAssets();
166
+ async package(): Promise<PackageResult> {
167
+ await this.loadAssets();
138
168
  this.buildExportedSymbols();
139
169
 
140
170
  // If building a library, the target is actually another bundler rather
@@ -155,9 +185,11 @@ export class ScopeHoistingPackager {
155
185
 
156
186
  let res = '';
157
187
  let lineCount = 0;
158
- let sourceMap = null;
159
- let processAsset = (asset) => {
188
+ let sourceMap: SourceMap | null | undefined = null;
189
+ let processAsset = (asset: Asset) => {
190
+ this.seenHoistedRequires.clear();
160
191
  let [content, map, lines] = this.visitAsset(asset);
192
+
161
193
  if (sourceMap && map) {
162
194
  sourceMap.addSourceMap(map, lineCount);
163
195
  } else if (this.bundle.env.sourceMap) {
@@ -168,10 +200,22 @@ export class ScopeHoistingPackager {
168
200
  lineCount += lines + 1;
169
201
  };
170
202
 
203
+ if (
204
+ getFeatureFlag('inlineConstOptimisationFix') ||
205
+ this.useBothScopeHoistingImprovements
206
+ ) {
207
+ // Write out all constant modules used by this bundle
208
+ for (let asset of this.constantAssets) {
209
+ if (!this.seenAssets.has(asset)) {
210
+ processAsset(asset);
211
+ }
212
+ }
213
+ }
214
+
171
215
  // Hoist wrapped asset to the top of the bundle to ensure that they are registered
172
216
  // before they are used.
173
- for (let asset of wrappedAssets) {
174
- if (!this.seenAssets.has(asset.id)) {
217
+ for (let asset of this.wrappedAssets) {
218
+ if (!this.seenAssets.has(asset)) {
175
219
  processAsset(asset);
176
220
  }
177
221
  }
@@ -179,7 +223,7 @@ export class ScopeHoistingPackager {
179
223
  // Add each asset that is directly connected to the bundle. Dependencies will be handled
180
224
  // by replacing `import` statements in the code.
181
225
  this.bundle.traverseAssets((asset, _, actions) => {
182
- if (this.seenAssets.has(asset.id)) {
226
+ if (this.seenAssets.has(asset)) {
183
227
  actions.skipChildren();
184
228
  return;
185
229
  }
@@ -191,14 +235,28 @@ export class ScopeHoistingPackager {
191
235
  let [prelude, preludeLines] = this.buildBundlePrelude();
192
236
  res = prelude + res;
193
237
  lineCount += preludeLines;
238
+ // @ts-expect-error TS2339 - offsetLines method exists but missing from @parcel/source-map type definitions
194
239
  sourceMap?.offsetLines(1, preludeLines);
195
240
 
196
241
  let entries = this.bundle.getEntryAssets();
197
242
  let mainEntry = this.bundle.getMainEntry();
198
243
  if (this.isAsyncBundle) {
199
- // In async bundles we don't want the main entry to execute until we require it
200
- // as there might be dependencies in a sibling bundle that hasn't loaded yet.
201
- entries = entries.filter((a) => a.id !== mainEntry?.id);
244
+ if (
245
+ this.useBothScopeHoistingImprovements ||
246
+ getFeatureFlag('supportWebpackChunkName')
247
+ ) {
248
+ // Generally speaking, async bundles should not be executed on load, as
249
+ // they're just collections of assets that other assets require.
250
+ // However, there are some special cases where a runtime asset needs to be
251
+ // injected, but no other asset will require it (mostly the bundle
252
+ // manifest).
253
+ // In this case, those assets need to be required on load.
254
+ entries = entries.filter(
255
+ (a) => a.meta?.runtimeAssetRequiringExecutionOnLoad,
256
+ );
257
+ } else {
258
+ entries = entries.filter((a) => a.id !== mainEntry?.id);
259
+ }
202
260
  mainEntry = null;
203
261
  }
204
262
 
@@ -206,7 +264,7 @@ export class ScopeHoistingPackager {
206
264
 
207
265
  // If any of the entry assets are wrapped, call parcelRequire so they are executed.
208
266
  for (let entry of entries) {
209
- if (this.wrappedAssets.has(entry.id) && !this.isScriptEntry(entry)) {
267
+ if (this.wrappedAssets.has(entry) && !this.isScriptEntry(entry)) {
210
268
  let parcelRequire = `parcelRequire(${JSON.stringify(
211
269
  this.bundleGraph.getAssetPublicId(entry),
212
270
  )});\n`;
@@ -250,9 +308,7 @@ export class ScopeHoistingPackager {
250
308
  lineCount++;
251
309
 
252
310
  let mainEntry = nullthrows(this.bundle.getMainEntry());
253
- let {code, map: mapBuffer} = nullthrows(
254
- this.assetOutputs.get(mainEntry.id),
255
- );
311
+ let {code, map: mapBuffer} = nullthrows(this.assetOutputs.get(mainEntry));
256
312
  let map;
257
313
  if (mapBuffer) {
258
314
  map = new SourceMap(this.options.projectRoot, mapBuffer);
@@ -265,14 +321,21 @@ export class ScopeHoistingPackager {
265
321
  this.parcelRequireName,
266
322
  );
267
323
  if (sourceMap && map) {
324
+ // @ts-expect-error TS2339 - addSourceMap method exists but missing from @parcel/source-map type definitions
268
325
  sourceMap.addSourceMap(map, lineCount);
269
326
  }
270
327
  }
271
328
 
272
- return {
273
- contents: res,
274
- map: sourceMap,
275
- };
329
+ const result: PackageResult = {contents: res, map: sourceMap};
330
+
331
+ if (debugTools['scope-hoisting-stats']) {
332
+ result.scopeHoistingStats = {
333
+ totalAssets: this.assetOutputs.size,
334
+ wrappedAssets: this.wrappedAssets.size,
335
+ };
336
+ }
337
+
338
+ return result;
276
339
  }
277
340
 
278
341
  shouldBundleQueue(bundle: NamedBundle): boolean {
@@ -281,10 +344,7 @@ export class ScopeHoistingPackager {
281
344
 
282
345
  let hasConditionalReference = false;
283
346
  let isConditionalBundle = false;
284
- if (
285
- getFeatureFlag('conditionalBundlingApi') &&
286
- getFeatureFlag('conditionalBundlingAsyncRuntime')
287
- ) {
347
+ if (getFeatureFlag('conditionalBundlingApi')) {
288
348
  // If the bundle has a conditional bundle reference (has an importCond)
289
349
  hasConditionalReference =
290
350
  this.bundleGraph.getReferencedConditionalBundles(bundle).length > 0;
@@ -296,6 +356,7 @@ export class ScopeHoistingPackager {
296
356
  this.useAsyncBundleRuntime &&
297
357
  bundle.type === 'js' &&
298
358
  bundle.bundleBehavior !== 'inline' &&
359
+ bundle.bundleBehavior !== 'inlineIsolated' &&
299
360
  bundle.env.outputFormat === 'esmodule' &&
300
361
  !bundle.env.isIsolated() &&
301
362
  bundle.bundleBehavior !== 'isolated' &&
@@ -309,11 +370,8 @@ export class ScopeHoistingPackager {
309
370
  .filter((b) => this.shouldBundleQueue(b))
310
371
  .map((b) => b.publicId);
311
372
 
312
- const conditions = [];
313
- if (
314
- getFeatureFlag('conditionalBundlingApi') &&
315
- getFeatureFlag('conditionalBundlingAsyncRuntime')
316
- ) {
373
+ const conditions: Array<string> = [];
374
+ if (getFeatureFlag('conditionalBundlingApi')) {
317
375
  const conditionSet = this.bundleGraph
318
376
  .getConditionalBundleMapping()
319
377
  .get(bundle.id);
@@ -354,22 +412,58 @@ export class ScopeHoistingPackager {
354
412
  return `$parcel$global.rwr(${params.join(', ')});`;
355
413
  }
356
414
 
357
- async loadAssets(): Promise<Array<Asset>> {
358
- let queue = new PromiseQueue({maxConcurrent: 32});
359
- let wrapped = [];
415
+ // Helper to check if an asset is referenced, with cache-first + fast-check hybrid approach
416
+ isAssetReferencedInBundle(bundle: NamedBundle, asset: Asset): boolean {
417
+ // STEP 1: Check expensive computation cache first (fastest when it hits)
418
+
419
+ let bundleId = bundle.id;
420
+ let referencedAssets = this.referencedAssetsCache.get(bundleId);
421
+
422
+ if (referencedAssets) {
423
+ // Cache hit - fastest path (~0.001ms)
424
+ return referencedAssets.has(asset);
425
+ }
426
+
427
+ // STEP 2: Cache miss - try fast checks (~0.01ms)
428
+ let fastCheckResult = this.bundleGraph.isAssetReferencedFastCheck(
429
+ bundle,
430
+ asset,
431
+ );
432
+
433
+ if (fastCheckResult === true) {
434
+ // Fast check succeeded - asset is referenced
435
+ return true;
436
+ }
437
+
438
+ // STEP 3: Need expensive computation (~20-2000ms)
439
+
440
+ // Compute and cache expensive results for this bundle
441
+ referencedAssets = this.bundleGraph.getReferencedAssets(bundle);
442
+ this.referencedAssetsCache.set(bundleId, referencedAssets);
443
+
444
+ return referencedAssets.has(asset);
445
+ }
446
+
447
+ async loadAssets() {
448
+ type QueueItem = [Asset, {code: string; map: Buffer | undefined | null}];
449
+ let queue = new PromiseQueue<QueueItem>({
450
+ maxConcurrent: 32,
451
+ });
452
+
360
453
  this.bundle.traverseAssets((asset) => {
361
454
  queue.add(async () => {
362
455
  let [code, map] = await Promise.all([
363
456
  asset.getCode(),
364
457
  this.bundle.env.sourceMap ? asset.getMapBuffer() : null,
365
458
  ]);
366
- return [asset.id, {code, map}];
459
+
460
+ return [asset, {code, map}];
367
461
  });
368
462
 
369
463
  if (
370
464
  asset.meta.shouldWrap ||
371
465
  this.bundle.env.sourceType === 'script' ||
372
- this.bundleGraph.isAssetReferenced(this.bundle, asset) ||
466
+ this.isAssetReferencedInBundle(this.bundle, asset) ||
373
467
  this.bundleGraph
374
468
  .getIncomingDependencies(asset)
375
469
  .some((dep) => dep.meta.shouldWrap && dep.specifierType !== 'url')
@@ -381,52 +475,113 @@ export class ScopeHoistingPackager {
381
475
  .getIncomingDependencies(asset)
382
476
  .some((dep) => dep.priority === 'lazy')
383
477
  ) {
384
- this.wrappedAssets.add(asset.id);
385
- wrapped.push(asset);
478
+ this.wrappedAssets.add(asset);
479
+ } else if (
480
+ (getFeatureFlag('inlineConstOptimisationFix') ||
481
+ this.useBothScopeHoistingImprovements) &&
482
+ asset.meta.isConstantModule
483
+ ) {
484
+ this.constantAssets.add(asset);
386
485
  }
387
486
  }
388
487
  });
389
488
 
390
- for (let wrappedAssetRoot of [...wrapped]) {
391
- this.bundle.traverseAssets((asset, _, actions) => {
392
- if (asset === wrappedAssetRoot) {
393
- return;
489
+ if (this.useBothScopeHoistingImprovements) {
490
+ // Tracks which assets have been assigned to a wrap group
491
+ let assignedAssets = new Set<Asset>();
492
+
493
+ // In V2 scope hoisting, we iterate from the main entry, rather than
494
+ // wrapping the entry assets
495
+ if (!getFeatureFlag('applyScopeHoistingImprovementV2')) {
496
+ // Make all entry assets wrapped, to avoid any top level hoisting
497
+ for (let entryAsset of this.bundle.getEntryAssets()) {
498
+ if (!this.wrappedAssets.has(entryAsset)) {
499
+ this.wrappedAssets.add(entryAsset);
500
+ }
394
501
  }
502
+ }
395
503
 
396
- if (this.wrappedAssets.has(asset.id)) {
397
- actions.skipChildren();
398
- return;
399
- }
400
- // This prevents children of a wrapped asset also being wrapped - it's an "unsafe" optimisation
401
- // that should only be used when you know (or think you know) what you're doing.
402
- //
403
- // In particular this can force an async bundle to be scope hoisted where it previously would not be
404
- // due to the entry asset being wrapped.
405
- if (
406
- this.forceSkipWrapAssets.length > 0 &&
407
- this.forceSkipWrapAssets.some(
408
- (p) =>
409
- p === path.relative(this.options.projectRoot, asset.filePath),
410
- )
411
- ) {
412
- this.logger.verbose({
413
- message: `Force skipping wrapping of ${path.relative(
414
- this.options.projectRoot,
415
- asset.filePath,
416
- )}`,
417
- });
418
- actions.skipChildren();
419
- return;
420
- }
421
- if (!asset.meta.isConstantModule) {
422
- this.wrappedAssets.add(asset.id);
423
- wrapped.push(asset);
504
+ // We need to make a new copy here so that we can add to the list and
505
+ // iterate the newly added items, without mutating the wrappedAssets set
506
+ let moduleGroupParents = [...this.wrappedAssets.values()];
507
+
508
+ if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
509
+ // The main entry needs to be check to find assets that would have gone in
510
+ // the top level scope
511
+ let mainEntry = this.bundle.getMainEntry();
512
+ if (mainEntry && !this.wrappedAssets.has(mainEntry)) {
513
+ moduleGroupParents.unshift(mainEntry);
424
514
  }
425
- }, wrappedAssetRoot);
515
+ }
516
+
517
+ for (let moduleGroupParentAsset of moduleGroupParents) {
518
+ this.bundle.traverseAssets((asset, _, actions) => {
519
+ if (asset === moduleGroupParentAsset) {
520
+ return;
521
+ }
522
+
523
+ if (this.wrappedAssets.has(asset)) {
524
+ actions.skipChildren();
525
+ return;
526
+ }
527
+
528
+ if (
529
+ !asset.meta.isConstantModule &&
530
+ (assignedAssets.has(asset) || this.isReExported(asset))
531
+ ) {
532
+ this.wrappedAssets.add(asset);
533
+
534
+ // This also needs to be added to the traversal so that we iterate
535
+ // it during this check.
536
+ moduleGroupParents.push(asset);
537
+
538
+ actions.skipChildren();
539
+ return;
540
+ }
541
+
542
+ assignedAssets.add(asset);
543
+ }, moduleGroupParentAsset);
544
+ }
545
+ } else {
546
+ for (let wrappedAssetRoot of this.wrappedAssets) {
547
+ this.bundle.traverseAssets((asset, _, actions) => {
548
+ if (asset === wrappedAssetRoot) {
549
+ return;
550
+ }
551
+
552
+ if (this.wrappedAssets.has(asset)) {
553
+ actions.skipChildren();
554
+ return;
555
+ }
556
+
557
+ if (!asset.meta.isConstantModule) {
558
+ this.wrappedAssets.add(asset);
559
+ }
560
+ }, wrappedAssetRoot);
561
+ }
426
562
  }
427
563
 
428
564
  this.assetOutputs = new Map(await queue.run());
429
- return wrapped;
565
+ }
566
+
567
+ isReExported(asset: Asset): boolean {
568
+ let parentSymbols = this.bundleGraph
569
+ .getIncomingDependencies(asset)
570
+ .map((dep) => this.bundleGraph.getAssetWithDependency(dep))
571
+ .flatMap((parent) => {
572
+ if (parent == null) {
573
+ return [];
574
+ }
575
+ return this.bundleGraph.getExportedSymbols(parent, this.bundle);
576
+ });
577
+
578
+ let assetSymbols = this.bundleGraph.getExportedSymbols(asset, this.bundle);
579
+
580
+ return assetSymbols.some((assetSymbol) =>
581
+ parentSymbols.some(
582
+ (parentSymbol) => parentSymbol.symbol === assetSymbol.symbol,
583
+ ),
584
+ );
430
585
  }
431
586
 
432
587
  buildExportedSymbols() {
@@ -439,7 +594,7 @@ export class ScopeHoistingPackager {
439
594
 
440
595
  // TODO: handle ESM exports of wrapped entry assets...
441
596
  let entry = this.bundle.getMainEntry();
442
- if (entry && !this.wrappedAssets.has(entry.id)) {
597
+ if (entry && !this.wrappedAssets.has(entry)) {
443
598
  let hasNamespace = entry.symbols.hasExportSymbol('*');
444
599
 
445
600
  for (let {
@@ -464,6 +619,7 @@ export class ScopeHoistingPackager {
464
619
  symbols = [];
465
620
  this.exportedSymbols.set(symbol, {
466
621
  asset,
622
+
467
623
  exportSymbol,
468
624
  local: symbol,
469
625
  exportAs: symbols,
@@ -519,20 +675,24 @@ export class ScopeHoistingPackager {
519
675
  return `${obj}[${JSON.stringify(property)}]`;
520
676
  }
521
677
 
522
- visitAsset(asset: Asset): [string, ?SourceMap, number] {
523
- invariant(!this.seenAssets.has(asset.id), 'Already visited asset');
524
- this.seenAssets.add(asset.id);
678
+ visitAsset(asset: Asset): [string, SourceMap | null | undefined, number] {
679
+ invariant(!this.seenAssets.has(asset), 'Already visited asset');
680
+ this.seenAssets.add(asset);
525
681
 
526
- let {code, map} = nullthrows(this.assetOutputs.get(asset.id));
682
+ let {code, map} = nullthrows(this.assetOutputs.get(asset));
527
683
  return this.buildAsset(asset, code, map);
528
684
  }
529
685
 
686
+ getAssetFilePath(asset: Asset): string {
687
+ return path.relative(this.options.projectRoot, asset.filePath);
688
+ }
689
+
530
690
  buildAsset(
531
691
  asset: Asset,
532
692
  code: string,
533
- map: ?Buffer,
534
- ): [string, ?SourceMap, number] {
535
- let shouldWrap = this.wrappedAssets.has(asset.id);
693
+ map?: Buffer | null,
694
+ ): [string, SourceMap | null | undefined, number] {
695
+ let shouldWrap = this.wrappedAssets.has(asset);
536
696
  let deps = this.bundleGraph.getDependencies(asset);
537
697
 
538
698
  let sourceMap =
@@ -559,16 +719,29 @@ export class ScopeHoistingPackager {
559
719
  continue;
560
720
  }
561
721
 
562
- if (
563
- this.bundle.hasAsset(resolved) &&
564
- !this.seenAssets.has(resolved.id)
565
- ) {
566
- let [code, map, lines] = this.visitAsset(resolved);
567
- depCode += code + '\n';
568
- if (sourceMap && map) {
569
- sourceMap.addSourceMap(map, lineCount);
722
+ if (this.bundle.hasAsset(resolved) && !this.seenAssets.has(resolved)) {
723
+ if (
724
+ this.useBothScopeHoistingImprovements &&
725
+ this.wrappedAssets.has(resolved)
726
+ ) {
727
+ if (this.wrappedAssets.has(asset)) {
728
+ // If both the asset and the dep are wrapped there's no need to
729
+ // drop a side-effect require. This is an extremely rare case.
730
+ continue;
731
+ }
732
+
733
+ // When the dep is wrapped then we just need to drop a side effect
734
+ // require instead of inlining
735
+ depCode += `parcelRequire("${this.bundleGraph.getAssetPublicId(resolved)}");\n`;
736
+ lineCount += 1;
737
+ } else {
738
+ let [code, map, lines] = this.visitAsset(resolved);
739
+ depCode += code + '\n';
740
+ if (sourceMap && map) {
741
+ sourceMap.addSourceMap(map, lineCount);
742
+ }
743
+ lineCount += lines + 1;
570
744
  }
571
- lineCount += lines + 1;
572
745
  }
573
746
  }
574
747
 
@@ -602,7 +775,7 @@ export class ScopeHoistingPackager {
602
775
  code += append;
603
776
 
604
777
  let lineCount = 0;
605
- let depContent = [];
778
+ let depContent: Array<[string, SourceMap | null | undefined, number]> = [];
606
779
  if (depMap.size === 0 && replacements.size === 0) {
607
780
  // If there are no dependencies or replacements, use a simple function to count the number of lines.
608
781
  lineCount = countLines(code) - 1;
@@ -647,27 +820,68 @@ export class ScopeHoistingPackager {
647
820
  // after the dependency is declared. This handles the case where the resulting asset
648
821
  // is wrapped, but the dependency in this asset is not marked as wrapped. This means
649
822
  // that it was imported/required at the top-level, so its side effects should run immediately.
650
- let [res, lines] = this.getHoistedParcelRequires(
651
- asset,
652
- dep,
653
- resolved,
654
- );
823
+ let res = '';
824
+ let lines = 0;
655
825
  let map;
826
+
827
+ if (!getFeatureFlag('applyScopeHoistingImprovementV2')) {
828
+ [res, lines] = this.getHoistedParcelRequires(
829
+ asset,
830
+ dep,
831
+ resolved,
832
+ );
833
+ }
834
+
656
835
  if (
657
836
  this.bundle.hasAsset(resolved) &&
658
- !this.seenAssets.has(resolved.id)
837
+ !this.seenAssets.has(resolved)
659
838
  ) {
660
839
  // If this asset is wrapped, we need to hoist the code for the dependency
661
840
  // outside our parcelRequire.register wrapper. This is safe because all
662
841
  // assets referenced by this asset will also be wrapped. Otherwise, inline the
663
842
  // asset content where the import statement was.
664
- if (shouldWrap) {
665
- depContent.push(this.visitAsset(resolved));
843
+ if (this.useBothScopeHoistingImprovements) {
844
+ if (
845
+ !resolved.meta.isConstantModule &&
846
+ !this.wrappedAssets.has(resolved)
847
+ ) {
848
+ let [depCode, depMap, depLines] =
849
+ this.visitAsset(resolved);
850
+ if (debugTools['asset-file-names-in-output']) {
851
+ let resolvedPath = this.getAssetFilePath(resolved);
852
+ res = outdent`
853
+ /* Scope hoisted asset: ${resolvedPath} */
854
+ ${depCode}
855
+ /* End: ${resolvedPath} */
856
+ ${res}
857
+ `;
858
+ lines += 3 + depLines;
859
+ } else {
860
+ res = depCode + '\n' + res;
861
+ lines += 1 + depLines;
862
+ }
863
+ map = depMap;
864
+ }
666
865
  } else {
667
- let [depCode, depMap, depLines] = this.visitAsset(resolved);
668
- res = depCode + '\n' + res;
669
- lines += 1 + depLines;
670
- map = depMap;
866
+ if (shouldWrap) {
867
+ depContent.push(this.visitAsset(resolved));
868
+ } else {
869
+ let [depCode, depMap, depLines] =
870
+ this.visitAsset(resolved);
871
+ res = depCode + '\n' + res;
872
+ lines += 1 + depLines;
873
+ map = depMap;
874
+ }
875
+ }
876
+ }
877
+
878
+ if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
879
+ let [requiresCode, requiresLines] =
880
+ this.getHoistedParcelRequires(asset, dep, resolved);
881
+
882
+ if (requiresCode) {
883
+ res = requiresCode + '\n' + res;
884
+ lines += requiresLines + 1;
671
885
  }
672
886
  }
673
887
 
@@ -726,6 +940,11 @@ ${code}
726
940
 
727
941
  lineCount += 2;
728
942
 
943
+ if (debugTools['asset-file-names-in-output']) {
944
+ code = `/* ${this.getAssetFilePath(asset)} */\n` + code;
945
+ lineCount += 1;
946
+ }
947
+
729
948
  for (let [depCode, map, lines] of depContent) {
730
949
  if (!depCode) continue;
731
950
  code += depCode + '\n';
@@ -803,7 +1022,7 @@ ${code}
803
1022
  referencedBundle &&
804
1023
  referencedBundle.getMainEntry() === resolved &&
805
1024
  referencedBundle.type === 'js' &&
806
- !this.bundleGraph.isAssetReferenced(referencedBundle, resolved)
1025
+ !this.isAssetReferencedInBundle(referencedBundle, resolved)
807
1026
  ) {
808
1027
  this.addExternal(dep, replacements, referencedBundle);
809
1028
  this.externalAssets.add(resolved);
@@ -848,7 +1067,7 @@ ${code}
848
1067
  // If this asset is wrapped, we need to replace the exports namespace with `module.exports`,
849
1068
  // which will be provided to us by the wrapper.
850
1069
  if (
851
- this.wrappedAssets.has(asset.id) ||
1070
+ this.wrappedAssets.has(asset) ||
852
1071
  (this.bundle.env.outputFormat === 'commonjs' &&
853
1072
  asset === this.bundle.getMainEntry())
854
1073
  ) {
@@ -895,7 +1114,9 @@ ${code}
895
1114
 
896
1115
  for (let [imported, {local}] of dep.symbols) {
897
1116
  // If already imported, just add the already renamed variable to the mapping.
1117
+
898
1118
  let renamed = external.get(imported);
1119
+
899
1120
  if (renamed && local !== '*' && replacements) {
900
1121
  replacements.set(local, renamed);
901
1122
  continue;
@@ -908,6 +1129,7 @@ ${code}
908
1129
  if (!renamed) {
909
1130
  if (referencedBundle) {
910
1131
  let entry = nullthrows(referencedBundle.getMainEntry());
1132
+
911
1133
  renamed =
912
1134
  entry.symbols.get('*')?.local ??
913
1135
  `$${String(entry.meta.id)}$exports`;
@@ -922,6 +1144,7 @@ ${code}
922
1144
 
923
1145
  if (local !== '*' && replacements) {
924
1146
  let replacement;
1147
+
925
1148
  if (imported === '*') {
926
1149
  replacement = renamed;
927
1150
  } else if (imported === 'default') {
@@ -946,10 +1169,12 @@ ${code}
946
1169
  let property;
947
1170
  if (referencedBundle) {
948
1171
  let entry = nullthrows(referencedBundle.getMainEntry());
1172
+
949
1173
  if (entry.symbols.hasExportSymbol('*')) {
950
1174
  // If importing * and the referenced module has a * export (e.g. CJS), use default instead.
951
1175
  // This mirrors the logic in buildExportedSymbols.
952
1176
  property = imported;
1177
+
953
1178
  imported =
954
1179
  referencedBundle?.env.outputFormat === 'esmodule'
955
1180
  ? 'default'
@@ -957,6 +1182,7 @@ ${code}
957
1182
  } else {
958
1183
  if (imported === '*') {
959
1184
  let exportedSymbols = this.bundleGraph.getExportedSymbols(entry);
1185
+
960
1186
  if (local === '*') {
961
1187
  // Re-export all symbols.
962
1188
  for (let exported of exportedSymbols) {
@@ -967,11 +1193,10 @@ ${code}
967
1193
  continue;
968
1194
  }
969
1195
  }
970
- renamed = this.bundleGraph.getSymbolResolution(
971
- entry,
972
- imported,
973
- this.bundle,
974
- ).symbol;
1196
+
1197
+ renamed =
1198
+ this.bundleGraph.getSymbolResolution(entry, imported, this.bundle)
1199
+ .symbol || undefined;
975
1200
  }
976
1201
  }
977
1202
 
@@ -993,8 +1218,10 @@ ${code}
993
1218
  }
994
1219
 
995
1220
  external.set(imported, renamed);
1221
+
996
1222
  if (local !== '*' && replacements) {
997
1223
  let replacement = renamed;
1224
+
998
1225
  if (property === '*') {
999
1226
  replacement = renamed;
1000
1227
  } else if (property === 'default') {
@@ -1003,6 +1230,7 @@ ${code}
1003
1230
  } else if (property) {
1004
1231
  replacement = this.getPropertyAccess(renamed, property);
1005
1232
  }
1233
+
1006
1234
  replacements.set(local, replacement);
1007
1235
  }
1008
1236
  }
@@ -1026,7 +1254,7 @@ ${code}
1026
1254
  }
1027
1255
  return (
1028
1256
  (!this.bundle.hasAsset(resolved) && !this.externalAssets.has(resolved)) ||
1029
- (this.wrappedAssets.has(resolved.id) && resolved !== parentAsset)
1257
+ (this.wrappedAssets.has(resolved) && resolved !== parentAsset)
1030
1258
  );
1031
1259
  }
1032
1260
 
@@ -1076,14 +1304,14 @@ ${code}
1076
1304
  (!this.bundle.hasAsset(resolvedAsset) ||
1077
1305
  !this.shouldSkipAsset(resolvedAsset))
1078
1306
  ) {
1079
- let hoisted = this.hoistedRequires.get(dep.id);
1307
+ let hoisted = this.hoistedRequires.get(dep);
1080
1308
  if (!hoisted) {
1081
1309
  hoisted = new Map();
1082
- this.hoistedRequires.set(dep.id, hoisted);
1310
+ this.hoistedRequires.set(dep, hoisted);
1083
1311
  }
1084
1312
 
1085
1313
  hoisted.set(
1086
- resolvedAsset.id,
1314
+ resolvedAsset,
1087
1315
  `var $${publicId} = parcelRequire(${JSON.stringify(publicId)});`,
1088
1316
  );
1089
1317
  }
@@ -1117,6 +1345,7 @@ ${code}
1117
1345
  obj = `$${publicId}`;
1118
1346
  } else {
1119
1347
  obj = resolvedAsset.symbols.get('*')?.local || `$${assetId}$exports`;
1348
+
1120
1349
  obj = replacements?.get(obj) || obj;
1121
1350
  }
1122
1351
 
@@ -1124,7 +1353,7 @@ ${code}
1124
1353
  // Resolve to the namespace object if requested or this is a CJS default interop reqiure.
1125
1354
  if (
1126
1355
  parentAsset === resolvedAsset &&
1127
- this.wrappedAssets.has(resolvedAsset.id)
1356
+ this.wrappedAssets.has(resolvedAsset)
1128
1357
  ) {
1129
1358
  // Directly use module.exports for wrapped assets importing themselves.
1130
1359
  return 'module.exports';
@@ -1152,7 +1381,16 @@ ${code}
1152
1381
  return this.getPropertyAccess(obj, exportSymbol);
1153
1382
  }
1154
1383
  } else if (!symbol) {
1155
- invariant(false, 'Asset was skipped or not found.');
1384
+ let parentPath =
1385
+ path.relative(this.options.projectRoot, parentAsset.filePath) ||
1386
+ '<unknown>';
1387
+ let resolvedPath =
1388
+ path.relative(this.options.projectRoot, resolvedAsset.filePath) ||
1389
+ '<unknown>';
1390
+ invariant(
1391
+ false,
1392
+ `Asset was skipped or not found when packaging ${this.bundle.name}.\nSearching for exported symbol "${imported}" (resolved as "${exportSymbol}") in asset with id "${resolvedAsset.meta.id}" (public id: "${publicId}", path: "${resolvedPath}") from parent asset "${parentAsset.meta.id}" (path: "${parentPath}").`,
1393
+ );
1156
1394
  } else {
1157
1395
  return replacements?.get(symbol) || symbol;
1158
1396
  }
@@ -1167,7 +1405,7 @@ ${code}
1167
1405
  return ['', 0];
1168
1406
  }
1169
1407
 
1170
- let hoisted = this.hoistedRequires.get(dep.id);
1408
+ let hoisted = this.hoistedRequires.get(dep);
1171
1409
  let res = '';
1172
1410
  let lineCount = 0;
1173
1411
  let isWrapped = this.isWrapped(resolved, parentAsset);
@@ -1179,7 +1417,7 @@ ${code}
1179
1417
  if (
1180
1418
  isWrapped &&
1181
1419
  !dep.meta.shouldWrap &&
1182
- (!hoisted || hoisted.keys().next().value !== resolved.id) &&
1420
+ (!hoisted || hoisted.keys().next().value !== resolved) &&
1183
1421
  !this.bundleGraph.isDependencySkipped(dep) &&
1184
1422
  !this.shouldSkipAsset(resolved)
1185
1423
  ) {
@@ -1191,8 +1429,22 @@ ${code}
1191
1429
 
1192
1430
  if (hoisted) {
1193
1431
  this.needsPrelude = true;
1194
- res += '\n' + [...hoisted.values()].join('\n');
1195
- lineCount += hoisted.size;
1432
+
1433
+ if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
1434
+ let hoistedValues = [...hoisted.values()].filter(
1435
+ (val) => !this.seenHoistedRequires.has(val),
1436
+ );
1437
+
1438
+ for (let val of hoistedValues) {
1439
+ this.seenHoistedRequires.add(val);
1440
+ }
1441
+
1442
+ res += '\n' + hoistedValues.join('\n');
1443
+ lineCount += hoisted.size;
1444
+ } else {
1445
+ res += '\n' + [...hoisted.values()].join('\n');
1446
+ lineCount += hoisted.size;
1447
+ }
1196
1448
  }
1197
1449
 
1198
1450
  return [res, lineCount];
@@ -1207,7 +1459,7 @@ ${code}
1207
1459
  let prependLineCount = 0;
1208
1460
  let append = '';
1209
1461
 
1210
- let shouldWrap = this.wrappedAssets.has(asset.id);
1462
+ let shouldWrap = this.wrappedAssets.has(asset);
1211
1463
  let usedSymbols = nullthrows(this.bundleGraph.getUsedSymbols(asset));
1212
1464
  let assetId = asset.meta.id;
1213
1465
  invariant(typeof assetId === 'string');
@@ -1220,34 +1472,51 @@ ${code}
1220
1472
  usedSymbols.has('default') &&
1221
1473
  !asset.symbols.hasExportSymbol('__esModule');
1222
1474
 
1223
- let usedNamespace =
1224
- // If the asset has * in its used symbols, we might need the exports namespace.
1225
- // The one case where this isn't true is in ESM library entries, where the only
1226
- // dependency on * is the entry dependency. In this case, we will use ESM exports
1227
- // instead of the namespace object.
1228
- (usedSymbols.has('*') &&
1229
- (this.bundle.env.outputFormat !== 'esmodule' ||
1230
- !this.bundle.env.isLibrary ||
1231
- asset !== this.bundle.getMainEntry() ||
1232
- this.bundleGraph
1233
- .getIncomingDependencies(asset)
1234
- .some(
1235
- (dep) =>
1236
- !dep.isEntry &&
1237
- this.bundle.hasDependency(dep) &&
1238
- nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
1239
- ))) ||
1240
- // If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
1241
- // we fallback on the namespace object.
1242
- (asset.symbols.hasExportSymbol('*') &&
1243
- [...usedSymbols].some((s) => !asset.symbols.hasExportSymbol(s))) ||
1244
- // If the exports has this asset's namespace (e.g. ESM output from CJS input),
1245
- // include the namespace object for the default export.
1246
- this.exportedSymbols.has(`$${assetId}$exports`) ||
1247
- // CommonJS library bundle entries always need a namespace.
1248
- (this.bundle.env.isLibrary &&
1249
- this.bundle.env.outputFormat === 'commonjs' &&
1250
- asset === this.bundle.getMainEntry());
1475
+ let usedNamespace;
1476
+ if (
1477
+ getFeatureFlag('inlineConstOptimisationFix') &&
1478
+ asset.meta.isConstantModule
1479
+ ) {
1480
+ // Only set usedNamespace if there is an incoming dependency in the current bundle that uses '*'
1481
+ usedNamespace = this.bundleGraph
1482
+ .getIncomingDependencies(asset)
1483
+ .some(
1484
+ (dep) =>
1485
+ this.bundle.hasDependency(dep) &&
1486
+ nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
1487
+ );
1488
+ } else {
1489
+ usedNamespace =
1490
+ // If the asset has * in its used symbols, we might need the exports namespace.
1491
+ // The one case where this isn't true is in ESM library entries, where the only
1492
+ // dependency on * is the entry dependency. In this case, we will use ESM exports
1493
+ // instead of the namespace object.
1494
+
1495
+ (usedSymbols.has('*') &&
1496
+ (this.bundle.env.outputFormat !== 'esmodule' ||
1497
+ !this.bundle.env.isLibrary ||
1498
+ asset !== this.bundle.getMainEntry() ||
1499
+ this.bundleGraph
1500
+ .getIncomingDependencies(asset)
1501
+ .some(
1502
+ (dep) =>
1503
+ !dep.isEntry &&
1504
+ this.bundle.hasDependency(dep) &&
1505
+ nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
1506
+ ))) ||
1507
+ // If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
1508
+ // we fallback on the namespace object.
1509
+
1510
+ (asset.symbols.hasExportSymbol('*') &&
1511
+ [...usedSymbols].some((s) => !asset.symbols.hasExportSymbol(s))) ||
1512
+ // If the exports has this asset's namespace (e.g. ESM output from CJS input),
1513
+ // include the namespace object for the default export.
1514
+ this.exportedSymbols.has(`$${assetId}$exports`) ||
1515
+ // CommonJS library bundle entries always need a namespace.
1516
+ (this.bundle.env.isLibrary &&
1517
+ this.bundle.env.outputFormat === 'commonjs' &&
1518
+ asset === this.bundle.getMainEntry());
1519
+ }
1251
1520
 
1252
1521
  // If the asset doesn't have static exports, should wrap, the namespace is used,
1253
1522
  // or we need default interop, then we need to synthesize a namespace object for
@@ -1274,6 +1543,7 @@ ${code}
1274
1543
  // Insert the __esModule interop flag for this module if it has a `default` export
1275
1544
  // and the namespace symbol is used.
1276
1545
  // TODO: only if required by CJS?
1546
+
1277
1547
  if (asset.symbols.hasExportSymbol('default') && usedSymbols.has('*')) {
1278
1548
  prepend += `\n$parcel$defineInteropFlag($${assetId}$exports);\n`;
1279
1549
  prependLineCount += 2;
@@ -1337,6 +1607,7 @@ ${code}
1337
1607
  let resolvedSymbol = this.getSymbolResolution(
1338
1608
  asset,
1339
1609
  resolved,
1610
+
1340
1611
  symbol,
1341
1612
  undefined,
1342
1613
  replacements,
@@ -1388,28 +1659,39 @@ ${code}
1388
1659
  // for the symbol so that when the value changes the object property also changes. This is
1389
1660
  // required to simulate ESM live bindings. It's easier to do it this way rather than inserting
1390
1661
  // additional assignments after each mutation of the original binding.
1391
- prepend += `\n${usedExports
1392
- .map((exp) => {
1393
- let resolved = this.getSymbolResolution(
1394
- asset,
1395
- asset,
1662
+ for (let exp of usedExports) {
1663
+ let resolved = this.getSymbolResolution(
1664
+ asset,
1665
+ asset,
1666
+ exp,
1667
+ undefined,
1668
+ replacements,
1669
+ );
1670
+ const meta = asset.symbols.get(exp)?.meta;
1671
+ if (
1672
+ getFeatureFlag('exportsRebindingOptimisation') &&
1673
+ (meta?.isStaticBindingSafe ||
1674
+ this.manualStaticBindingExports?.some((regex) =>
1675
+ regex.test(asset.filePath),
1676
+ ))
1677
+ ) {
1678
+ append += `$${assetId}$exports[${JSON.stringify(
1396
1679
  exp,
1397
- undefined,
1398
- replacements,
1399
- );
1680
+ )}] = ${resolved};\n`;
1681
+ } else {
1400
1682
  let get = this.buildFunctionExpression([], resolved);
1401
1683
  let isEsmExport = !!asset.symbols.get(exp)?.meta?.isEsm;
1402
1684
  let set =
1403
1685
  !isEsmExport && asset.meta.hasCJSExports
1404
1686
  ? ', ' + this.buildFunctionExpression(['v'], `${resolved} = v`)
1405
1687
  : '';
1406
- return `$parcel$export($${assetId}$exports, ${JSON.stringify(
1688
+ prepend += `$parcel$export($${assetId}$exports, ${JSON.stringify(
1407
1689
  exp,
1408
- )}, ${get}${set});`;
1409
- })
1410
- .join('\n')}\n`;
1411
- this.usedHelpers.add('$parcel$export');
1412
- prependLineCount += 1 + usedExports.length;
1690
+ )}, ${get}${set});\n`;
1691
+ this.usedHelpers.add('$parcel$export');
1692
+ prependLineCount += 1 + usedExports.length;
1693
+ }
1694
+ }
1413
1695
  }
1414
1696
  }
1415
1697
 
@@ -1448,9 +1730,11 @@ ${code}
1448
1730
  }
1449
1731
 
1450
1732
  for (let helper of this.usedHelpers) {
1451
- let currentHelper = helpers[helper];
1733
+ let currentHelper = (helpers as Record<string, any>)[helper];
1452
1734
  if (typeof currentHelper === 'function') {
1453
- currentHelper = helpers[helper](this.bundle.env);
1735
+ currentHelper = (helpers as Record<string, any>)[helper](
1736
+ this.bundle.env,
1737
+ );
1454
1738
  }
1455
1739
  res += currentHelper;
1456
1740
  if (enableSourceMaps) {
@@ -1470,11 +1754,14 @@ ${code}
1470
1754
  .some((g) => this.bundleGraph.isEntryBundleGroup(g)) ||
1471
1755
  this.bundle.env.isIsolated() ||
1472
1756
  this.bundle.bundleBehavior === 'isolated' ||
1757
+ this.bundle.bundleBehavior === 'inlineIsolated' ||
1473
1758
  // Conditional deps may be loaded before entrypoints on the server
1474
1759
  this.hasConditionalDependency();
1475
1760
 
1476
1761
  if (mightBeFirstJS) {
1477
- let preludeCode = prelude(this.parcelRequireName);
1762
+ let preludeCode = (
1763
+ getFeatureFlag('useNewPrelude') ? preludeNew : preludeOld
1764
+ )(this.parcelRequireName);
1478
1765
  res += preludeCode;
1479
1766
  if (enableSourceMaps) {
1480
1767
  lines += countLines(preludeCode) - 1;
@@ -1498,7 +1785,11 @@ ${code}
1498
1785
  }
1499
1786
 
1500
1787
  // Add importScripts for sibling bundles in workers.
1501
- if (this.bundle.env.isWorker() || this.bundle.env.isWorklet()) {
1788
+ if (
1789
+ this.bundle.env.isWorker() ||
1790
+ this.bundle.env.isTesseract() ||
1791
+ this.bundle.env.isWorklet()
1792
+ ) {
1502
1793
  let importScripts = '';
1503
1794
  let bundles = this.bundleGraph.getReferencedBundles(this.bundle);
1504
1795
  for (let b of bundles) {
@@ -1539,7 +1830,7 @@ ${code}
1539
1830
  return (
1540
1831
  asset.sideEffects === false &&
1541
1832
  nullthrows(this.bundleGraph.getUsedSymbols(asset)).size == 0 &&
1542
- !this.bundleGraph.isAssetReferenced(this.bundle, asset)
1833
+ !this.isAssetReferencedInBundle(this.bundle, asset)
1543
1834
  );
1544
1835
  }
1545
1836