@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.
- package/CHANGELOG.md +333 -0
- package/lib/DevPackager.js +28 -3
- package/lib/ScopeHoistingPackager.js +236 -74
- package/lib/dev-prelude.js +6 -6
- package/lib/helpers.js +38 -3
- package/lib/index.js +5 -10
- package/lib/types/CJSOutputFormat.d.ts +7 -0
- package/lib/types/DevPackager.d.ts +15 -0
- package/lib/types/ESMOutputFormat.d.ts +7 -0
- package/lib/types/GlobalOutputFormat.d.ts +7 -0
- package/lib/types/ScopeHoistingPackager.d.ts +67 -0
- package/lib/types/helpers.d.ts +12 -0
- package/lib/types/index.d.ts +3 -0
- package/lib/types/utils.d.ts +6 -0
- package/package.json +18 -12
- package/src/{CJSOutputFormat.js → CJSOutputFormat.ts} +0 -1
- package/src/{DevPackager.js → DevPackager.ts} +34 -7
- package/src/{ESMOutputFormat.js → ESMOutputFormat.ts} +2 -3
- package/src/{GlobalOutputFormat.js → GlobalOutputFormat.ts} +0 -1
- package/src/{ScopeHoistingPackager.js → ScopeHoistingPackager.ts} +365 -130
- package/src/dev-prelude.js +6 -6
- package/src/{helpers.js → helpers.ts} +37 -3
- package/src/{index.js → index.ts} +13 -20
- package/src/{utils.js → utils.ts} +1 -2
- package/tsconfig.json +4 -0
|
@@ -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 {
|
|
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:
|
|
87
|
-
|
|
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<{
|
|
137
|
-
|
|
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
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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<
|
|
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
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
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
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
//
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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
|
-
}
|
|
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,
|
|
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
|
|
534
|
-
): [string,
|
|
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
|
-
|
|
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
|
|
651
|
-
|
|
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 (
|
|
665
|
-
|
|
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
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
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
|
-
|
|
1195
|
-
|
|
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
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
.
|
|
1234
|
-
.
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
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
|
-
|
|
1392
|
-
.
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
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
|
-
|
|
1398
|
-
|
|
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
|
-
|
|
1632
|
+
prepend += `$parcel$export($${assetId}$exports, ${JSON.stringify(
|
|
1407
1633
|
exp,
|
|
1408
|
-
)}, ${get}${set})
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
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 =
|
|
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 (
|
|
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) {
|