@atlaspack/packager-js 2.14.5-canary.20 → 2.14.5-canary.200

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,6 +13,7 @@ import {
15
13
  relativeBundlePath,
16
14
  countLines,
17
15
  normalizeSeparators,
16
+ debugTools,
18
17
  } from '@atlaspack/utils';
19
18
  import SourceMap from '@parcel/source-map';
20
19
  import nullthrows from 'nullthrows';
@@ -25,11 +24,18 @@ import ThrowableDiagnostic, {
25
24
  import globals from 'globals';
26
25
  import path from 'path';
27
26
  import {getFeatureFlag} from '@atlaspack/feature-flags';
27
+ import {outdent} from 'outdent';
28
28
 
29
29
  import {ESMOutputFormat} from './ESMOutputFormat';
30
30
  import {CJSOutputFormat} from './CJSOutputFormat';
31
31
  import {GlobalOutputFormat} from './GlobalOutputFormat';
32
- import {prelude, helpers, bundleQueuePrelude, fnExpr} from './helpers';
32
+ import {
33
+ preludeOld,
34
+ preludeNew,
35
+ helpers,
36
+ bundleQueuePrelude,
37
+ fnExpr,
38
+ } from './helpers';
33
39
  import {
34
40
  replaceScriptDependencies,
35
41
  getSpecifier,
@@ -39,7 +45,6 @@ import {
39
45
 
40
46
  // General regex used to replace imports with the resolved code, references with resolutions,
41
47
  // and count the number of newlines in the file for source maps.
42
- //
43
48
  // For conditional bundling the only difference in this regex is adding `importCond` where we have `importAsync` etc..
44
49
  const REPLACEMENT_RE_CONDITIONAL =
45
50
  /\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 +60,7 @@ const GLOBALS_BY_CONTEXT = {
55
60
  ...Object.keys(globals.serviceworker),
56
61
  ]),
57
62
  worklet: new Set([...BUILTINS]),
63
+ tesseract: new Set([...BUILTINS, ...Object.keys(globals.worker)]),
58
64
  node: new Set([...BUILTINS, ...Object.keys(globals.node)]),
59
65
  'electron-main': new Set([...BUILTINS, ...Object.keys(globals.node)]),
60
66
  'electron-renderer': new Set([
@@ -62,13 +68,13 @@ const GLOBALS_BY_CONTEXT = {
62
68
  ...Object.keys(globals.node),
63
69
  ...Object.keys(globals.browser),
64
70
  ]),
65
- };
71
+ } as const;
66
72
 
67
73
  const OUTPUT_FORMATS = {
68
74
  esmodule: ESMOutputFormat,
69
75
  commonjs: CJSOutputFormat,
70
76
  global: GlobalOutputFormat,
71
- };
77
+ } as const;
72
78
 
