@atlaspack/packager-js 2.14.5-canary.21 → 2.14.5-canary.211
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 +348 -0
- package/dist/CJSOutputFormat.js +34 -0
- package/dist/DevPackager.js +202 -0
- package/dist/ESMOutputFormat.js +102 -0
- package/dist/GlobalOutputFormat.js +18 -0
- package/dist/ScopeHoistingPackager.js +1362 -0
- package/dist/helpers.js +170 -0
- package/dist/index.js +101 -0
- package/dist/utils.js +60 -0
- package/lib/DevPackager.js +28 -3
- package/lib/ESMOutputFormat.js +1 -1
- package/lib/ScopeHoistingPackager.js +255 -105
- 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 +65 -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 +17 -12
- package/src/{CJSOutputFormat.js → CJSOutputFormat.ts} +0 -1
- package/src/{DevPackager.js → DevPackager.ts} +34 -7
- package/src/{ESMOutputFormat.js → ESMOutputFormat.ts} +3 -4
- package/src/{GlobalOutputFormat.js → GlobalOutputFormat.ts} +0 -1
- package/src/{ScopeHoistingPackager.js → ScopeHoistingPackager.ts} +403 -176
- 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 +27 -0
- package/tsconfig.tsbuildinfo +1 -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
|
-
assetOutputs: Map<
|
|
92
|
+
globalNames: ReadonlySet<string>;
|
|
93
|
+
assetOutputs: Map<
|
|
94
|
+
Asset,
|
|
95
|
+
{
|
|
96
|
+
code: string;
|
|
97
|
+
map: Buffer | null | undefined;
|
|
98
|
+
}
|
|
99
|
+
> = new Map();
|
|
88
100
|
exportedSymbols: Map<
|
|
89
101
|
string,
|
|
90
|
-
{
|
|
91
|
-
asset: Asset
|
|
92
|
-
exportSymbol: string
|
|
93
|
-
local: string
|
|
94
|
-
exportAs: Array<string
|
|
95
|
-
|
|
102
|
+
{
|
|
103
|
+
asset: Asset;
|
|
104
|
+
exportSymbol: string;
|
|
105
|
+
local: string;
|
|
106
|
+
exportAs: Array<string>;
|
|
107
|
+
}
|
|
96
108
|
> = new Map();
|
|
97
109
|
externals: Map<string, Map<string, string>> = new Map();
|
|
98
110
|
topLevelNames: Map<string, number> = new Map();
|
|
99
|
-
seenAssets: Set<
|
|
100
|
-
wrappedAssets: Set<
|
|
101
|
-
|
|
111
|
+
seenAssets: Set<Asset> = new Set();
|
|
112
|
+
wrappedAssets: Set<Asset> = new Set();
|
|
113
|
+
constantAssets: Set<Asset> = new Set();
|
|
114
|
+
hoistedRequires: Map<Dependency, Map<Asset, 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,17 @@ 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
|
+
await this.loadAssets();
|
|
138
156
|
this.buildExportedSymbols();
|
|
139
157
|
|
|
140
158
|
// If building a library, the target is actually another bundler rather
|
|
@@ -155,10 +173,13 @@ export class ScopeHoistingPackager {
|
|
|
155
173
|
|
|
156
174
|
let res = '';
|
|
157
175
|
let lineCount = 0;
|
|
158
|
-
let sourceMap = null;
|
|
159
|
-
let processAsset = (asset) => {
|
|
176
|
+
let sourceMap: SourceMap | null | undefined = null;
|
|
177
|
+
let processAsset = (asset: Asset) => {
|
|
178
|
+
this.seenHoistedRequires.clear();
|
|
160
179
|
let [content, map, lines] = this.visitAsset(asset);
|
|
180
|
+
|
|
161
181
|
if (sourceMap && map) {
|
|
182
|
+
// @ts-expect-error TS2551 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
162
183
|
sourceMap.addSourceMap(map, lineCount);
|
|
163
184
|
} else if (this.bundle.env.sourceMap) {
|
|
164
185
|
sourceMap = map;
|
|
@@ -168,10 +189,22 @@ export class ScopeHoistingPackager {
|
|
|
168
189
|
lineCount += lines + 1;
|
|
169
190
|
};
|
|
170
191
|
|
|
192
|
+
if (
|
|
193
|
+
getFeatureFlag('inlineConstOptimisationFix') ||
|
|
194
|
+
this.useBothScopeHoistingImprovements
|
|
195
|
+
) {
|
|
196
|
+
// Write out all constant modules used by this bundle
|
|
197
|
+
for (let asset of this.constantAssets) {
|
|
198
|
+
if (!this.seenAssets.has(asset)) {
|
|
199
|
+
processAsset(asset);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
171
204
|
// Hoist wrapped asset to the top of the bundle to ensure that they are registered
|
|
172
205
|
// before they are used.
|
|
173
|
-
for (let asset of wrappedAssets) {
|
|
174
|
-
if (!this.seenAssets.has(asset
|
|
206
|
+
for (let asset of this.wrappedAssets) {
|
|
207
|
+
if (!this.seenAssets.has(asset)) {
|
|
175
208
|
processAsset(asset);
|
|
176
209
|
}
|
|
177
210
|
}
|
|
@@ -179,7 +212,7 @@ export class ScopeHoistingPackager {
|
|
|
179
212
|
// Add each asset that is directly connected to the bundle. Dependencies will be handled
|
|
180
213
|
// by replacing `import` statements in the code.
|
|
181
214
|
this.bundle.traverseAssets((asset, _, actions) => {
|
|
182
|
-
if (this.seenAssets.has(asset
|
|
215
|
+
if (this.seenAssets.has(asset)) {
|
|
183
216
|
actions.skipChildren();
|
|
184
217
|
return;
|
|
185
218
|
}
|
|
@@ -191,14 +224,28 @@ export class ScopeHoistingPackager {
|
|
|
191
224
|
let [prelude, preludeLines] = this.buildBundlePrelude();
|
|
192
225
|
res = prelude + res;
|
|
193
226
|
lineCount += preludeLines;
|
|
227
|
+
// @ts-expect-error TS2339 - offsetLines method exists but missing from @parcel/source-map type definitions
|
|
194
228
|
sourceMap?.offsetLines(1, preludeLines);
|
|
195
229
|
|
|
196
230
|
let entries = this.bundle.getEntryAssets();
|
|
197
231
|
let mainEntry = this.bundle.getMainEntry();
|
|
198
232
|
if (this.isAsyncBundle) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
233
|
+
if (
|
|
234
|
+
this.useBothScopeHoistingImprovements ||
|
|
235
|
+
getFeatureFlag('supportWebpackChunkName')
|
|
236
|
+
) {
|
|
237
|
+
// Generally speaking, async bundles should not be executed on load, as
|
|
238
|
+
// they're just collections of assets that other assets require.
|
|
239
|
+
// However, there are some special cases where a runtime asset needs to be
|
|
240
|
+
// injected, but no other asset will require it (mostly the bundle
|
|
241
|
+
// manifest).
|
|
242
|
+
// In this case, those assets need to be required on load.
|
|
243
|
+
entries = entries.filter(
|
|
244
|
+
(a) => a.meta?.runtimeAssetRequiringExecutionOnLoad,
|
|
245
|
+
);
|
|
246
|
+
} else {
|
|
247
|
+
entries = entries.filter((a) => a.id !== mainEntry?.id);
|
|
248
|
+
}
|
|
202
249
|
mainEntry = null;
|
|
203
250
|
}
|
|
204
251
|
|
|
@@ -206,7 +253,7 @@ export class ScopeHoistingPackager {
|
|
|
206
253
|
|
|
207
254
|
// If any of the entry assets are wrapped, call parcelRequire so they are executed.
|
|
208
255
|
for (let entry of entries) {
|
|
209
|
-
if (this.wrappedAssets.has(entry
|
|
256
|
+
if (this.wrappedAssets.has(entry) && !this.isScriptEntry(entry)) {
|
|
210
257
|
let parcelRequire = `parcelRequire(${JSON.stringify(
|
|
211
258
|
this.bundleGraph.getAssetPublicId(entry),
|
|
212
259
|
)});\n`;
|
|
@@ -250,9 +297,7 @@ export class ScopeHoistingPackager {
|
|
|
250
297
|
lineCount++;
|
|
251
298
|
|
|
252
299
|
let mainEntry = nullthrows(this.bundle.getMainEntry());
|
|
253
|
-
let {code, map: mapBuffer} = nullthrows(
|
|
254
|
-
this.assetOutputs.get(mainEntry.id),
|
|
255
|
-
);
|
|
300
|
+
let {code, map: mapBuffer} = nullthrows(this.assetOutputs.get(mainEntry));
|
|
256
301
|
let map;
|
|
257
302
|
if (mapBuffer) {
|
|
258
303
|
map = new SourceMap(this.options.projectRoot, mapBuffer);
|
|
@@ -265,6 +310,7 @@ export class ScopeHoistingPackager {
|
|
|
265
310
|
this.parcelRequireName,
|
|
266
311
|
);
|
|
267
312
|
if (sourceMap && map) {
|
|
313
|
+
// @ts-expect-error TS2339 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
268
314
|
sourceMap.addSourceMap(map, lineCount);
|
|
269
315
|
}
|
|
270
316
|
}
|
|
@@ -281,10 +327,7 @@ export class ScopeHoistingPackager {
|
|
|
281
327
|
|
|
282
328
|
let hasConditionalReference = false;
|
|
283
329
|
let isConditionalBundle = false;
|
|
284
|
-
if (
|
|
285
|
-
getFeatureFlag('conditionalBundlingApi') &&
|
|
286
|
-
getFeatureFlag('conditionalBundlingAsyncRuntime')
|
|
287
|
-
) {
|
|
330
|
+
if (getFeatureFlag('conditionalBundlingApi')) {
|
|
288
331
|
// If the bundle has a conditional bundle reference (has an importCond)
|
|
289
332
|
hasConditionalReference =
|
|
290
333
|
this.bundleGraph.getReferencedConditionalBundles(bundle).length > 0;
|
|
@@ -296,6 +339,7 @@ export class ScopeHoistingPackager {
|
|
|
296
339
|
this.useAsyncBundleRuntime &&
|
|
297
340
|
bundle.type === 'js' &&
|
|
298
341
|
bundle.bundleBehavior !== 'inline' &&
|
|
342
|
+
bundle.bundleBehavior !== 'inlineIsolated' &&
|
|
299
343
|
bundle.env.outputFormat === 'esmodule' &&
|
|
300
344
|
!bundle.env.isIsolated() &&
|
|
301
345
|
bundle.bundleBehavior !== 'isolated' &&
|
|
@@ -309,11 +353,8 @@ export class ScopeHoistingPackager {
|
|
|
309
353
|
.filter((b) => this.shouldBundleQueue(b))
|
|
310
354
|
.map((b) => b.publicId);
|
|
311
355
|
|
|
312
|
-
const conditions = [];
|
|
313
|
-
if (
|
|
314
|
-
getFeatureFlag('conditionalBundlingApi') &&
|
|
315
|
-
getFeatureFlag('conditionalBundlingAsyncRuntime')
|
|
316
|
-
) {
|
|
356
|
+
const conditions: Array<string> = [];
|
|
357
|
+
if (getFeatureFlag('conditionalBundlingApi')) {
|
|
317
358
|
const conditionSet = this.bundleGraph
|
|
318
359
|
.getConditionalBundleMapping()
|
|
319
360
|
.get(bundle.id);
|
|
@@ -354,16 +395,20 @@ export class ScopeHoistingPackager {
|
|
|
354
395
|
return `$parcel$global.rwr(${params.join(', ')});`;
|
|
355
396
|
}
|
|
356
397
|
|
|
357
|
-
async loadAssets()
|
|
358
|
-
|
|
359
|
-
let
|
|
398
|
+
async loadAssets() {
|
|
399
|
+
type QueueItem = [Asset, {code: string; map: Buffer | undefined | null}];
|
|
400
|
+
let queue = new PromiseQueue<QueueItem>({
|
|
401
|
+
maxConcurrent: 32,
|
|
402
|
+
});
|
|
403
|
+
|
|
360
404
|
this.bundle.traverseAssets((asset) => {
|
|
361
405
|
queue.add(async () => {
|
|
362
406
|
let [code, map] = await Promise.all([
|
|
363
407
|
asset.getCode(),
|
|
364
408
|
this.bundle.env.sourceMap ? asset.getMapBuffer() : null,
|
|
365
409
|
]);
|
|
366
|
-
|
|
410
|
+
|
|
411
|
+
return [asset, {code, map}];
|
|
367
412
|
});
|
|
368
413
|
|
|
369
414
|
if (
|
|
@@ -381,52 +426,113 @@ export class ScopeHoistingPackager {
|
|
|
381
426
|
.getIncomingDependencies(asset)
|
|
382
427
|
.some((dep) => dep.priority === 'lazy')
|
|
383
428
|
) {
|
|
384
|
-
this.wrappedAssets.add(asset
|
|
385
|
-
|
|
429
|
+
this.wrappedAssets.add(asset);
|
|
430
|
+
} else if (
|
|
431
|
+
(getFeatureFlag('inlineConstOptimisationFix') ||
|
|
432
|
+
this.useBothScopeHoistingImprovements) &&
|
|
433
|
+
asset.meta.isConstantModule
|
|
434
|
+
) {
|
|
435
|
+
this.constantAssets.add(asset);
|
|
386
436
|
}
|
|
387
437
|
}
|
|
388
438
|
});
|
|
389
439
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
440
|
+
if (this.useBothScopeHoistingImprovements) {
|
|
441
|
+
// Tracks which assets have been assigned to a wrap group
|
|
442
|
+
let assignedAssets = new Set<Asset>();
|
|
443
|
+
|
|
444
|
+
// In V2 scope hoisting, we iterate from the main entry, rather than
|
|
445
|
+
// wrapping the entry assets
|
|
446
|
+
if (!getFeatureFlag('applyScopeHoistingImprovementV2')) {
|
|
447
|
+
// Make all entry assets wrapped, to avoid any top level hoisting
|
|
448
|
+
for (let entryAsset of this.bundle.getEntryAssets()) {
|
|
449
|
+
if (!this.wrappedAssets.has(entryAsset)) {
|
|
450
|
+
this.wrappedAssets.add(entryAsset);
|
|
451
|
+
}
|
|
394
452
|
}
|
|
453
|
+
}
|
|
395
454
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
//
|
|
402
|
-
//
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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);
|
|
455
|
+
// We need to make a new copy here so that we can add to the list and
|
|
456
|
+
// iterate the newly added items, without mutating the wrappedAssets set
|
|
457
|
+
let moduleGroupParents = [...this.wrappedAssets.values()];
|
|
458
|
+
|
|
459
|
+
if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
|
|
460
|
+
// The main entry needs to be check to find assets that would have gone in
|
|
461
|
+
// the top level scope
|
|
462
|
+
let mainEntry = this.bundle.getMainEntry();
|
|
463
|
+
if (mainEntry && !this.wrappedAssets.has(mainEntry)) {
|
|
464
|
+
moduleGroupParents.unshift(mainEntry);
|
|
424
465
|
}
|
|
425
|
-
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
for (let moduleGroupParentAsset of moduleGroupParents) {
|
|
469
|
+
this.bundle.traverseAssets((asset, _, actions) => {
|
|
470
|
+
if (asset === moduleGroupParentAsset) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (this.wrappedAssets.has(asset)) {
|
|
475
|
+
actions.skipChildren();
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (
|
|
480
|
+
!asset.meta.isConstantModule &&
|
|
481
|
+
(assignedAssets.has(asset) || this.isReExported(asset))
|
|
482
|
+
) {
|
|
483
|
+
this.wrappedAssets.add(asset);
|
|
484
|
+
|
|
485
|
+
// This also needs to be added to the traversal so that we iterate
|
|
486
|
+
// it during this check.
|
|
487
|
+
moduleGroupParents.push(asset);
|
|
488
|
+
|
|
489
|
+
actions.skipChildren();
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
assignedAssets.add(asset);
|
|
494
|
+
}, moduleGroupParentAsset);
|
|
495
|
+
}
|
|
496
|
+
} else {
|
|
497
|
+
for (let wrappedAssetRoot of this.wrappedAssets) {
|
|
498
|
+
this.bundle.traverseAssets((asset, _, actions) => {
|
|
499
|
+
if (asset === wrappedAssetRoot) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (this.wrappedAssets.has(asset)) {
|
|
504
|
+
actions.skipChildren();
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (!asset.meta.isConstantModule) {
|
|
509
|
+
this.wrappedAssets.add(asset);
|
|
510
|
+
}
|
|
511
|
+
}, wrappedAssetRoot);
|
|
512
|
+
}
|
|
426
513
|
}
|
|
427
514
|
|
|
428
515
|
this.assetOutputs = new Map(await queue.run());
|
|
429
|
-
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
isReExported(asset: Asset): boolean {
|
|
519
|
+
let parentSymbols = this.bundleGraph
|
|
520
|
+
.getIncomingDependencies(asset)
|
|
521
|
+
.map((dep) => this.bundleGraph.getAssetWithDependency(dep))
|
|
522
|
+
.flatMap((parent) => {
|
|
523
|
+
if (parent == null) {
|
|
524
|
+
return [];
|
|
525
|
+
}
|
|
526
|
+
return this.bundleGraph.getExportedSymbols(parent, this.bundle);
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
let assetSymbols = this.bundleGraph.getExportedSymbols(asset, this.bundle);
|
|
530
|
+
|
|
531
|
+
return assetSymbols.some((assetSymbol) =>
|
|
532
|
+
parentSymbols.some(
|
|
533
|
+
(parentSymbol) => parentSymbol.symbol === assetSymbol.symbol,
|
|
534
|
+
),
|
|
535
|
+
);
|
|
430
536
|
}
|
|
431
537
|
|
|
432
538
|
buildExportedSymbols() {
|
|
@@ -439,7 +545,7 @@ export class ScopeHoistingPackager {
|
|
|
439
545
|
|
|
440
546
|
// TODO: handle ESM exports of wrapped entry assets...
|
|
441
547
|
let entry = this.bundle.getMainEntry();
|
|
442
|
-
if (entry && !this.wrappedAssets.has(entry
|
|
548
|
+
if (entry && !this.wrappedAssets.has(entry)) {
|
|
443
549
|
let hasNamespace = entry.symbols.hasExportSymbol('*');
|
|
444
550
|
|
|
445
551
|
for (let {
|
|
@@ -464,6 +570,7 @@ export class ScopeHoistingPackager {
|
|
|
464
570
|
symbols = [];
|
|
465
571
|
this.exportedSymbols.set(symbol, {
|
|
466
572
|
asset,
|
|
573
|
+
|
|
467
574
|
exportSymbol,
|
|
468
575
|
local: symbol,
|
|
469
576
|
exportAs: symbols,
|
|
@@ -519,20 +626,24 @@ export class ScopeHoistingPackager {
|
|
|
519
626
|
return `${obj}[${JSON.stringify(property)}]`;
|
|
520
627
|
}
|
|
521
628
|
|
|
522
|
-
visitAsset(asset: Asset): [string,
|
|
523
|
-
invariant(!this.seenAssets.has(asset
|
|
524
|
-
this.seenAssets.add(asset
|
|
629
|
+
visitAsset(asset: Asset): [string, SourceMap | null | undefined, number] {
|
|
630
|
+
invariant(!this.seenAssets.has(asset), 'Already visited asset');
|
|
631
|
+
this.seenAssets.add(asset);
|
|
525
632
|
|
|
526
|
-
let {code, map} = nullthrows(this.assetOutputs.get(asset
|
|
633
|
+
let {code, map} = nullthrows(this.assetOutputs.get(asset));
|
|
527
634
|
return this.buildAsset(asset, code, map);
|
|
528
635
|
}
|
|
529
636
|
|
|
637
|
+
getAssetFilePath(asset: Asset): string {
|
|
638
|
+
return path.relative(this.options.projectRoot, asset.filePath);
|
|
639
|
+
}
|
|
640
|
+
|
|
530
641
|
buildAsset(
|
|
531
642
|
asset: Asset,
|
|
532
643
|
code: string,
|
|
533
|
-
map
|
|
534
|
-
): [string,
|
|
535
|
-
let shouldWrap = this.wrappedAssets.has(asset
|
|
644
|
+
map?: Buffer | null,
|
|
645
|
+
): [string, SourceMap | null | undefined, number] {
|
|
646
|
+
let shouldWrap = this.wrappedAssets.has(asset);
|
|
536
647
|
let deps = this.bundleGraph.getDependencies(asset);
|
|
537
648
|
|
|
538
649
|
let sourceMap =
|
|
@@ -559,16 +670,24 @@ export class ScopeHoistingPackager {
|
|
|
559
670
|
continue;
|
|
560
671
|
}
|
|
561
672
|
|
|
562
|
-
if (
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
673
|
+
if (this.bundle.hasAsset(resolved) && !this.seenAssets.has(resolved)) {
|
|
674
|
+
if (
|
|
675
|
+
this.useBothScopeHoistingImprovements &&
|
|
676
|
+
this.wrappedAssets.has(resolved)
|
|
677
|
+
) {
|
|
678
|
+
// When the dep is wrapped then we just need to drop a side effect
|
|
679
|
+
// require instead of inlining
|
|
680
|
+
depCode += `parcelRequire("${this.bundleGraph.getAssetPublicId(resolved)}");\n`;
|
|
681
|
+
lineCount += 1;
|
|
682
|
+
} else {
|
|
683
|
+
let [code, map, lines] = this.visitAsset(resolved);
|
|
684
|
+
depCode += code + '\n';
|
|
685
|
+
if (sourceMap && map) {
|
|
686
|
+
// @ts-expect-error TS2551 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
687
|
+
sourceMap.addSourceMap(map, lineCount);
|
|
688
|
+
}
|
|
689
|
+
lineCount += lines + 1;
|
|
570
690
|
}
|
|
571
|
-
lineCount += lines + 1;
|
|
572
691
|
}
|
|
573
692
|
}
|
|
574
693
|
|
|
@@ -602,7 +721,7 @@ export class ScopeHoistingPackager {
|
|
|
602
721
|
code += append;
|
|
603
722
|
|
|
604
723
|
let lineCount = 0;
|
|
605
|
-
let depContent = [];
|
|
724
|
+
let depContent: Array<[string, SourceMap | null | undefined, number]> = [];
|
|
606
725
|
if (depMap.size === 0 && replacements.size === 0) {
|
|
607
726
|
// If there are no dependencies or replacements, use a simple function to count the number of lines.
|
|
608
727
|
lineCount = countLines(code) - 1;
|
|
@@ -647,27 +766,68 @@ export class ScopeHoistingPackager {
|
|
|
647
766
|
// after the dependency is declared. This handles the case where the resulting asset
|
|
648
767
|
// is wrapped, but the dependency in this asset is not marked as wrapped. This means
|
|
649
768
|
// that it was imported/required at the top-level, so its side effects should run immediately.
|
|
650
|
-
let
|
|
651
|
-
|
|
652
|
-
dep,
|
|
653
|
-
resolved,
|
|
654
|
-
);
|
|
769
|
+
let res = '';
|
|
770
|
+
let lines = 0;
|
|
655
771
|
let map;
|
|
772
|
+
|
|
773
|
+
if (!getFeatureFlag('applyScopeHoistingImprovementV2')) {
|
|
774
|
+
[res, lines] = this.getHoistedParcelRequires(
|
|
775
|
+
asset,
|
|
776
|
+
dep,
|
|
777
|
+
resolved,
|
|
778
|
+
);
|
|
779
|
+
}
|
|
780
|
+
|
|
656
781
|
if (
|
|
657
782
|
this.bundle.hasAsset(resolved) &&
|
|
658
|
-
!this.seenAssets.has(resolved
|
|
783
|
+
!this.seenAssets.has(resolved)
|
|
659
784
|
) {
|
|
660
785
|
// If this asset is wrapped, we need to hoist the code for the dependency
|
|
661
786
|
// outside our parcelRequire.register wrapper. This is safe because all
|
|
662
787
|
// assets referenced by this asset will also be wrapped. Otherwise, inline the
|
|
663
788
|
// asset content where the import statement was.
|
|
664
|
-
if (
|
|
665
|
-
|
|
789
|
+
if (this.useBothScopeHoistingImprovements) {
|
|
790
|
+
if (
|
|
791
|
+
!resolved.meta.isConstantModule &&
|
|
792
|
+
!this.wrappedAssets.has(resolved)
|
|
793
|
+
) {
|
|
794
|
+
let [depCode, depMap, depLines] =
|
|
795
|
+
this.visitAsset(resolved);
|
|
796
|
+
if (debugTools['asset-file-names-in-output']) {
|
|
797
|
+
let resolvedPath = this.getAssetFilePath(resolved);
|
|
798
|
+
res = outdent`
|
|
799
|
+
/* Scope hoisted asset: ${resolvedPath} */
|
|
800
|
+
${depCode}
|
|
801
|
+
/* End: ${resolvedPath} */
|
|
802
|
+
${res}
|
|
803
|
+
`;
|
|
804
|
+
lines += 3 + depLines;
|
|
805
|
+
} else {
|
|
806
|
+
res = depCode + '\n' + res;
|
|
807
|
+
lines += 1 + depLines;
|
|
808
|
+
}
|
|
809
|
+
map = depMap;
|
|
810
|
+
}
|
|
666
811
|
} else {
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
812
|
+
if (shouldWrap) {
|
|
813
|
+
depContent.push(this.visitAsset(resolved));
|
|
814
|
+
} else {
|
|
815
|
+
let [depCode, depMap, depLines] =
|
|
816
|
+
this.visitAsset(resolved);
|
|
817
|
+
res = depCode + '\n' + res;
|
|
818
|
+
lines += 1 + depLines;
|
|
819
|
+
map = depMap;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
|
|
825
|
+
let [requiresCode, requiresLines] =
|
|
826
|
+
this.getHoistedParcelRequires(asset, dep, resolved);
|
|
827
|
+
|
|
828
|
+
if (requiresCode) {
|
|
829
|
+
res = requiresCode + '\n' + res;
|
|
830
|
+
lines += requiresLines + 1;
|
|
671
831
|
}
|
|
672
832
|
}
|
|
673
833
|
|
|
@@ -679,6 +839,7 @@ export class ScopeHoistingPackager {
|
|
|
679
839
|
}
|
|
680
840
|
|
|
681
841
|
if (map) {
|
|
842
|
+
// @ts-expect-error TS2551 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
682
843
|
sourceMap.addSourceMap(map, lineCount);
|
|
683
844
|
}
|
|
684
845
|
}
|
|
@@ -726,10 +887,16 @@ ${code}
|
|
|
726
887
|
|
|
727
888
|
lineCount += 2;
|
|
728
889
|
|
|
890
|
+
if (debugTools['asset-file-names-in-output']) {
|
|
891
|
+
code = `/* ${this.getAssetFilePath(asset)} */\n` + code;
|
|
892
|
+
lineCount += 1;
|
|
893
|
+
}
|
|
894
|
+
|
|
729
895
|
for (let [depCode, map, lines] of depContent) {
|
|
730
896
|
if (!depCode) continue;
|
|
731
897
|
code += depCode + '\n';
|
|
732
898
|
if (sourceMap && map) {
|
|
899
|
+
// @ts-expect-error TS2551 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
733
900
|
sourceMap.addSourceMap(map, lineCount);
|
|
734
901
|
}
|
|
735
902
|
lineCount += lines + 1;
|
|
@@ -848,7 +1015,7 @@ ${code}
|
|
|
848
1015
|
// If this asset is wrapped, we need to replace the exports namespace with `module.exports`,
|
|
849
1016
|
// which will be provided to us by the wrapper.
|
|
850
1017
|
if (
|
|
851
|
-
this.wrappedAssets.has(asset
|
|
1018
|
+
this.wrappedAssets.has(asset) ||
|
|
852
1019
|
(this.bundle.env.outputFormat === 'commonjs' &&
|
|
853
1020
|
asset === this.bundle.getMainEntry())
|
|
854
1021
|
) {
|
|
@@ -895,7 +1062,9 @@ ${code}
|
|
|
895
1062
|
|
|
896
1063
|
for (let [imported, {local}] of dep.symbols) {
|
|
897
1064
|
// If already imported, just add the already renamed variable to the mapping.
|
|
1065
|
+
|
|
898
1066
|
let renamed = external.get(imported);
|
|
1067
|
+
|
|
899
1068
|
if (renamed && local !== '*' && replacements) {
|
|
900
1069
|
replacements.set(local, renamed);
|
|
901
1070
|
continue;
|
|
@@ -908,6 +1077,7 @@ ${code}
|
|
|
908
1077
|
if (!renamed) {
|
|
909
1078
|
if (referencedBundle) {
|
|
910
1079
|
let entry = nullthrows(referencedBundle.getMainEntry());
|
|
1080
|
+
|
|
911
1081
|
renamed =
|
|
912
1082
|
entry.symbols.get('*')?.local ??
|
|
913
1083
|
`$${String(entry.meta.id)}$exports`;
|
|
@@ -922,6 +1092,7 @@ ${code}
|
|
|
922
1092
|
|
|
923
1093
|
if (local !== '*' && replacements) {
|
|
924
1094
|
let replacement;
|
|
1095
|
+
|
|
925
1096
|
if (imported === '*') {
|
|
926
1097
|
replacement = renamed;
|
|
927
1098
|
} else if (imported === 'default') {
|
|
@@ -946,10 +1117,12 @@ ${code}
|
|
|
946
1117
|
let property;
|
|
947
1118
|
if (referencedBundle) {
|
|
948
1119
|
let entry = nullthrows(referencedBundle.getMainEntry());
|
|
1120
|
+
|
|
949
1121
|
if (entry.symbols.hasExportSymbol('*')) {
|
|
950
1122
|
// If importing * and the referenced module has a * export (e.g. CJS), use default instead.
|
|
951
1123
|
// This mirrors the logic in buildExportedSymbols.
|
|
952
1124
|
property = imported;
|
|
1125
|
+
|
|
953
1126
|
imported =
|
|
954
1127
|
referencedBundle?.env.outputFormat === 'esmodule'
|
|
955
1128
|
? 'default'
|
|
@@ -957,6 +1130,7 @@ ${code}
|
|
|
957
1130
|
} else {
|
|
958
1131
|
if (imported === '*') {
|
|
959
1132
|
let exportedSymbols = this.bundleGraph.getExportedSymbols(entry);
|
|
1133
|
+
|
|
960
1134
|
if (local === '*') {
|
|
961
1135
|
// Re-export all symbols.
|
|
962
1136
|
for (let exported of exportedSymbols) {
|
|
@@ -967,11 +1141,10 @@ ${code}
|
|
|
967
1141
|
continue;
|
|
968
1142
|
}
|
|
969
1143
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
imported,
|
|
973
|
-
|
|
974
|
-
).symbol;
|
|
1144
|
+
|
|
1145
|
+
renamed =
|
|
1146
|
+
this.bundleGraph.getSymbolResolution(entry, imported, this.bundle)
|
|
1147
|
+
.symbol || undefined;
|
|
975
1148
|
}
|
|
976
1149
|
}
|
|
977
1150
|
|
|
@@ -993,8 +1166,10 @@ ${code}
|
|
|
993
1166
|
}
|
|
994
1167
|
|
|
995
1168
|
external.set(imported, renamed);
|
|
1169
|
+
|
|
996
1170
|
if (local !== '*' && replacements) {
|
|
997
1171
|
let replacement = renamed;
|
|
1172
|
+
|
|
998
1173
|
if (property === '*') {
|
|
999
1174
|
replacement = renamed;
|
|
1000
1175
|
} else if (property === 'default') {
|
|
@@ -1003,6 +1178,7 @@ ${code}
|
|
|
1003
1178
|
} else if (property) {
|
|
1004
1179
|
replacement = this.getPropertyAccess(renamed, property);
|
|
1005
1180
|
}
|
|
1181
|
+
|
|
1006
1182
|
replacements.set(local, replacement);
|
|
1007
1183
|
}
|
|
1008
1184
|
}
|
|
@@ -1026,7 +1202,7 @@ ${code}
|
|
|
1026
1202
|
}
|
|
1027
1203
|
return (
|
|
1028
1204
|
(!this.bundle.hasAsset(resolved) && !this.externalAssets.has(resolved)) ||
|
|
1029
|
-
(this.wrappedAssets.has(resolved
|
|
1205
|
+
(this.wrappedAssets.has(resolved) && resolved !== parentAsset)
|
|
1030
1206
|
);
|
|
1031
1207
|
}
|
|
1032
1208
|
|
|
@@ -1076,14 +1252,14 @@ ${code}
|
|
|
1076
1252
|
(!this.bundle.hasAsset(resolvedAsset) ||
|
|
1077
1253
|
!this.shouldSkipAsset(resolvedAsset))
|
|
1078
1254
|
) {
|
|
1079
|
-
let hoisted = this.hoistedRequires.get(dep
|
|
1255
|
+
let hoisted = this.hoistedRequires.get(dep);
|
|
1080
1256
|
if (!hoisted) {
|
|
1081
1257
|
hoisted = new Map();
|
|
1082
|
-
this.hoistedRequires.set(dep
|
|
1258
|
+
this.hoistedRequires.set(dep, hoisted);
|
|
1083
1259
|
}
|
|
1084
1260
|
|
|
1085
1261
|
hoisted.set(
|
|
1086
|
-
resolvedAsset
|
|
1262
|
+
resolvedAsset,
|
|
1087
1263
|
`var $${publicId} = parcelRequire(${JSON.stringify(publicId)});`,
|
|
1088
1264
|
);
|
|
1089
1265
|
}
|
|
@@ -1117,6 +1293,7 @@ ${code}
|
|
|
1117
1293
|
obj = `$${publicId}`;
|
|
1118
1294
|
} else {
|
|
1119
1295
|
obj = resolvedAsset.symbols.get('*')?.local || `$${assetId}$exports`;
|
|
1296
|
+
|
|
1120
1297
|
obj = replacements?.get(obj) || obj;
|
|
1121
1298
|
}
|
|
1122
1299
|
|
|
@@ -1124,7 +1301,7 @@ ${code}
|
|
|
1124
1301
|
// Resolve to the namespace object if requested or this is a CJS default interop reqiure.
|
|
1125
1302
|
if (
|
|
1126
1303
|
parentAsset === resolvedAsset &&
|
|
1127
|
-
this.wrappedAssets.has(resolvedAsset
|
|
1304
|
+
this.wrappedAssets.has(resolvedAsset)
|
|
1128
1305
|
) {
|
|
1129
1306
|
// Directly use module.exports for wrapped assets importing themselves.
|
|
1130
1307
|
return 'module.exports';
|
|
@@ -1167,7 +1344,7 @@ ${code}
|
|
|
1167
1344
|
return ['', 0];
|
|
1168
1345
|
}
|
|
1169
1346
|
|
|
1170
|
-
let hoisted = this.hoistedRequires.get(dep
|
|
1347
|
+
let hoisted = this.hoistedRequires.get(dep);
|
|
1171
1348
|
let res = '';
|
|
1172
1349
|
let lineCount = 0;
|
|
1173
1350
|
let isWrapped = this.isWrapped(resolved, parentAsset);
|
|
@@ -1179,7 +1356,7 @@ ${code}
|
|
|
1179
1356
|
if (
|
|
1180
1357
|
isWrapped &&
|
|
1181
1358
|
!dep.meta.shouldWrap &&
|
|
1182
|
-
(!hoisted || hoisted.keys().next().value !== resolved
|
|
1359
|
+
(!hoisted || hoisted.keys().next().value !== resolved) &&
|
|
1183
1360
|
!this.bundleGraph.isDependencySkipped(dep) &&
|
|
1184
1361
|
!this.shouldSkipAsset(resolved)
|
|
1185
1362
|
) {
|
|
@@ -1191,8 +1368,22 @@ ${code}
|
|
|
1191
1368
|
|
|
1192
1369
|
if (hoisted) {
|
|
1193
1370
|
this.needsPrelude = true;
|
|
1194
|
-
|
|
1195
|
-
|
|
1371
|
+
|
|
1372
|
+
if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
|
|
1373
|
+
let hoistedValues = [...hoisted.values()].filter(
|
|
1374
|
+
(val) => !this.seenHoistedRequires.has(val),
|
|
1375
|
+
);
|
|
1376
|
+
|
|
1377
|
+
for (let val of hoistedValues) {
|
|
1378
|
+
this.seenHoistedRequires.add(val);
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
res += '\n' + hoistedValues.join('\n');
|
|
1382
|
+
lineCount += hoisted.size;
|
|
1383
|
+
} else {
|
|
1384
|
+
res += '\n' + [...hoisted.values()].join('\n');
|
|
1385
|
+
lineCount += hoisted.size;
|
|
1386
|
+
}
|
|
1196
1387
|
}
|
|
1197
1388
|
|
|
1198
1389
|
return [res, lineCount];
|
|
@@ -1207,7 +1398,7 @@ ${code}
|
|
|
1207
1398
|
let prependLineCount = 0;
|
|
1208
1399
|
let append = '';
|
|
1209
1400
|
|
|
1210
|
-
let shouldWrap = this.wrappedAssets.has(asset
|
|
1401
|
+
let shouldWrap = this.wrappedAssets.has(asset);
|
|
1211
1402
|
let usedSymbols = nullthrows(this.bundleGraph.getUsedSymbols(asset));
|
|
1212
1403
|
let assetId = asset.meta.id;
|
|
1213
1404
|
invariant(typeof assetId === 'string');
|
|
@@ -1220,34 +1411,51 @@ ${code}
|
|
|
1220
1411
|
usedSymbols.has('default') &&
|
|
1221
1412
|
!asset.symbols.hasExportSymbol('__esModule');
|
|
1222
1413
|
|
|
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
|
-
|
|
1414
|
+
let usedNamespace;
|
|
1415
|
+
if (
|
|
1416
|
+
getFeatureFlag('inlineConstOptimisationFix') &&
|
|
1417
|
+
asset.meta.isConstantModule
|
|
1418
|
+
) {
|
|
1419
|
+
// Only set usedNamespace if there is an incoming dependency in the current bundle that uses '*'
|
|
1420
|
+
usedNamespace = this.bundleGraph
|
|
1421
|
+
.getIncomingDependencies(asset)
|
|
1422
|
+
.some(
|
|
1423
|
+
(dep) =>
|
|
1424
|
+
this.bundle.hasDependency(dep) &&
|
|
1425
|
+
nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
|
|
1426
|
+
);
|
|
1427
|
+
} else {
|
|
1428
|
+
usedNamespace =
|
|
1429
|
+
// If the asset has * in its used symbols, we might need the exports namespace.
|
|
1430
|
+
// The one case where this isn't true is in ESM library entries, where the only
|
|
1431
|
+
// dependency on * is the entry dependency. In this case, we will use ESM exports
|
|
1432
|
+
// instead of the namespace object.
|
|
1433
|
+
|
|
1434
|
+
(usedSymbols.has('*') &&
|
|
1435
|
+
(this.bundle.env.outputFormat !== 'esmodule' ||
|
|
1436
|
+
!this.bundle.env.isLibrary ||
|
|
1437
|
+
asset !== this.bundle.getMainEntry() ||
|
|
1438
|
+
this.bundleGraph
|
|
1439
|
+
.getIncomingDependencies(asset)
|
|
1440
|
+
.some(
|
|
1441
|
+
(dep) =>
|
|
1442
|
+
!dep.isEntry &&
|
|
1443
|
+
this.bundle.hasDependency(dep) &&
|
|
1444
|
+
nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
|
|
1445
|
+
))) ||
|
|
1446
|
+
// If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
|
|
1447
|
+
// we fallback on the namespace object.
|
|
1448
|
+
|
|
1449
|
+
(asset.symbols.hasExportSymbol('*') &&
|
|
1450
|
+
[...usedSymbols].some((s) => !asset.symbols.hasExportSymbol(s))) ||
|
|
1451
|
+
// If the exports has this asset's namespace (e.g. ESM output from CJS input),
|
|
1452
|
+
// include the namespace object for the default export.
|
|
1453
|
+
this.exportedSymbols.has(`$${assetId}$exports`) ||
|
|
1454
|
+
// CommonJS library bundle entries always need a namespace.
|
|
1455
|
+
(this.bundle.env.isLibrary &&
|
|
1456
|
+
this.bundle.env.outputFormat === 'commonjs' &&
|
|
1457
|
+
asset === this.bundle.getMainEntry());
|
|
1458
|
+
}
|
|
1251
1459
|
|
|
1252
1460
|
// If the asset doesn't have static exports, should wrap, the namespace is used,
|
|
1253
1461
|
// or we need default interop, then we need to synthesize a namespace object for
|
|
@@ -1274,6 +1482,7 @@ ${code}
|
|
|
1274
1482
|
// Insert the __esModule interop flag for this module if it has a `default` export
|
|
1275
1483
|
// and the namespace symbol is used.
|
|
1276
1484
|
// TODO: only if required by CJS?
|
|
1485
|
+
|
|
1277
1486
|
if (asset.symbols.hasExportSymbol('default') && usedSymbols.has('*')) {
|
|
1278
1487
|
prepend += `\n$parcel$defineInteropFlag($${assetId}$exports);\n`;
|
|
1279
1488
|
prependLineCount += 2;
|
|
@@ -1337,6 +1546,7 @@ ${code}
|
|
|
1337
1546
|
let resolvedSymbol = this.getSymbolResolution(
|
|
1338
1547
|
asset,
|
|
1339
1548
|
resolved,
|
|
1549
|
+
|
|
1340
1550
|
symbol,
|
|
1341
1551
|
undefined,
|
|
1342
1552
|
replacements,
|
|
@@ -1388,28 +1598,36 @@ ${code}
|
|
|
1388
1598
|
// for the symbol so that when the value changes the object property also changes. This is
|
|
1389
1599
|
// required to simulate ESM live bindings. It's easier to do it this way rather than inserting
|
|
1390
1600
|
// additional assignments after each mutation of the original binding.
|
|
1391
|
-
|
|
1392
|
-
.
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1601
|
+
for (let exp of usedExports) {
|
|
1602
|
+
let resolved = this.getSymbolResolution(
|
|
1603
|
+
asset,
|
|
1604
|
+
asset,
|
|
1605
|
+
exp,
|
|
1606
|
+
undefined,
|
|
1607
|
+
replacements,
|
|
1608
|
+
);
|
|
1609
|
+
const meta = asset.symbols.get(exp)?.meta;
|
|
1610
|
+
if (
|
|
1611
|
+
getFeatureFlag('exportsRebindingOptimisation') &&
|
|
1612
|
+
meta?.isStaticBindingSafe
|
|
1613
|
+
) {
|
|
1614
|
+
append += `$${assetId}$exports[${JSON.stringify(
|
|
1396
1615
|
exp,
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
);
|
|
1616
|
+
)}] = ${resolved};\n`;
|
|
1617
|
+
} else {
|
|
1400
1618
|
let get = this.buildFunctionExpression([], resolved);
|
|
1401
1619
|
let isEsmExport = !!asset.symbols.get(exp)?.meta?.isEsm;
|
|
1402
1620
|
let set =
|
|
1403
1621
|
!isEsmExport && asset.meta.hasCJSExports
|
|
1404
1622
|
? ', ' + this.buildFunctionExpression(['v'], `${resolved} = v`)
|
|
1405
1623
|
: '';
|
|
1406
|
-
|
|
1624
|
+
prepend += `$parcel$export($${assetId}$exports, ${JSON.stringify(
|
|
1407
1625
|
exp,
|
|
1408
|
-
)}, ${get}${set})
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1626
|
+
)}, ${get}${set});\n`;
|
|
1627
|
+
this.usedHelpers.add('$parcel$export');
|
|
1628
|
+
prependLineCount += 1 + usedExports.length;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1413
1631
|
}
|
|
1414
1632
|
}
|
|
1415
1633
|
|
|
@@ -1448,9 +1666,11 @@ ${code}
|
|
|
1448
1666
|
}
|
|
1449
1667
|
|
|
1450
1668
|
for (let helper of this.usedHelpers) {
|
|
1451
|
-
let currentHelper = helpers[helper];
|
|
1669
|
+
let currentHelper = (helpers as Record<string, any>)[helper];
|
|
1452
1670
|
if (typeof currentHelper === 'function') {
|
|
1453
|
-
currentHelper = helpers[helper](
|
|
1671
|
+
currentHelper = (helpers as Record<string, any>)[helper](
|
|
1672
|
+
this.bundle.env,
|
|
1673
|
+
);
|
|
1454
1674
|
}
|
|
1455
1675
|
res += currentHelper;
|
|
1456
1676
|
if (enableSourceMaps) {
|
|
@@ -1470,11 +1690,14 @@ ${code}
|
|
|
1470
1690
|
.some((g) => this.bundleGraph.isEntryBundleGroup(g)) ||
|
|
1471
1691
|
this.bundle.env.isIsolated() ||
|
|
1472
1692
|
this.bundle.bundleBehavior === 'isolated' ||
|
|
1693
|
+
this.bundle.bundleBehavior === 'inlineIsolated' ||
|
|
1473
1694
|
// Conditional deps may be loaded before entrypoints on the server
|
|
1474
1695
|
this.hasConditionalDependency();
|
|
1475
1696
|
|
|
1476
1697
|
if (mightBeFirstJS) {
|
|
1477
|
-
let preludeCode =
|
|
1698
|
+
let preludeCode = (
|
|
1699
|
+
getFeatureFlag('useNewPrelude') ? preludeNew : preludeOld
|
|
1700
|
+
)(this.parcelRequireName);
|
|
1478
1701
|
res += preludeCode;
|
|
1479
1702
|
if (enableSourceMaps) {
|
|
1480
1703
|
lines += countLines(preludeCode) - 1;
|
|
@@ -1498,7 +1721,11 @@ ${code}
|
|
|
1498
1721
|
}
|
|
1499
1722
|
|
|
1500
1723
|
// Add importScripts for sibling bundles in workers.
|
|
1501
|
-
if (
|
|
1724
|
+
if (
|
|
1725
|
+
this.bundle.env.isWorker() ||
|
|
1726
|
+
this.bundle.env.isTesseract() ||
|
|
1727
|
+
this.bundle.env.isWorklet()
|
|
1728
|
+
) {
|
|
1502
1729
|
let importScripts = '';
|
|
1503
1730
|
let bundles = this.bundleGraph.getReferencedBundles(this.bundle);
|
|
1504
1731
|
for (let b of bundles) {
|