@atlaspack/packager-js 2.14.5-canary.22 → 2.14.5-canary.220
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 +358 -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 +1365 -0
- package/dist/helpers.js +170 -0
- package/dist/index.js +105 -0
- package/dist/utils.js +60 -0
- package/lib/DevPackager.js +28 -3
- package/lib/ESMOutputFormat.js +1 -1
- package/lib/ScopeHoistingPackager.js +257 -106
- package/lib/dev-prelude.js +6 -6
- package/lib/helpers.js +38 -3
- package/lib/index.js +3 -3
- 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 +66 -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} +411 -176
- package/src/dev-prelude.js +6 -6
- package/src/{helpers.js → helpers.ts} +37 -3
- package/src/{index.js → index.ts} +21 -17
- 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,8 @@ import {
|
|
|
15
13
|
relativeBundlePath,
|
|
16
14
|
countLines,
|
|
17
15
|
normalizeSeparators,
|
|
16
|
+
debugTools,
|
|
17
|
+
globToRegex,
|
|
18
18
|
} from '@atlaspack/utils';
|
|
19
19
|
import SourceMap from '@parcel/source-map';
|
|
20
20
|
import nullthrows from 'nullthrows';
|
|
@@ -25,11 +25,18 @@ import ThrowableDiagnostic, {
|
|
|
25
25
|
import globals from 'globals';
|
|
26
26
|
import path from 'path';
|
|
27
27
|
import {getFeatureFlag} from '@atlaspack/feature-flags';
|
|
28
|
+
import {outdent} from 'outdent';
|
|
28
29
|
|
|
29
30
|
import {ESMOutputFormat} from './ESMOutputFormat';
|
|
30
31
|
import {CJSOutputFormat} from './CJSOutputFormat';
|
|
31
32
|
import {GlobalOutputFormat} from './GlobalOutputFormat';
|
|
32
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
preludeOld,
|
|
35
|
+
preludeNew,
|
|
36
|
+
helpers,
|
|
37
|
+
bundleQueuePrelude,
|
|
38
|
+
fnExpr,
|
|
39
|
+
} from './helpers';
|
|
33
40
|
import {
|
|
34
41
|
replaceScriptDependencies,
|
|
35
42
|
getSpecifier,
|
|
@@ -39,7 +46,6 @@ import {
|
|
|
39
46
|
|
|
40
47
|
// General regex used to replace imports with the resolved code, references with resolutions,
|
|
41
48
|
// and count the number of newlines in the file for source maps.
|
|
42
|
-
//
|
|
43
49
|
// For conditional bundling the only difference in this regex is adding `importCond` where we have `importAsync` etc..
|
|
44
50
|
const REPLACEMENT_RE_CONDITIONAL =
|
|
45
51
|
/\n|import\s+"([0-9a-f]{16,20}:.+?)";|(?:\$[0-9a-f]{16,20}\$exports)|(?:\$[0-9a-f]{16,20}\$(?:import|importAsync|require|importCond)\$[0-9a-f]+(?:\$[0-9a-f]+)?)/g;
|
|
@@ -55,6 +61,7 @@ const GLOBALS_BY_CONTEXT = {
|
|
|
55
61
|
...Object.keys(globals.serviceworker),
|
|
56
62
|
]),
|
|
57
63
|
worklet: new Set([...BUILTINS]),
|
|
64
|
+
tesseract: new Set([...BUILTINS, ...Object.keys(globals.worker)]),
|
|
58
65
|
node: new Set([...BUILTINS, ...Object.keys(globals.node)]),
|
|
59
66
|
'electron-main': new Set([...BUILTINS, ...Object.keys(globals.node)]),
|
|
60
67
|
'electron-renderer': new Set([
|
|
@@ -62,13 +69,13 @@ const GLOBALS_BY_CONTEXT = {
|
|
|
62
69
|
...Object.keys(globals.node),
|
|
63
70
|
...Object.keys(globals.browser),
|
|
64
71
|
]),
|
|
65
|
-
};
|
|
72
|
+
} as const;
|
|
66
73
|
|
|
67
74
|
const OUTPUT_FORMATS = {
|
|
68
75
|
esmodule: ESMOutputFormat,
|
|
69
76
|
commonjs: CJSOutputFormat,
|
|
70
77
|
global: GlobalOutputFormat,
|
|
71
|
-
};
|
|
78
|
+
} as const;
|
|
72
79
|
|
|
73
80
|
export interface OutputFormat {
|
|
74
81
|
buildBundlePrelude(): [string, number];
|
|
@@ -83,27 +90,38 @@ export class ScopeHoistingPackager {
|
|
|
83
90
|
useAsyncBundleRuntime: boolean;
|
|
84
91
|
outputFormat: OutputFormat;
|
|
85
92
|
isAsyncBundle: boolean;
|
|
86
|
-
globalNames:
|
|
87
|
-
|
|
93
|
+
globalNames: ReadonlySet<string>;
|
|
94
|
+
manualStaticBindingExports: RegExp[] | null;
|
|
95
|
+
assetOutputs: Map<
|
|
96
|
+
Asset,
|
|
97
|
+
{
|
|
98
|
+
code: string;
|
|
99
|
+
map: Buffer | null | undefined;
|
|
100
|
+
}
|
|
101
|
+
> = new Map();
|
|
88
102
|
exportedSymbols: Map<
|
|
89
103
|
string,
|
|
90
|
-
{
|
|
91
|
-
asset: Asset
|
|
92
|
-
exportSymbol: string
|
|
93
|
-
local: string
|
|
94
|
-
exportAs: Array<string
|
|
95
|
-
|
|
104
|
+
{
|
|
105
|
+
asset: Asset;
|
|
106
|
+
exportSymbol: string;
|
|
107
|
+
local: string;
|
|
108
|
+
exportAs: Array<string>;
|
|
109
|
+
}
|
|
96
110
|
> = new Map();
|
|
97
111
|
externals: Map<string, Map<string, string>> = new Map();
|
|
98
112
|
topLevelNames: Map<string, number> = new Map();
|
|
99
|
-
seenAssets: Set<
|
|
100
|
-
wrappedAssets: Set<
|
|
101
|
-
|
|
113
|
+
seenAssets: Set<Asset> = new Set();
|
|
114
|
+
wrappedAssets: Set<Asset> = new Set();
|
|
115
|
+
constantAssets: Set<Asset> = new Set();
|
|
116
|
+
hoistedRequires: Map<Dependency, Map<Asset, string>> = new Map();
|
|
117
|
+
seenHoistedRequires: Set<string> = new Set();
|
|
102
118
|
needsPrelude: boolean = false;
|
|
103
119
|
usedHelpers: Set<string> = new Set();
|
|
104
120
|
externalAssets: Set<Asset> = new Set();
|
|
105
|
-
forceSkipWrapAssets: Array<string> = [];
|
|
106
121
|
logger: PluginLogger;
|
|
122
|
+
useBothScopeHoistingImprovements: boolean =
|
|
123
|
+
getFeatureFlag('applyScopeHoistingImprovementV2') ||
|
|
124
|
+
getFeatureFlag('applyScopeHoistingImprovement');
|
|
107
125
|
|
|
108
126
|
constructor(
|
|
109
127
|
options: PluginOptions,
|
|
@@ -111,7 +129,7 @@ export class ScopeHoistingPackager {
|
|
|
111
129
|
bundle: NamedBundle,
|
|
112
130
|
parcelRequireName: string,
|
|
113
131
|
useAsyncBundleRuntime: boolean,
|
|
114
|
-
|
|
132
|
+
manualStaticBindingExports: string[] | null,
|
|
115
133
|
logger: PluginLogger,
|
|
116
134
|
) {
|
|
117
135
|
this.options = options;
|
|
@@ -119,7 +137,8 @@ export class ScopeHoistingPackager {
|
|
|
119
137
|
this.bundle = bundle;
|
|
120
138
|
this.parcelRequireName = parcelRequireName;
|
|
121
139
|
this.useAsyncBundleRuntime = useAsyncBundleRuntime;
|
|
122
|
-
this.
|
|
140
|
+
this.manualStaticBindingExports =
|
|
141
|
+
manualStaticBindingExports?.map((glob) => globToRegex(glob)) ?? null;
|
|
123
142
|
this.logger = logger;
|
|
124
143
|
|
|
125
144
|
let OutputFormat = OUTPUT_FORMATS[this.bundle.env.outputFormat];
|
|
@@ -128,13 +147,17 @@ export class ScopeHoistingPackager {
|
|
|
128
147
|
this.isAsyncBundle =
|
|
129
148
|
this.bundleGraph.hasParentBundleOfType(this.bundle, 'js') &&
|
|
130
149
|
!this.bundle.env.isIsolated() &&
|
|
131
|
-
this.bundle.bundleBehavior !== 'isolated'
|
|
150
|
+
this.bundle.bundleBehavior !== 'isolated' &&
|
|
151
|
+
this.bundle.bundleBehavior !== 'inlineIsolated';
|
|
132
152
|
|
|
133
153
|
this.globalNames = GLOBALS_BY_CONTEXT[bundle.env.context];
|
|
134
154
|
}
|
|
135
155
|
|
|
136
|
-
async package(): Promise<{
|
|
137
|
-
|
|
156
|
+
async package(): Promise<{
|
|
157
|
+
contents: string;
|
|
158
|
+
map: SourceMap | null | undefined;
|
|
159
|
+
}> {
|
|
160
|
+
await this.loadAssets();
|
|
138
161
|
this.buildExportedSymbols();
|
|
139
162
|
|
|
140
163
|
// If building a library, the target is actually another bundler rather
|
|
@@ -155,10 +178,13 @@ export class ScopeHoistingPackager {
|
|
|
155
178
|
|
|
156
179
|
let res = '';
|
|
157
180
|
let lineCount = 0;
|
|
158
|
-
let sourceMap = null;
|
|
159
|
-
let processAsset = (asset) => {
|
|
181
|
+
let sourceMap: SourceMap | null | undefined = null;
|
|
182
|
+
let processAsset = (asset: Asset) => {
|
|
183
|
+
this.seenHoistedRequires.clear();
|
|
160
184
|
let [content, map, lines] = this.visitAsset(asset);
|
|
185
|
+
|
|
161
186
|
if (sourceMap && map) {
|
|
187
|
+
// @ts-expect-error TS2551 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
162
188
|
sourceMap.addSourceMap(map, lineCount);
|
|
163
189
|
} else if (this.bundle.env.sourceMap) {
|
|
164
190
|
sourceMap = map;
|
|
@@ -168,10 +194,22 @@ export class ScopeHoistingPackager {
|
|
|
168
194
|
lineCount += lines + 1;
|
|
169
195
|
};
|
|
170
196
|
|
|
197
|
+
if (
|
|
198
|
+
getFeatureFlag('inlineConstOptimisationFix') ||
|
|
199
|
+
this.useBothScopeHoistingImprovements
|
|
200
|
+
) {
|
|
201
|
+
// Write out all constant modules used by this bundle
|
|
202
|
+
for (let asset of this.constantAssets) {
|
|
203
|
+
if (!this.seenAssets.has(asset)) {
|
|
204
|
+
processAsset(asset);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
171
209
|
// Hoist wrapped asset to the top of the bundle to ensure that they are registered
|
|
172
210
|
// before they are used.
|
|
173
|
-
for (let asset of wrappedAssets) {
|
|
174
|
-
if (!this.seenAssets.has(asset
|
|
211
|
+
for (let asset of this.wrappedAssets) {
|
|
212
|
+
if (!this.seenAssets.has(asset)) {
|
|
175
213
|
processAsset(asset);
|
|
176
214
|
}
|
|
177
215
|
}
|
|
@@ -179,7 +217,7 @@ export class ScopeHoistingPackager {
|
|
|
179
217
|
// Add each asset that is directly connected to the bundle. Dependencies will be handled
|
|
180
218
|
// by replacing `import` statements in the code.
|
|
181
219
|
this.bundle.traverseAssets((asset, _, actions) => {
|
|
182
|
-
if (this.seenAssets.has(asset
|
|
220
|
+
if (this.seenAssets.has(asset)) {
|
|
183
221
|
actions.skipChildren();
|
|
184
222
|
return;
|
|
185
223
|
}
|
|
@@ -191,14 +229,28 @@ export class ScopeHoistingPackager {
|
|
|
191
229
|
let [prelude, preludeLines] = this.buildBundlePrelude();
|
|
192
230
|
res = prelude + res;
|
|
193
231
|
lineCount += preludeLines;
|
|
232
|
+
// @ts-expect-error TS2339 - offsetLines method exists but missing from @parcel/source-map type definitions
|
|
194
233
|
sourceMap?.offsetLines(1, preludeLines);
|
|
195
234
|
|
|
196
235
|
let entries = this.bundle.getEntryAssets();
|
|
197
236
|
let mainEntry = this.bundle.getMainEntry();
|
|
198
237
|
if (this.isAsyncBundle) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
238
|
+
if (
|
|
239
|
+
this.useBothScopeHoistingImprovements ||
|
|
240
|
+
getFeatureFlag('supportWebpackChunkName')
|
|
241
|
+
) {
|
|
242
|
+
// Generally speaking, async bundles should not be executed on load, as
|
|
243
|
+
// they're just collections of assets that other assets require.
|
|
244
|
+
// However, there are some special cases where a runtime asset needs to be
|
|
245
|
+
// injected, but no other asset will require it (mostly the bundle
|
|
246
|
+
// manifest).
|
|
247
|
+
// In this case, those assets need to be required on load.
|
|
248
|
+
entries = entries.filter(
|
|
249
|
+
(a) => a.meta?.runtimeAssetRequiringExecutionOnLoad,
|
|
250
|
+
);
|
|
251
|
+
} else {
|
|
252
|
+
entries = entries.filter((a) => a.id !== mainEntry?.id);
|
|
253
|
+
}
|
|
202
254
|
mainEntry = null;
|
|
203
255
|
}
|
|
204
256
|
|
|
@@ -206,7 +258,7 @@ export class ScopeHoistingPackager {
|
|
|
206
258
|
|
|
207
259
|
// If any of the entry assets are wrapped, call parcelRequire so they are executed.
|
|
208
260
|
for (let entry of entries) {
|
|
209
|
-
if (this.wrappedAssets.has(entry
|
|
261
|
+
if (this.wrappedAssets.has(entry) && !this.isScriptEntry(entry)) {
|
|
210
262
|
let parcelRequire = `parcelRequire(${JSON.stringify(
|
|
211
263
|
this.bundleGraph.getAssetPublicId(entry),
|
|
212
264
|
)});\n`;
|
|
@@ -250,9 +302,7 @@ export class ScopeHoistingPackager {
|
|
|
250
302
|
lineCount++;
|
|
251
303
|
|
|
252
304
|
let mainEntry = nullthrows(this.bundle.getMainEntry());
|
|
253
|
-
let {code, map: mapBuffer} = nullthrows(
|
|
254
|
-
this.assetOutputs.get(mainEntry.id),
|
|
255
|
-
);
|
|
305
|
+
let {code, map: mapBuffer} = nullthrows(this.assetOutputs.get(mainEntry));
|
|
256
306
|
let map;
|
|
257
307
|
if (mapBuffer) {
|
|
258
308
|
map = new SourceMap(this.options.projectRoot, mapBuffer);
|
|
@@ -265,6 +315,7 @@ export class ScopeHoistingPackager {
|
|
|
265
315
|
this.parcelRequireName,
|
|
266
316
|
);
|
|
267
317
|
if (sourceMap && map) {
|
|
318
|
+
// @ts-expect-error TS2339 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
268
319
|
sourceMap.addSourceMap(map, lineCount);
|
|
269
320
|
}
|
|
270
321
|
}
|
|
@@ -281,10 +332,7 @@ export class ScopeHoistingPackager {
|
|
|
281
332
|
|
|
282
333
|
let hasConditionalReference = false;
|
|
283
334
|
let isConditionalBundle = false;
|
|
284
|
-
if (
|
|
285
|
-
getFeatureFlag('conditionalBundlingApi') &&
|
|
286
|
-
getFeatureFlag('conditionalBundlingAsyncRuntime')
|
|
287
|
-
) {
|
|
335
|
+
if (getFeatureFlag('conditionalBundlingApi')) {
|
|
288
336
|
// If the bundle has a conditional bundle reference (has an importCond)
|
|
289
337
|
hasConditionalReference =
|
|
290
338
|
this.bundleGraph.getReferencedConditionalBundles(bundle).length > 0;
|
|
@@ -296,6 +344,7 @@ export class ScopeHoistingPackager {
|
|
|
296
344
|
this.useAsyncBundleRuntime &&
|
|
297
345
|
bundle.type === 'js' &&
|
|
298
346
|
bundle.bundleBehavior !== 'inline' &&
|
|
347
|
+
bundle.bundleBehavior !== 'inlineIsolated' &&
|
|
299
348
|
bundle.env.outputFormat === 'esmodule' &&
|
|
300
349
|
!bundle.env.isIsolated() &&
|
|
301
350
|
bundle.bundleBehavior !== 'isolated' &&
|
|
@@ -309,11 +358,8 @@ export class ScopeHoistingPackager {
|
|
|
309
358
|
.filter((b) => this.shouldBundleQueue(b))
|
|
310
359
|
.map((b) => b.publicId);
|
|
311
360
|
|
|
312
|
-
const conditions = [];
|
|
313
|
-
if (
|
|
314
|
-
getFeatureFlag('conditionalBundlingApi') &&
|
|
315
|
-
getFeatureFlag('conditionalBundlingAsyncRuntime')
|
|
316
|
-
) {
|
|
361
|
+
const conditions: Array<string> = [];
|
|
362
|
+
if (getFeatureFlag('conditionalBundlingApi')) {
|
|
317
363
|
const conditionSet = this.bundleGraph
|
|
318
364
|
.getConditionalBundleMapping()
|
|
319
365
|
.get(bundle.id);
|
|
@@ -354,16 +400,20 @@ export class ScopeHoistingPackager {
|
|
|
354
400
|
return `$parcel$global.rwr(${params.join(', ')});`;
|
|
355
401
|
}
|
|
356
402
|
|
|
357
|
-
async loadAssets()
|
|
358
|
-
|
|
359
|
-
let
|
|
403
|
+
async loadAssets() {
|
|
404
|
+
type QueueItem = [Asset, {code: string; map: Buffer | undefined | null}];
|
|
405
|
+
let queue = new PromiseQueue<QueueItem>({
|
|
406
|
+
maxConcurrent: 32,
|
|
407
|
+
});
|
|
408
|
+
|
|
360
409
|
this.bundle.traverseAssets((asset) => {
|
|
361
410
|
queue.add(async () => {
|
|
362
411
|
let [code, map] = await Promise.all([
|
|
363
412
|
asset.getCode(),
|
|
364
413
|
this.bundle.env.sourceMap ? asset.getMapBuffer() : null,
|
|
365
414
|
]);
|
|
366
|
-
|
|
415
|
+
|
|
416
|
+
return [asset, {code, map}];
|
|
367
417
|
});
|
|
368
418
|
|
|
369
419
|
if (
|
|
@@ -381,52 +431,113 @@ export class ScopeHoistingPackager {
|
|
|
381
431
|
.getIncomingDependencies(asset)
|
|
382
432
|
.some((dep) => dep.priority === 'lazy')
|
|
383
433
|
) {
|
|
384
|
-
this.wrappedAssets.add(asset
|
|
385
|
-
|
|
434
|
+
this.wrappedAssets.add(asset);
|
|
435
|
+
} else if (
|
|
436
|
+
(getFeatureFlag('inlineConstOptimisationFix') ||
|
|
437
|
+
this.useBothScopeHoistingImprovements) &&
|
|
438
|
+
asset.meta.isConstantModule
|
|
439
|
+
) {
|
|
440
|
+
this.constantAssets.add(asset);
|
|
386
441
|
}
|
|
387
442
|
}
|
|
388
443
|
});
|
|
389
444
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
445
|
+
if (this.useBothScopeHoistingImprovements) {
|
|
446
|
+
// Tracks which assets have been assigned to a wrap group
|
|
447
|
+
let assignedAssets = new Set<Asset>();
|
|
448
|
+
|
|
449
|
+
// In V2 scope hoisting, we iterate from the main entry, rather than
|
|
450
|
+
// wrapping the entry assets
|
|
451
|
+
if (!getFeatureFlag('applyScopeHoistingImprovementV2')) {
|
|
452
|
+
// Make all entry assets wrapped, to avoid any top level hoisting
|
|
453
|
+
for (let entryAsset of this.bundle.getEntryAssets()) {
|
|
454
|
+
if (!this.wrappedAssets.has(entryAsset)) {
|
|
455
|
+
this.wrappedAssets.add(entryAsset);
|
|
456
|
+
}
|
|
394
457
|
}
|
|
458
|
+
}
|
|
395
459
|
|
|
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);
|
|
460
|
+
// We need to make a new copy here so that we can add to the list and
|
|
461
|
+
// iterate the newly added items, without mutating the wrappedAssets set
|
|
462
|
+
let moduleGroupParents = [...this.wrappedAssets.values()];
|
|
463
|
+
|
|
464
|
+
if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
|
|
465
|
+
// The main entry needs to be check to find assets that would have gone in
|
|
466
|
+
// the top level scope
|
|
467
|
+
let mainEntry = this.bundle.getMainEntry();
|
|
468
|
+
if (mainEntry && !this.wrappedAssets.has(mainEntry)) {
|
|
469
|
+
moduleGroupParents.unshift(mainEntry);
|
|
424
470
|
}
|
|
425
|
-
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
for (let moduleGroupParentAsset of moduleGroupParents) {
|
|
474
|
+
this.bundle.traverseAssets((asset, _, actions) => {
|
|
475
|
+
if (asset === moduleGroupParentAsset) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (this.wrappedAssets.has(asset)) {
|
|
480
|
+
actions.skipChildren();
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (
|
|
485
|
+
!asset.meta.isConstantModule &&
|
|
486
|
+
(assignedAssets.has(asset) || this.isReExported(asset))
|
|
487
|
+
) {
|
|
488
|
+
this.wrappedAssets.add(asset);
|
|
489
|
+
|
|
490
|
+
// This also needs to be added to the traversal so that we iterate
|
|
491
|
+
// it during this check.
|
|
492
|
+
moduleGroupParents.push(asset);
|
|
493
|
+
|
|
494
|
+
actions.skipChildren();
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
assignedAssets.add(asset);
|
|
499
|
+
}, moduleGroupParentAsset);
|
|
500
|
+
}
|
|
501
|
+
} else {
|
|
502
|
+
for (let wrappedAssetRoot of this.wrappedAssets) {
|
|
503
|
+
this.bundle.traverseAssets((asset, _, actions) => {
|
|
504
|
+
if (asset === wrappedAssetRoot) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (this.wrappedAssets.has(asset)) {
|
|
509
|
+
actions.skipChildren();
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (!asset.meta.isConstantModule) {
|
|
514
|
+
this.wrappedAssets.add(asset);
|
|
515
|
+
}
|
|
516
|
+
}, wrappedAssetRoot);
|
|
517
|
+
}
|
|
426
518
|
}
|
|
427
519
|
|
|
428
520
|
this.assetOutputs = new Map(await queue.run());
|
|
429
|
-
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
isReExported(asset: Asset): boolean {
|
|
524
|
+
let parentSymbols = this.bundleGraph
|
|
525
|
+
.getIncomingDependencies(asset)
|
|
526
|
+
.map((dep) => this.bundleGraph.getAssetWithDependency(dep))
|
|
527
|
+
.flatMap((parent) => {
|
|
528
|
+
if (parent == null) {
|
|
529
|
+
return [];
|
|
530
|
+
}
|
|
531
|
+
return this.bundleGraph.getExportedSymbols(parent, this.bundle);
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
let assetSymbols = this.bundleGraph.getExportedSymbols(asset, this.bundle);
|
|
535
|
+
|
|
536
|
+
return assetSymbols.some((assetSymbol) =>
|
|
537
|
+
parentSymbols.some(
|
|
538
|
+
(parentSymbol) => parentSymbol.symbol === assetSymbol.symbol,
|
|
539
|
+
),
|
|
540
|
+
);
|
|
430
541
|
}
|
|
431
542
|
|
|
432
543
|
buildExportedSymbols() {
|
|
@@ -439,7 +550,7 @@ export class ScopeHoistingPackager {
|
|
|
439
550
|
|
|
440
551
|
// TODO: handle ESM exports of wrapped entry assets...
|
|
441
552
|
let entry = this.bundle.getMainEntry();
|
|
442
|
-
if (entry && !this.wrappedAssets.has(entry
|
|
553
|
+
if (entry && !this.wrappedAssets.has(entry)) {
|
|
443
554
|
let hasNamespace = entry.symbols.hasExportSymbol('*');
|
|
444
555
|
|
|
445
556
|
for (let {
|
|
@@ -464,6 +575,7 @@ export class ScopeHoistingPackager {
|
|
|
464
575
|
symbols = [];
|
|
465
576
|
this.exportedSymbols.set(symbol, {
|
|
466
577
|
asset,
|
|
578
|
+
|
|
467
579
|
exportSymbol,
|
|
468
580
|
local: symbol,
|
|
469
581
|
exportAs: symbols,
|
|
@@ -519,20 +631,24 @@ export class ScopeHoistingPackager {
|
|
|
519
631
|
return `${obj}[${JSON.stringify(property)}]`;
|
|
520
632
|
}
|
|
521
633
|
|
|
522
|
-
visitAsset(asset: Asset): [string,
|
|
523
|
-
invariant(!this.seenAssets.has(asset
|
|
524
|
-
this.seenAssets.add(asset
|
|
634
|
+
visitAsset(asset: Asset): [string, SourceMap | null | undefined, number] {
|
|
635
|
+
invariant(!this.seenAssets.has(asset), 'Already visited asset');
|
|
636
|
+
this.seenAssets.add(asset);
|
|
525
637
|
|
|
526
|
-
let {code, map} = nullthrows(this.assetOutputs.get(asset
|
|
638
|
+
let {code, map} = nullthrows(this.assetOutputs.get(asset));
|
|
527
639
|
return this.buildAsset(asset, code, map);
|
|
528
640
|
}
|
|
529
641
|
|
|
642
|
+
getAssetFilePath(asset: Asset): string {
|
|
643
|
+
return path.relative(this.options.projectRoot, asset.filePath);
|
|
644
|
+
}
|
|
645
|
+
|
|
530
646
|
buildAsset(
|
|
531
647
|
asset: Asset,
|
|
532
648
|
code: string,
|
|
533
|
-
map
|
|
534
|
-
): [string,
|
|
535
|
-
let shouldWrap = this.wrappedAssets.has(asset
|
|
649
|
+
map?: Buffer | null,
|
|
650
|
+
): [string, SourceMap | null | undefined, number] {
|
|
651
|
+
let shouldWrap = this.wrappedAssets.has(asset);
|
|
536
652
|
let deps = this.bundleGraph.getDependencies(asset);
|
|
537
653
|
|
|
538
654
|
let sourceMap =
|
|
@@ -559,16 +675,24 @@ export class ScopeHoistingPackager {
|
|
|
559
675
|
continue;
|
|
560
676
|
}
|
|
561
677
|
|
|
562
|
-
if (
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
678
|
+
if (this.bundle.hasAsset(resolved) && !this.seenAssets.has(resolved)) {
|
|
679
|
+
if (
|
|
680
|
+
this.useBothScopeHoistingImprovements &&
|
|
681
|
+
this.wrappedAssets.has(resolved)
|
|
682
|
+
) {
|
|
683
|
+
// When the dep is wrapped then we just need to drop a side effect
|
|
684
|
+
// require instead of inlining
|
|
685
|
+
depCode += `parcelRequire("${this.bundleGraph.getAssetPublicId(resolved)}");\n`;
|
|
686
|
+
lineCount += 1;
|
|
687
|
+
} else {
|
|
688
|
+
let [code, map, lines] = this.visitAsset(resolved);
|
|
689
|
+
depCode += code + '\n';
|
|
690
|
+
if (sourceMap && map) {
|
|
691
|
+
// @ts-expect-error TS2551 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
692
|
+
sourceMap.addSourceMap(map, lineCount);
|
|
693
|
+
}
|
|
694
|
+
lineCount += lines + 1;
|
|
570
695
|
}
|
|
571
|
-
lineCount += lines + 1;
|
|
572
696
|
}
|
|
573
697
|
}
|
|
574
698
|
|
|
@@ -602,7 +726,7 @@ export class ScopeHoistingPackager {
|
|
|
602
726
|
code += append;
|
|
603
727
|
|
|
604
728
|
let lineCount = 0;
|
|
605
|
-
let depContent = [];
|
|
729
|
+
let depContent: Array<[string, SourceMap | null | undefined, number]> = [];
|
|
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,27 +771,68 @@ 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
|
-
!this.seenAssets.has(resolved
|
|
788
|
+
!this.seenAssets.has(resolved)
|
|
659
789
|
) {
|
|
660
790
|
// If this asset is wrapped, we need to hoist the code for the dependency
|
|
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)
|
|
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 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
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 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
733
905
|
sourceMap.addSourceMap(map, lineCount);
|
|
734
906
|
}
|
|
735
907
|
lineCount += lines + 1;
|
|
@@ -848,7 +1020,7 @@ ${code}
|
|
|
848
1020
|
// If this asset is wrapped, we need to replace the exports namespace with `module.exports`,
|
|
849
1021
|
// which will be provided to us by the wrapper.
|
|
850
1022
|
if (
|
|
851
|
-
this.wrappedAssets.has(asset
|
|
1023
|
+
this.wrappedAssets.has(asset) ||
|
|
852
1024
|
(this.bundle.env.outputFormat === 'commonjs' &&
|
|
853
1025
|
asset === this.bundle.getMainEntry())
|
|
854
1026
|
) {
|
|
@@ -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,11 +1146,10 @@ ${code}
|
|
|
967
1146
|
continue;
|
|
968
1147
|
}
|
|
969
1148
|
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
imported,
|
|
973
|
-
|
|
974
|
-
).symbol;
|
|
1149
|
+
|
|
1150
|
+
renamed =
|
|
1151
|
+
this.bundleGraph.getSymbolResolution(entry, imported, this.bundle)
|
|
1152
|
+
.symbol || undefined;
|
|
975
1153
|
}
|
|
976
1154
|
}
|
|
977
1155
|
|
|
@@ -993,8 +1171,10 @@ ${code}
|
|
|
993
1171
|
}
|
|
994
1172
|
|
|
995
1173
|
external.set(imported, renamed);
|
|
1174
|
+
|
|
996
1175
|
if (local !== '*' && replacements) {
|
|
997
1176
|
let replacement = renamed;
|
|
1177
|
+
|
|
998
1178
|
if (property === '*') {
|
|
999
1179
|
replacement = renamed;
|
|
1000
1180
|
} else if (property === 'default') {
|
|
@@ -1003,6 +1183,7 @@ ${code}
|
|
|
1003
1183
|
} else if (property) {
|
|
1004
1184
|
replacement = this.getPropertyAccess(renamed, property);
|
|
1005
1185
|
}
|
|
1186
|
+
|
|
1006
1187
|
replacements.set(local, replacement);
|
|
1007
1188
|
}
|
|
1008
1189
|
}
|
|
@@ -1026,7 +1207,7 @@ ${code}
|
|
|
1026
1207
|
}
|
|
1027
1208
|
return (
|
|
1028
1209
|
(!this.bundle.hasAsset(resolved) && !this.externalAssets.has(resolved)) ||
|
|
1029
|
-
(this.wrappedAssets.has(resolved
|
|
1210
|
+
(this.wrappedAssets.has(resolved) && resolved !== parentAsset)
|
|
1030
1211
|
);
|
|
1031
1212
|
}
|
|
1032
1213
|
|
|
@@ -1076,14 +1257,14 @@ ${code}
|
|
|
1076
1257
|
(!this.bundle.hasAsset(resolvedAsset) ||
|
|
1077
1258
|
!this.shouldSkipAsset(resolvedAsset))
|
|
1078
1259
|
) {
|
|
1079
|
-
let hoisted = this.hoistedRequires.get(dep
|
|
1260
|
+
let hoisted = this.hoistedRequires.get(dep);
|
|
1080
1261
|
if (!hoisted) {
|
|
1081
1262
|
hoisted = new Map();
|
|
1082
|
-
this.hoistedRequires.set(dep
|
|
1263
|
+
this.hoistedRequires.set(dep, hoisted);
|
|
1083
1264
|
}
|
|
1084
1265
|
|
|
1085
1266
|
hoisted.set(
|
|
1086
|
-
resolvedAsset
|
|
1267
|
+
resolvedAsset,
|
|
1087
1268
|
`var $${publicId} = parcelRequire(${JSON.stringify(publicId)});`,
|
|
1088
1269
|
);
|
|
1089
1270
|
}
|
|
@@ -1117,6 +1298,7 @@ ${code}
|
|
|
1117
1298
|
obj = `$${publicId}`;
|
|
1118
1299
|
} else {
|
|
1119
1300
|
obj = resolvedAsset.symbols.get('*')?.local || `$${assetId}$exports`;
|
|
1301
|
+
|
|
1120
1302
|
obj = replacements?.get(obj) || obj;
|
|
1121
1303
|
}
|
|
1122
1304
|
|
|
@@ -1124,7 +1306,7 @@ ${code}
|
|
|
1124
1306
|
// Resolve to the namespace object if requested or this is a CJS default interop reqiure.
|
|
1125
1307
|
if (
|
|
1126
1308
|
parentAsset === resolvedAsset &&
|
|
1127
|
-
this.wrappedAssets.has(resolvedAsset
|
|
1309
|
+
this.wrappedAssets.has(resolvedAsset)
|
|
1128
1310
|
) {
|
|
1129
1311
|
// Directly use module.exports for wrapped assets importing themselves.
|
|
1130
1312
|
return 'module.exports';
|
|
@@ -1167,7 +1349,7 @@ ${code}
|
|
|
1167
1349
|
return ['', 0];
|
|
1168
1350
|
}
|
|
1169
1351
|
|
|
1170
|
-
let hoisted = this.hoistedRequires.get(dep
|
|
1352
|
+
let hoisted = this.hoistedRequires.get(dep);
|
|
1171
1353
|
let res = '';
|
|
1172
1354
|
let lineCount = 0;
|
|
1173
1355
|
let isWrapped = this.isWrapped(resolved, parentAsset);
|
|
@@ -1179,7 +1361,7 @@ ${code}
|
|
|
1179
1361
|
if (
|
|
1180
1362
|
isWrapped &&
|
|
1181
1363
|
!dep.meta.shouldWrap &&
|
|
1182
|
-
(!hoisted || hoisted.keys().next().value !== resolved
|
|
1364
|
+
(!hoisted || hoisted.keys().next().value !== resolved) &&
|
|
1183
1365
|
!this.bundleGraph.isDependencySkipped(dep) &&
|
|
1184
1366
|
!this.shouldSkipAsset(resolved)
|
|
1185
1367
|
) {
|
|
@@ -1191,8 +1373,22 @@ ${code}
|
|
|
1191
1373
|
|
|
1192
1374
|
if (hoisted) {
|
|
1193
1375
|
this.needsPrelude = true;
|
|
1194
|
-
|
|
1195
|
-
|
|
1376
|
+
|
|
1377
|
+
if (getFeatureFlag('applyScopeHoistingImprovementV2')) {
|
|
1378
|
+
let hoistedValues = [...hoisted.values()].filter(
|
|
1379
|
+
(val) => !this.seenHoistedRequires.has(val),
|
|
1380
|
+
);
|
|
1381
|
+
|
|
1382
|
+
for (let val of hoistedValues) {
|
|
1383
|
+
this.seenHoistedRequires.add(val);
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
res += '\n' + hoistedValues.join('\n');
|
|
1387
|
+
lineCount += hoisted.size;
|
|
1388
|
+
} else {
|
|
1389
|
+
res += '\n' + [...hoisted.values()].join('\n');
|
|
1390
|
+
lineCount += hoisted.size;
|
|
1391
|
+
}
|
|
1196
1392
|
}
|
|
1197
1393
|
|
|
1198
1394
|
return [res, lineCount];
|
|
@@ -1207,7 +1403,7 @@ ${code}
|
|
|
1207
1403
|
let prependLineCount = 0;
|
|
1208
1404
|
let append = '';
|
|
1209
1405
|
|
|
1210
|
-
let shouldWrap = this.wrappedAssets.has(asset
|
|
1406
|
+
let shouldWrap = this.wrappedAssets.has(asset);
|
|
1211
1407
|
let usedSymbols = nullthrows(this.bundleGraph.getUsedSymbols(asset));
|
|
1212
1408
|
let assetId = asset.meta.id;
|
|
1213
1409
|
invariant(typeof assetId === 'string');
|
|
@@ -1220,34 +1416,51 @@ ${code}
|
|
|
1220
1416
|
usedSymbols.has('default') &&
|
|
1221
1417
|
!asset.symbols.hasExportSymbol('__esModule');
|
|
1222
1418
|
|
|
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
|
-
|
|
1419
|
+
let usedNamespace;
|
|
1420
|
+
if (
|
|
1421
|
+
getFeatureFlag('inlineConstOptimisationFix') &&
|
|
1422
|
+
asset.meta.isConstantModule
|
|
1423
|
+
) {
|
|
1424
|
+
// Only set usedNamespace if there is an incoming dependency in the current bundle that uses '*'
|
|
1425
|
+
usedNamespace = this.bundleGraph
|
|
1426
|
+
.getIncomingDependencies(asset)
|
|
1427
|
+
.some(
|
|
1428
|
+
(dep) =>
|
|
1429
|
+
this.bundle.hasDependency(dep) &&
|
|
1430
|
+
nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
|
|
1431
|
+
);
|
|
1432
|
+
} else {
|
|
1433
|
+
usedNamespace =
|
|
1434
|
+
// If the asset has * in its used symbols, we might need the exports namespace.
|
|
1435
|
+
// The one case where this isn't true is in ESM library entries, where the only
|
|
1436
|
+
// dependency on * is the entry dependency. In this case, we will use ESM exports
|
|
1437
|
+
// instead of the namespace object.
|
|
1438
|
+
|
|
1439
|
+
(usedSymbols.has('*') &&
|
|
1440
|
+
(this.bundle.env.outputFormat !== 'esmodule' ||
|
|
1441
|
+
!this.bundle.env.isLibrary ||
|
|
1442
|
+
asset !== this.bundle.getMainEntry() ||
|
|
1443
|
+
this.bundleGraph
|
|
1444
|
+
.getIncomingDependencies(asset)
|
|
1445
|
+
.some(
|
|
1446
|
+
(dep) =>
|
|
1447
|
+
!dep.isEntry &&
|
|
1448
|
+
this.bundle.hasDependency(dep) &&
|
|
1449
|
+
nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
|
|
1450
|
+
))) ||
|
|
1451
|
+
// If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
|
|
1452
|
+
// we fallback on the namespace object.
|
|
1453
|
+
|
|
1454
|
+
(asset.symbols.hasExportSymbol('*') &&
|
|
1455
|
+
[...usedSymbols].some((s) => !asset.symbols.hasExportSymbol(s))) ||
|
|
1456
|
+
// If the exports has this asset's namespace (e.g. ESM output from CJS input),
|
|
1457
|
+
// include the namespace object for the default export.
|
|
1458
|
+
this.exportedSymbols.has(`$${assetId}$exports`) ||
|
|
1459
|
+
// CommonJS library bundle entries always need a namespace.
|
|
1460
|
+
(this.bundle.env.isLibrary &&
|
|
1461
|
+
this.bundle.env.outputFormat === 'commonjs' &&
|
|
1462
|
+
asset === this.bundle.getMainEntry());
|
|
1463
|
+
}
|
|
1251
1464
|
|
|
1252
1465
|
// If the asset doesn't have static exports, should wrap, the namespace is used,
|
|
1253
1466
|
// or we need default interop, then we need to synthesize a namespace object for
|
|
@@ -1274,6 +1487,7 @@ ${code}
|
|
|
1274
1487
|
// Insert the __esModule interop flag for this module if it has a `default` export
|
|
1275
1488
|
// and the namespace symbol is used.
|
|
1276
1489
|
// TODO: only if required by CJS?
|
|
1490
|
+
|
|
1277
1491
|
if (asset.symbols.hasExportSymbol('default') && usedSymbols.has('*')) {
|
|
1278
1492
|
prepend += `\n$parcel$defineInteropFlag($${assetId}$exports);\n`;
|
|
1279
1493
|
prependLineCount += 2;
|
|
@@ -1337,6 +1551,7 @@ ${code}
|
|
|
1337
1551
|
let resolvedSymbol = this.getSymbolResolution(
|
|
1338
1552
|
asset,
|
|
1339
1553
|
resolved,
|
|
1554
|
+
|
|
1340
1555
|
symbol,
|
|
1341
1556
|
undefined,
|
|
1342
1557
|
replacements,
|
|
@@ -1388,28 +1603,39 @@ ${code}
|
|
|
1388
1603
|
// for the symbol so that when the value changes the object property also changes. This is
|
|
1389
1604
|
// required to simulate ESM live bindings. It's easier to do it this way rather than inserting
|
|
1390
1605
|
// additional assignments after each mutation of the original binding.
|
|
1391
|
-
|
|
1392
|
-
.
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1606
|
+
for (let exp of usedExports) {
|
|
1607
|
+
let resolved = this.getSymbolResolution(
|
|
1608
|
+
asset,
|
|
1609
|
+
asset,
|
|
1610
|
+
exp,
|
|
1611
|
+
undefined,
|
|
1612
|
+
replacements,
|
|
1613
|
+
);
|
|
1614
|
+
const meta = asset.symbols.get(exp)?.meta;
|
|
1615
|
+
if (
|
|
1616
|
+
getFeatureFlag('exportsRebindingOptimisation') &&
|
|
1617
|
+
(meta?.isStaticBindingSafe ||
|
|
1618
|
+
this.manualStaticBindingExports?.some((regex) =>
|
|
1619
|
+
regex.test(asset.filePath),
|
|
1620
|
+
))
|
|
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,9 +1674,11 @@ ${code}
|
|
|
1448
1674
|
}
|
|
1449
1675
|
|
|
1450
1676
|
for (let helper of this.usedHelpers) {
|
|
1451
|
-
let currentHelper = helpers[helper];
|
|
1677
|
+
let currentHelper = (helpers as Record<string, any>)[helper];
|
|
1452
1678
|
if (typeof currentHelper === 'function') {
|
|
1453
|
-
currentHelper = helpers[helper](
|
|
1679
|
+
currentHelper = (helpers as Record<string, any>)[helper](
|
|
1680
|
+
this.bundle.env,
|
|
1681
|
+
);
|
|
1454
1682
|
}
|
|
1455
1683
|
res += currentHelper;
|
|
1456
1684
|
if (enableSourceMaps) {
|
|
@@ -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) {
|