73
79
  export interface OutputFormat {
74
80
  buildBundlePrelude(): [string, number];
@@ -83,27 +89,37 @@ export class ScopeHoistingPackager {
83
89
  useAsyncBundleRuntime: boolean;
84
90
  outputFormat: OutputFormat;
85
91
  isAsyncBundle: boolean;
86
- globalNames: $ReadOnlySet<string>;
87
- assetOutputs: Map<string, {|code: string, map: ?Buffer|}>;
92
+ globalNames: ReadonlySet<string>;
93
+ // @ts-expect-error TS2564
94
+ assetOutputs: Map<
95
+ string,
96
+ {
97
+ code: string;
98
+ map: Buffer | null | undefined;
99
+ }
100
+ >;
88
101
  exportedSymbols: Map<
89
102
  string,
90
- {|
91
- asset: Asset,
92
- exportSymbol: string,
93
- local: string,
94
- exportAs: Array<string>,
95
- |},
103
+ {
104
+ asset: Asset;
105
+ exportSymbol: string;
106
+ local: string;
107
+ exportAs: Array<string>;
108
+ }
96
109
  > = new Map();
97
110
  externals: Map<string, Map<string, string>> = new Map();
98
111
  topLevelNames: Map<string, number> = new Map();
99
112
  seenAssets: Set<string> = new Set();
100
113
  wrappedAssets: Set<string> = new Set();
101
114
  hoistedRequires: Map<string, Map<string, string>> = new Map();
115
+ seenHoistedRequires: Set<string> = new Set();
102
116
  needsPrelude: boolean = false;
103
117
  usedHelpers: Set<string> = new Set();
104
118
  externalAssets: Set<Asset> = new Set();
105
- forceSkipWrapAssets: Array<string> = [];
106
119
  logger: PluginLogger;
120
+ useBothScopeHoistingImprovements: boolean =
121
+ getFeatureFlag('applyScopeHoistingImprovementV2') ||
122
+ getFeatureFlag('applyScopeHoistingImprovement');
107
123
 
108
124
  constructor(
109
125
  options: PluginOptions,
@@ -111,7 +127,6 @@ export class ScopeHoistingPackager {
111
127
  bundle: NamedBundle,
112
128
  parcelRequireName: string,
113
129
  useAsyncBundleRuntime: boolean,
114
- forceSkipWrapAssets: Array<string>,
115
130
  logger: PluginLogger,
116
131
  ) {
117
132
  this.options = options;
@@ -119,7 +134,6 @@ export class ScopeHoistingPackager {
119
134
  this.bundle = bundle;
120
135
  this.parcelRequireName = parcelRequireName;
121
136
  this.useAsyncBundleRuntime = useAsyncBundleRuntime;
122
- this.forceSkipWrapAssets = forceSkipWrapAssets ?? [];
123
137
  this.logger = logger;
124
138
 
125
139
  let OutputFormat = OUTPUT_FORMATS[this.bundle.env.outputFormat];
@@ -128,13 +142,18 @@ export class ScopeHoistingPackager {
128
142
  this.isAsyncBundle =
129
143
  this.bundleGraph.hasParentBundleOfType(this.bundle, 'js') &&
130
144
  !this.bundle.env.isIsolated() &&
131
- this.bundle.bundleBehavior !== 'isolated';
145
+ this.bundle.bundleBehavior !== 'isolated' &&
146
+ this.bundle.bundleBehavior !== 'inlineIsolated';
132
147
 
133
148
  this.globalNames = GLOBALS_BY_CONTEXT[bundle.env.context];
134
149
  }
135
150
 
136
- async package(): Promise<{|contents: string, map: ?SourceMap|}> {
137
- let wrappedAssets = await this.loadAssets();
151
+ async package(): Promise<{
152
+ contents: string;
153
+ map: SourceMap | null | undefined;
154
+ }> {
155
+ let {wrapped: wrappedAssets, constant: constantAssets} =
156
+ await this.loadAssets();
138
157
  this.buildExportedSymbols();
139
158
 
140
159
  // If building a library, the target is actually another bundler rather
@@ -155,9 +174,13 @@ export class ScopeHoistingPackager {
155
174
 
156
175
  let res = '';
157
176
  let lineCount = 0;
177
+ // @ts-expect-error TS7034
158
178
  let sourceMap = null;
159
- let processAsset = (asset) => {
179
+ let processAsset = (asset: Asset) => {
180
+ this.seenHoistedRequires.clear();
160
181
  let [content, map, lines] = this.visitAsset(asset);
182
+
183
+ // @ts-expect-error TS7005
161
184
  if (sourceMap && map) {
162
185
  sourceMap.addSourceMap(map, lineCount);
163
186
  } else if (this.bundle.env.sourceMap) {
@@ -168,6 +191,18 @@ export class ScopeHoistingPackager {
168
191
  lineCount += lines + 1;
169
192
  };
170
193
 
194
+ if (
195
+ getFeatureFlag('inlineConstOptimisationFix') ||
196
+ this.useBothScopeHoistingImprovements
197
+ ) {
198
+ // Write out all constant modules used by this bundle
199
+ for (let asset of constantAssets) {
200
+ if (!this.seenAssets.has(asset.id)) {
201
+ processAsset(asset);
202
+ }
203
+ }
204
+ }
205
+
171
206
  // Hoist wrapped asset to the top of the bundle to ensure that they are registered
172
207
  // before they are used.
173
208
  for (let asset of wrappedAssets) {
@@ -191,14 +226,28 @@ export class ScopeHoistingPackager {
191
226
  let [prelude, preludeLines] = this.buildBundlePrelude();
192
227
  res = prelude + res;
193
228
  lineCount += preludeLines;
229
+ // @ts-expect-error TS2339
194
230
  sourceMap?.offsetLines(1, preludeLines);
195
231
 
196
232
  let entries = this.bundle.getEntryAssets();
197
233
  let mainEntry = this.bundle.getMainEntry();
198
234
  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);
235
+ if (
236
+ this.useBothScopeHoistingImprovements ||
237
+ getFeatureFlag('supportWebpackChunkName')
238
+ ) {
239
+ // Generally speaking, async bundles should not be executed on load, as
240
+ // they're just collections of assets that other assets require.
241
+ // However, there are some special cases where a runtime asset needs to be
242
+ // injected, but no other asset will require it (mostly the bundle
243
+ // manifest).
244
+ // In this case, those assets need to be required on load.
245
+ entries = entries.filter(
246
+ (a) => a.meta?.runtimeAssetRequiringExecutionOnLoad,
247
+ );
248
+ } else {
249
+ entries = entries.filter((a) => a.id !== mainEntry?.id);
250
+ }
202
251
  mainEntry = null;
203
252
  }
204
253
 
@@ -265,6 +314,7 @@ export class ScopeHoistingPackager {
265
314
  this.parcelRequireName,
266
315
  );
267
316
  if (sourceMap && map) {
317
+ // @ts-expect-error TS2339
268
318
  sourceMap.addSourceMap(map, lineCount);
269
319
  }
270
320
  }
@@ -281,10 +331,7 @@ export class ScopeHoistingPackager {
281
331
 
282
332
  let hasConditionalReference = false;
283
333
  let isConditionalBundle = false;
284
- if (
285
- getFeatureFlag('conditionalBundlingApi') &&
286
- getFeatureFlag('conditionalBundlingAsyncRuntime')
287
- ) {
334
+ if (getFeatureFlag('conditionalBundlingApi')) {
288
335
  // If the bundle has a conditional bundle reference (has an importCond)
289
336
  hasConditionalReference =
290
337
  this.bundleGraph.getReferencedConditionalBundles(bundle).length > 0;
@@ -296,6 +343,7 @@ export class ScopeHoistingPackager {
296
343
  this.useAsyncBundleRuntime &&
297
344
  bundle.type === 'js' &&
298
345
  bundle.bundleBehavior !== 'inline' &&
346
+ bundle.bundleBehavior !== 'inlineIsolated' &&
299
347
  bundle.env.outputFormat === 'esmodule' &&
300
348
  !bundle.env.isIsolated() &&
301
349
  bundle.bundleBehavior !== 'isolated' &&
@@ -309,11 +357,8 @@ export class ScopeHoistingPackager {
309
357
  .filter((b) => this.shouldBundleQueue(b))
310
358
  .map((b) => b.publicId);
311
359
 
312
- const conditions = [];
313
- if (
314
- getFeatureFlag('conditionalBundlingApi') &&
315
- getFeatureFlag('conditionalBundlingAsyncRuntime')
316
- ) {
360
+ const conditions: Array<string> = [];
361
+ if (getFeatureFlag('conditionalBundlingApi')) {
317
362
  const conditionSet = this.bundleGraph
318
363
  .getConditionalBundleMapping()
319
364
  .get(bundle.id);
@@ -354,15 +399,21 @@ export class ScopeHoistingPackager {
354
399
  return `$parcel$global.rwr(${params.join(', ')});`;
355
400
  }
356
401
 
357
- async loadAssets(): Promise<Array<Asset>> {
402
+ async loadAssets(): Promise<{
403
+ wrapped: Array<Asset>;
404
+ constant: Array<Asset>;
405
+ }> {
358
406
  let queue = new PromiseQueue({maxConcurrent: 32});
359
- let wrapped = [];
407
+ let wrapped: Array<Asset> = [];
408
+ let constant: Array<Asset> = [];
409
+
360
410
  this.bundle.traverseAssets((asset) => {
361
411
  queue.add(async () => {
362
412
  let [code, map] = await Promise.all([
363
413
  asset.getCode(),
364
414
  this.bundle.env.sourceMap ? asset.getMapBuffer() : null,
365
415
  ]);
416
+
366
417
  return [asset.id, {code, map}];
367
418
  });
368
419
 
@@ -383,50 +434,115 @@ export class ScopeHoistingPackager {
383
434
  ) {
384
435
  this.wrappedAssets.add(asset.id);
385
436
  wrapped.push(asset);
437
+ } else if (
438
+ (getFeatureFlag('inlineConstOptimisationFix') ||
439
+ this.useBothScopeHoistingImprovements) &&
440
+ asset.meta.isConstantModule
441
+ ) {
442
+ constant.push(asset);
386
443
  }
387
444
  }
388
445
  });
389
446
 
390
- for (let wrappedAssetRoot of [...wrapped]) {
391
- this.bundle.traverseAssets((asset, _, actions) => {
392
- if (asset === wrappedAssetRoot) {
393
- return;
447
+ if (this.useBothScopeHoistingImprovements) {
448
+ // Tracks which assets have been assigned to a wrap group
449
+ let assignedAssets = new Set<Asset>();
450
+
451
+ // In V2 scope hoisting, we iterate from the main entry, rather than
452
+ // wrapping the entry assets
453
+ if (!getFeatureFlag('applyScopeHoistingImprovementV2')) {
454
+ // Make all entry assets wrapped, to avoid any top level hoisting
455
+ for (let entryAsset of this.bundle.getEntryAssets()) {
456
+ if (!this.wrappedAssets.has(entryAsset.id)) {
457
+ this.wrappedAssets.add(entryAsset.id);
458
+ wrapped.push(entryAsset);
459
+ }
394
460
  }
461
+ }
395
462
 
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);
463
+ let moduleGroupParents = [...wrapped];
464
+
465
+ if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
466
+ // The main entry needs to be check to find assets that would have gone in
467
+ // the top level scope
468
+ let mainEntry = this.bundle.getMainEntry();
469
+ if (mainEntry && !this.wrappedAssets.has(mainEntry.id)) {
470
+ moduleGroupParents.unshift(mainEntry);
424
471
  }
425
- }, wrappedAssetRoot);
472
+ }
473
+
474
+ for (let moduleGroupParentAsset of moduleGroupParents) {
475
+ this.bundle.traverseAssets((asset, _, actions) => {
476
+ if (asset === moduleGroupParentAsset) {
477
+ return;
478
+ }
479
+
480
+ if (this.wrappedAssets.has(asset.id)) {
481
+ actions.skipChildren();
482
+ return;
483
+ }
484
+
485
+ if (
486
+ !asset.meta.isConstantModule &&
487
+ (assignedAssets.has(asset) || this.isReExported(asset))
488
+ ) {
489
+ wrapped.push(asset);
490
+ this.wrappedAssets.add(asset.id);
491
+
492
+ // This also needs to be added to the traversal so that we iterate
493
+ // it during this check.
494
+ moduleGroupParents.push(asset);
495
+
496
+ actions.skipChildren();
497
+ return;
498
+ }
499
+
500
+ assignedAssets.add(asset);
501
+ }, moduleGroupParentAsset);
502
+ }
503
+ } else {
504
+ for (let wrappedAssetRoot of [...wrapped]) {
505
+ this.bundle.traverseAssets((asset, _, actions) => {
506
+ if (asset === wrappedAssetRoot) {
507
+ return;
508
+ }
509
+
510
+ if (this.wrappedAssets.has(asset.id)) {
511
+ actions.skipChildren();
512
+ return;
513
+ }
514
+
515
+ if (!asset.meta.isConstantModule) {
516
+ this.wrappedAssets.add(asset.id);
517
+ wrapped.push(asset);
518
+ }
519
+ }, wrappedAssetRoot);
520
+ }
426
521
  }
427
522
 
523
+ // @ts-expect-error TS2769
428
524
  this.assetOutputs = new Map(await queue.run());
429
- return wrapped;
525
+ return {wrapped, constant};
526
+ }
527
+
528
+ isReExported(asset: Asset): boolean {
529
+ let parentSymbols = this.bundleGraph
530
+ .getIncomingDependencies(asset)
531
+ .map((dep) => this.bundleGraph.getAssetWithDependency(dep))
532
+ .flatMap((parent) => {
533
+ if (parent == null) {
534
+ return [];
535
+ }
536
+ return this.bundleGraph.getExportedSymbols(parent, this.bundle);
537
+ });
538
+
539
+ let assetSymbols = this.bundleGraph.getExportedSymbols(asset, this.bundle);
540
+
541
+ return assetSymbols.some((assetSymbol) =>
542
+ parentSymbols.some(
543
+ (parentSymbol) => parentSymbol.symbol === assetSymbol.symbol,
544
+ ),
545
+ );
430
546
  }
431
547
 
432
548
  buildExportedSymbols() {
@@ -464,6 +580,7 @@ export class ScopeHoistingPackager {
464
580
  symbols = [];
465
581
  this.exportedSymbols.set(symbol, {
466
582
  asset,
583
+
467
584
  exportSymbol,
468
585
  local: symbol,
469
586
  exportAs: symbols,
@@ -519,7 +636,7 @@ export class ScopeHoistingPackager {
519
636
  return `${obj}[${JSON.stringify(property)}]`;
520
637
  }
521
638
 
522
- visitAsset(asset: Asset): [string, ?SourceMap, number] {
639
+ visitAsset(asset: Asset): [string, SourceMap | null | undefined, number] {
523
640
  invariant(!this.seenAssets.has(asset.id), 'Already visited asset');
524
641
  this.seenAssets.add(asset.id);
525
642
 
@@ -527,11 +644,15 @@ export class ScopeHoistingPackager {
527
644
  return this.buildAsset(asset, code, map);
528
645
  }
529
646
 
647
+ getAssetFilePath(asset: Asset): string {
648
+ return path.relative(this.options.projectRoot, asset.filePath);
649
+ }
650
+
530
651
  buildAsset(
531
652
  asset: Asset,
532
653
  code: string,
533
- map: ?Buffer,
534
- ): [string, ?SourceMap, number] {
654
+ map?: Buffer | null,
655
+ ): [string, SourceMap | null | undefined, number] {
535
656
  let shouldWrap = this.wrappedAssets.has(asset.id);
536
657
  let deps = this.bundleGraph.getDependencies(asset);
537
658
 
@@ -566,6 +687,7 @@ export class ScopeHoistingPackager {
566
687
  let [code, map, lines] = this.visitAsset(resolved);
567
688
  depCode += code + '\n';
568
689
  if (sourceMap && map) {
690
+ // @ts-expect-error TS2551
569
691
  sourceMap.addSourceMap(map, lineCount);
570
692
  }
571
693
  lineCount += lines + 1;
@@ -602,7 +724,9 @@ export class ScopeHoistingPackager {
602
724
  code += append;
603
725
 
604
726
  let lineCount = 0;
605
- let depContent = [];
727
+ // @ts-expect-error TS2552
728
+ let depContent: Array<[string, NodeSourceMap | null | undefined, number]> =
729
+ [];
606
730
  if (depMap.size === 0 && replacements.size === 0) {
607
731
  // If there are no dependencies or replacements, use a simple function to count the number of lines.
608
732
  lineCount = countLines(code) - 1;
@@ -647,12 +771,18 @@ export class ScopeHoistingPackager {
647
771
  // after the dependency is declared. This handles the case where the resulting asset
648
772
  // is wrapped, but the dependency in this asset is not marked as wrapped. This means
649
773
  // 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
- );
774
+ let res = '';
775
+ let lines = 0;
655
776
  let map;
777
+
778
+ if (!getFeatureFlag('applyScopeHoistingImprovementV2')) {
779
+ [res, lines] = this.getHoistedParcelRequires(
780
+ asset,
781
+ dep,
782
+ resolved,
783
+ );
784
+ }
785
+
656
786
  if (
657
787
  this.bundle.hasAsset(resolved) &&
658
788
  !this.seenAssets.has(resolved.id)
@@ -661,13 +791,48 @@ export class ScopeHoistingPackager {
661
791
  // outside our parcelRequire.register wrapper. This is safe because all
662
792
  // assets referenced by this asset will also be wrapped. Otherwise, inline the
663
793
  // asset content where the import statement was.
664
- if (shouldWrap) {
665
- depContent.push(this.visitAsset(resolved));
794
+ if (this.useBothScopeHoistingImprovements) {
795
+ if (
796
+ !resolved.meta.isConstantModule &&
797
+ !this.wrappedAssets.has(resolved.id)
798
+ ) {
799
+ let [depCode, depMap, depLines] =
800
+ this.visitAsset(resolved);
801
+ if (debugTools['asset-file-names-in-output']) {
802
+ let resolvedPath = this.getAssetFilePath(resolved);
803
+ res = outdent`
804
+ /* Scope hoisted asset: ${resolvedPath} */
805
+ ${depCode}
806
+ /* End: ${resolvedPath} */
807
+ ${res}
808
+ `;
809
+ lines += 3 + depLines;
810
+ } else {
811
+ res = depCode + '\n' + res;
812
+ lines += 1 + depLines;
813
+ }
814
+ map = depMap;
815
+ }
666
816
  } else {
667
- let [depCode, depMap, depLines] = this.visitAsset(resolved);
668
- res = depCode + '\n' + res;
669
- lines += 1 + depLines;
670
- map = depMap;
817
+ if (shouldWrap) {
818
+ depContent.push(this.visitAsset(resolved));
819
+ } else {
820
+ let [depCode, depMap, depLines] =
821
+ this.visitAsset(resolved);
822
+ res = depCode + '\n' + res;
823
+ lines += 1 + depLines;
824
+ map = depMap;
825
+ }
826
+ }
827
+ }
828
+
829
+ if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
830
+ let [requiresCode, requiresLines] =
831
+ this.getHoistedParcelRequires(asset, dep, resolved);
832
+
833
+ if (requiresCode) {
834
+ res = requiresCode + '\n' + res;
835
+ lines += requiresLines + 1;
671
836
  }
672
837
  }
673
838
 
@@ -679,6 +844,7 @@ export class ScopeHoistingPackager {
679
844
  }
680
845
 
681
846
  if (map) {
847
+ // @ts-expect-error TS2551
682
848
  sourceMap.addSourceMap(map, lineCount);
683
849
  }
684
850
  }
@@ -726,10 +892,16 @@ ${code}
726
892
 
727
893
  lineCount += 2;
728
894
 
895
+ if (debugTools['asset-file-names-in-output']) {
896
+ code = `/* ${this.getAssetFilePath(asset)} */\n` + code;
897
+ lineCount += 1;
898
+ }
899
+
729
900
  for (let [depCode, map, lines] of depContent) {
730
901
  if (!depCode) continue;
731
902
  code += depCode + '\n';
732
903
  if (sourceMap && map) {
904
+ // @ts-expect-error TS2551
733
905
  sourceMap.addSourceMap(map, lineCount);
734
906
  }
735
907
  lineCount += lines + 1;
@@ -895,7 +1067,9 @@ ${code}
895
1067
 
896
1068
  for (let [imported, {local}] of dep.symbols) {
897
1069
  // If already imported, just add the already renamed variable to the mapping.
1070
+
898
1071
  let renamed = external.get(imported);
1072
+
899
1073
  if (renamed && local !== '*' && replacements) {
900
1074
  replacements.set(local, renamed);
901
1075
  continue;
@@ -908,6 +1082,7 @@ ${code}
908
1082
  if (!renamed) {
909
1083
  if (referencedBundle) {
910
1084
  let entry = nullthrows(referencedBundle.getMainEntry());
1085
+
911
1086
  renamed =
912
1087
  entry.symbols.get('*')?.local ??
913
1088
  `$${String(entry.meta.id)}$exports`;
@@ -922,6 +1097,7 @@ ${code}
922
1097
 
923
1098
  if (local !== '*' && replacements) {
924
1099
  let replacement;
1100
+
925
1101
  if (imported === '*') {
926
1102
  replacement = renamed;
927
1103
  } else if (imported === 'default') {
@@ -946,10 +1122,12 @@ ${code}
946
1122
  let property;
947
1123
  if (referencedBundle) {
948
1124
  let entry = nullthrows(referencedBundle.getMainEntry());
1125
+
949
1126
  if (entry.symbols.hasExportSymbol('*')) {
950
1127
  // If importing * and the referenced module has a * export (e.g. CJS), use default instead.
951
1128
  // This mirrors the logic in buildExportedSymbols.
952
1129
  property = imported;
1130
+
953
1131
  imported =
954
1132
  referencedBundle?.env.outputFormat === 'esmodule'
955
1133
  ? 'default'
@@ -957,6 +1135,7 @@ ${code}
957
1135
  } else {
958
1136
  if (imported === '*') {
959
1137
  let exportedSymbols = this.bundleGraph.getExportedSymbols(entry);
1138
+
960
1139
  if (local === '*') {
961
1140
  // Re-export all symbols.
962
1141
  for (let exported of exportedSymbols) {
@@ -967,6 +1146,8 @@ ${code}
967
1146
  continue;
968
1147
  }
969
1148
  }
1149
+
1150
+ // @ts-expect-error TS2322
970
1151
  renamed = this.bundleGraph.getSymbolResolution(
971
1152
  entry,
972
1153
  imported,
@@ -993,8 +1174,10 @@ ${code}
993
1174
  }
994
1175
 
995
1176
  external.set(imported, renamed);
1177
+
996
1178
  if (local !== '*' && replacements) {
997
1179
  let replacement = renamed;
1180
+
998
1181
  if (property === '*') {
999
1182
  replacement = renamed;
1000
1183
  } else if (property === 'default') {
@@ -1003,6 +1186,7 @@ ${code}
1003
1186
  } else if (property) {
1004
1187
  replacement = this.getPropertyAccess(renamed, property);
1005
1188
  }
1189
+
1006
1190
  replacements.set(local, replacement);
1007
1191
  }
1008
1192
  }
@@ -1117,6 +1301,7 @@ ${code}
1117
1301
  obj = `$${publicId}`;
1118
1302
  } else {
1119
1303
  obj = resolvedAsset.symbols.get('*')?.local || `$${assetId}$exports`;
1304
+
1120
1305
  obj = replacements?.get(obj) || obj;
1121
1306
  }
1122
1307
 
@@ -1191,8 +1376,22 @@ ${code}
1191
1376
 
1192
1377
  if (hoisted) {
1193
1378
  this.needsPrelude = true;
1194
- res += '\n' + [...hoisted.values()].join('\n');
1195
- lineCount += hoisted.size;
1379
+
1380
+ if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
1381
+ let hoistedValues = [...hoisted.values()].filter(
1382
+ (val) => !this.seenHoistedRequires.has(val),
1383
+ );
1384
+
1385
+ for (let val of hoistedValues) {
1386
+ this.seenHoistedRequires.add(val);
1387
+ }
1388
+
1389
+ res += '\n' + hoistedValues.join('\n');
1390
+ lineCount += hoisted.size;
1391
+ } else {
1392
+ res += '\n' + [...hoisted.values()].join('\n');
1393
+ lineCount += hoisted.size;
1394
+ }
1196
1395
  }
1197
1396
 
1198
1397
  return [res, lineCount];
@@ -1220,34 +1419,51 @@ ${code}
1220
1419
  usedSymbols.has('default') &&
1221
1420
  !asset.symbols.hasExportSymbol('__esModule');
1222
1421
 
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());
1422
+ let usedNamespace;
1423
+ if (
1424
+ getFeatureFlag('inlineConstOptimisationFix') &&
1425
+ asset.meta.isConstantModule
1426
+ ) {
1427
+ // Only set usedNamespace if there is an incoming dependency in the current bundle that uses '*'
1428
+ usedNamespace = this.bundleGraph
1429
+ .getIncomingDependencies(asset)
1430
+ .some(
1431
+ (dep) =>
1432
+ this.bundle.hasDependency(dep) &&
1433
+ nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
1434
+ );
1435
+ } else {
1436
+ usedNamespace =
1437
+ // If the asset has * in its used symbols, we might need the exports namespace.
1438
+ // The one case where this isn't true is in ESM library entries, where the only
1439
+ // dependency on * is the entry dependency. In this case, we will use ESM exports
1440
+ // instead of the namespace object.
1441
+
1442
+ (usedSymbols.has('*') &&
1443
+ (this.bundle.env.outputFormat !== 'esmodule' ||
1444
+ !this.bundle.env.isLibrary ||
1445
+ asset !== this.bundle.getMainEntry() ||
1446
+ this.bundleGraph
1447
+ .getIncomingDependencies(asset)
1448
+ .some(
1449
+ (dep) =>
1450
+ !dep.isEntry &&
1451
+ this.bundle.hasDependency(dep) &&
1452
+ nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
1453
+ ))) ||
1454
+ // If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
1455
+ // we fallback on the namespace object.
1456
+
1457
+ (asset.symbols.hasExportSymbol('*') &&
1458
+ [...usedSymbols].some((s) => !asset.symbols.hasExportSymbol(s))) ||
1459
+ // If the exports has this asset's namespace (e.g. ESM output from CJS input),
1460
+ // include the namespace object for the default export.
1461
+ this.exportedSymbols.has(`$${assetId}$exports`) ||
1462
+ // CommonJS library bundle entries always need a namespace.
1463
+ (this.bundle.env.isLibrary &&
1464
+ this.bundle.env.outputFormat === 'commonjs' &&
1465
+ asset === this.bundle.getMainEntry());
1466
+ }
1251
1467
 
1252
1468
  // If the asset doesn't have static exports, should wrap, the namespace is used,
1253
1469
  // or we need default interop, then we need to synthesize a namespace object for
@@ -1274,6 +1490,7 @@ ${code}
1274
1490
  // Insert the __esModule interop flag for this module if it has a `default` export
1275
1491
  // and the namespace symbol is used.
1276
1492
  // TODO: only if required by CJS?
1493
+
1277
1494
  if (asset.symbols.hasExportSymbol('default') && usedSymbols.has('*')) {
1278
1495
  prepend += `\n$parcel$defineInteropFlag($${assetId}$exports);\n`;
1279
1496
  prependLineCount += 2;
@@ -1337,6 +1554,7 @@ ${code}
1337
1554
  let resolvedSymbol = this.getSymbolResolution(
1338
1555
  asset,
1339
1556
  resolved,
1557
+
1340
1558
  symbol,
1341
1559
  undefined,
1342
1560
  replacements,
@@ -1388,28 +1606,36 @@ ${code}
1388
1606
  // for the symbol so that when the value changes the object property also changes. This is
1389
1607
  // required to simulate ESM live bindings. It's easier to do it this way rather than inserting
1390
1608
  // 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,
1609
+ for (let exp of usedExports) {
1610
+ let resolved = this.getSymbolResolution(
1611
+ asset,
1612
+ asset,
1613
+ exp,
1614
+ undefined,
1615
+ replacements,
1616
+ );
1617
+ const meta = asset.symbols.get(exp)?.meta;
1618
+ if (
1619
+ getFeatureFlag('exportsRebindingOptimisation') &&
1620
+ meta?.isStaticBindingSafe
1621
+ ) {
1622
+ append += `$${assetId}$exports[${JSON.stringify(
1396
1623
  exp,
1397
- undefined,
1398
- replacements,
1399
- );
1624
+ )}] = ${resolved};\n`;
1625
+ } else {
1400
1626
  let get = this.buildFunctionExpression([], resolved);
1401
1627
  let isEsmExport = !!asset.symbols.get(exp)?.meta?.isEsm;
1402
1628
  let set =
1403
1629
  !isEsmExport && asset.meta.hasCJSExports
1404
1630
  ? ', ' + this.buildFunctionExpression(['v'], `${resolved} = v`)
1405
1631
  : '';
1406
- return `$parcel$export($${assetId}$exports, ${JSON.stringify(
1632
+ prepend += `$parcel$export($${assetId}$exports, ${JSON.stringify(
1407
1633
  exp,
1408
- )}, ${get}${set});`;
1409
- })
1410
- .join('\n')}\n`;
1411
- this.usedHelpers.add('$parcel$export');
1412
- prependLineCount += 1 + usedExports.length;
1634
+ )}, ${get}${set});\n`;
1635
+ this.usedHelpers.add('$parcel$export');
1636
+ prependLineCount += 1 + usedExports.length;
1637
+ }
1638
+ }
1413
1639
  }
1414
1640
  }
1415
1641
 
@@ -1448,8 +1674,10 @@ ${code}
1448
1674
  }
1449
1675
 
1450
1676
  for (let helper of this.usedHelpers) {
1677
+ // @ts-expect-error TS7053
1451
1678
  let currentHelper = helpers[helper];
1452
1679
  if (typeof currentHelper === 'function') {
1680
+ // @ts-expect-error TS7053
1453
1681
  currentHelper = helpers[helper](this.bundle.env);
1454
1682
  }
1455
1683
  res += currentHelper;
@@ -1470,11 +1698,14 @@ ${code}
1470
1698
  .some((g) => this.bundleGraph.isEntryBundleGroup(g)) ||
1471
1699
  this.bundle.env.isIsolated() ||
1472
1700
  this.bundle.bundleBehavior === 'isolated' ||
1701
+ this.bundle.bundleBehavior === 'inlineIsolated' ||
1473
1702
  // Conditional deps may be loaded before entrypoints on the server
1474
1703
  this.hasConditionalDependency();
1475
1704
 
1476
1705
  if (mightBeFirstJS) {
1477
- let preludeCode = prelude(this.parcelRequireName);
1706
+ let preludeCode = (
1707
+ getFeatureFlag('useNewPrelude') ? preludeNew : preludeOld
1708
+ )(this.parcelRequireName);
1478
1709
  res += preludeCode;
1479
1710
  if (enableSourceMaps) {
1480
1711
  lines += countLines(preludeCode) - 1;
@@ -1498,7 +1729,11 @@ ${code}
1498
1729
  }
1499
1730
 
1500
1731
  // Add importScripts for sibling bundles in workers.
1501
- if (this.bundle.env.isWorker() || this.bundle.env.isWorklet()) {
1732
+ if (
1733
+ this.bundle.env.isWorker() ||
1734
+ this.bundle.env.isTesseract() ||
1735
+ this.bundle.env.isWorklet()
1736
+ ) {
1502
1737
  let importScripts = '';
1503
1738
  let bundles = this.bundleGraph.getReferencedBundles(this.bundle);
1504
1739
  for (let b of bundles) {