@atlaspack/packager-js 2.14.5-canary.21 → 2.14.5-canary.210
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
|
@@ -60,6 +60,13 @@ function _featureFlags() {
|
|
|
60
60
|
};
|
|
61
61
|
return data;
|
|
62
62
|
}
|
|
63
|
+
function _outdent() {
|
|
64
|
+
const data = require("outdent");
|
|
65
|
+
_outdent = function () {
|
|
66
|
+
return data;
|
|
67
|
+
};
|
|
68
|
+
return data;
|
|
69
|
+
}
|
|
63
70
|
var _ESMOutputFormat = require("./ESMOutputFormat");
|
|
64
71
|
var _CJSOutputFormat = require("./CJSOutputFormat");
|
|
65
72
|
var _GlobalOutputFormat = require("./GlobalOutputFormat");
|
|
@@ -70,7 +77,6 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
70
77
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
71
78
|
// General regex used to replace imports with the resolved code, references with resolutions,
|
|
72
79
|
// and count the number of newlines in the file for source maps.
|
|
73
|
-
//
|
|
74
80
|
// For conditional bundling the only difference in this regex is adding `importCond` where we have `importAsync` etc..
|
|
75
81
|
const REPLACEMENT_RE_CONDITIONAL = /\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;
|
|
76
82
|
const REPLACEMENT_RE = /\n|import\s+"([0-9a-f]{16,20}:.+?)";|(?:\$[0-9a-f]{16,20}\$exports)|(?:\$[0-9a-f]{16,20}\$(?:import|importAsync|require)\$[0-9a-f]+(?:\$[0-9a-f]+)?)/g;
|
|
@@ -80,6 +86,7 @@ const GLOBALS_BY_CONTEXT = {
|
|
|
80
86
|
'web-worker': new Set([...BUILTINS, ...Object.keys(_globals().default.worker)]),
|
|
81
87
|
'service-worker': new Set([...BUILTINS, ...Object.keys(_globals().default.serviceworker)]),
|
|
82
88
|
worklet: new Set([...BUILTINS]),
|
|
89
|
+
tesseract: new Set([...BUILTINS, ...Object.keys(_globals().default.worker)]),
|
|
83
90
|
node: new Set([...BUILTINS, ...Object.keys(_globals().default.node)]),
|
|
84
91
|
'electron-main': new Set([...BUILTINS, ...Object.keys(_globals().default.node)]),
|
|
85
92
|
'electron-renderer': new Set([...BUILTINS, ...Object.keys(_globals().default.node), ...Object.keys(_globals().default.browser)])
|
|
@@ -90,32 +97,34 @@ const OUTPUT_FORMATS = {
|
|
|
90
97
|
global: _GlobalOutputFormat.GlobalOutputFormat
|
|
91
98
|
};
|
|
92
99
|
class ScopeHoistingPackager {
|
|
100
|
+
assetOutputs = new Map();
|
|
93
101
|
exportedSymbols = new Map();
|
|
94
102
|
externals = new Map();
|
|
95
103
|
topLevelNames = new Map();
|
|
96
104
|
seenAssets = new Set();
|
|
97
105
|
wrappedAssets = new Set();
|
|
106
|
+
constantAssets = new Set();
|
|
98
107
|
hoistedRequires = new Map();
|
|
108
|
+
seenHoistedRequires = new Set();
|
|
99
109
|
needsPrelude = false;
|
|
100
110
|
usedHelpers = new Set();
|
|
101
111
|
externalAssets = new Set();
|
|
102
|
-
|
|
103
|
-
constructor(options, bundleGraph, bundle, parcelRequireName, useAsyncBundleRuntime,
|
|
112
|
+
useBothScopeHoistingImprovements = (0, _featureFlags().getFeatureFlag)('applyScopeHoistingImprovementV2') || (0, _featureFlags().getFeatureFlag)('applyScopeHoistingImprovement');
|
|
113
|
+
constructor(options, bundleGraph, bundle, parcelRequireName, useAsyncBundleRuntime, logger) {
|
|
104
114
|
this.options = options;
|
|
105
115
|
this.bundleGraph = bundleGraph;
|
|
106
116
|
this.bundle = bundle;
|
|
107
117
|
this.parcelRequireName = parcelRequireName;
|
|
108
118
|
this.useAsyncBundleRuntime = useAsyncBundleRuntime;
|
|
109
|
-
this.forceSkipWrapAssets = forceSkipWrapAssets ?? [];
|
|
110
119
|
this.logger = logger;
|
|
111
120
|
let OutputFormat = OUTPUT_FORMATS[this.bundle.env.outputFormat];
|
|
112
121
|
this.outputFormat = new OutputFormat(this);
|
|
113
|
-
this.isAsyncBundle = this.bundleGraph.hasParentBundleOfType(this.bundle, 'js') && !this.bundle.env.isIsolated() && this.bundle.bundleBehavior !== 'isolated';
|
|
122
|
+
this.isAsyncBundle = this.bundleGraph.hasParentBundleOfType(this.bundle, 'js') && !this.bundle.env.isIsolated() && this.bundle.bundleBehavior !== 'isolated' && this.bundle.bundleBehavior !== 'inlineIsolated';
|
|
114
123
|
this.globalNames = GLOBALS_BY_CONTEXT[bundle.env.context];
|
|
115
124
|
}
|
|
116
125
|
async package() {
|
|
117
126
|
var _sourceMap;
|
|
118
|
-
|
|
127
|
+
await this.loadAssets();
|
|
119
128
|
this.buildExportedSymbols();
|
|
120
129
|
|
|
121
130
|
// If building a library, the target is actually another bundler rather
|
|
@@ -134,8 +143,10 @@ class ScopeHoistingPackager {
|
|
|
134
143
|
let lineCount = 0;
|
|
135
144
|
let sourceMap = null;
|
|
136
145
|
let processAsset = asset => {
|
|
146
|
+
this.seenHoistedRequires.clear();
|
|
137
147
|
let [content, map, lines] = this.visitAsset(asset);
|
|
138
148
|
if (sourceMap && map) {
|
|
149
|
+
// @ts-expect-error TS2551 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
139
150
|
sourceMap.addSourceMap(map, lineCount);
|
|
140
151
|
} else if (this.bundle.env.sourceMap) {
|
|
141
152
|
sourceMap = map;
|
|
@@ -143,11 +154,19 @@ class ScopeHoistingPackager {
|
|
|
143
154
|
res += content + '\n';
|
|
144
155
|
lineCount += lines + 1;
|
|
145
156
|
};
|
|
157
|
+
if ((0, _featureFlags().getFeatureFlag)('inlineConstOptimisationFix') || this.useBothScopeHoistingImprovements) {
|
|
158
|
+
// Write out all constant modules used by this bundle
|
|
159
|
+
for (let asset of this.constantAssets) {
|
|
160
|
+
if (!this.seenAssets.has(asset)) {
|
|
161
|
+
processAsset(asset);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
146
165
|
|
|
147
166
|
// Hoist wrapped asset to the top of the bundle to ensure that they are registered
|
|
148
167
|
// before they are used.
|
|
149
|
-
for (let asset of wrappedAssets) {
|
|
150
|
-
if (!this.seenAssets.has(asset
|
|
168
|
+
for (let asset of this.wrappedAssets) {
|
|
169
|
+
if (!this.seenAssets.has(asset)) {
|
|
151
170
|
processAsset(asset);
|
|
152
171
|
}
|
|
153
172
|
}
|
|
@@ -155,7 +174,7 @@ class ScopeHoistingPackager {
|
|
|
155
174
|
// Add each asset that is directly connected to the bundle. Dependencies will be handled
|
|
156
175
|
// by replacing `import` statements in the code.
|
|
157
176
|
this.bundle.traverseAssets((asset, _, actions) => {
|
|
158
|
-
if (this.seenAssets.has(asset
|
|
177
|
+
if (this.seenAssets.has(asset)) {
|
|
159
178
|
actions.skipChildren();
|
|
160
179
|
return;
|
|
161
180
|
}
|
|
@@ -165,23 +184,35 @@ class ScopeHoistingPackager {
|
|
|
165
184
|
let [prelude, preludeLines] = this.buildBundlePrelude();
|
|
166
185
|
res = prelude + res;
|
|
167
186
|
lineCount += preludeLines;
|
|
187
|
+
// @ts-expect-error TS2339 - offsetLines method exists but missing from @parcel/source-map type definitions
|
|
168
188
|
(_sourceMap = sourceMap) === null || _sourceMap === void 0 || _sourceMap.offsetLines(1, preludeLines);
|
|
169
189
|
let entries = this.bundle.getEntryAssets();
|
|
170
190
|
let mainEntry = this.bundle.getMainEntry();
|
|
171
191
|
if (this.isAsyncBundle) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
192
|
+
if (this.useBothScopeHoistingImprovements || (0, _featureFlags().getFeatureFlag)('supportWebpackChunkName')) {
|
|
193
|
+
// Generally speaking, async bundles should not be executed on load, as
|
|
194
|
+
// they're just collections of assets that other assets require.
|
|
195
|
+
// However, there are some special cases where a runtime asset needs to be
|
|
196
|
+
// injected, but no other asset will require it (mostly the bundle
|
|
197
|
+
// manifest).
|
|
198
|
+
// In this case, those assets need to be required on load.
|
|
199
|
+
entries = entries.filter(a => {
|
|
200
|
+
var _a$meta;
|
|
201
|
+
return (_a$meta = a.meta) === null || _a$meta === void 0 ? void 0 : _a$meta.runtimeAssetRequiringExecutionOnLoad;
|
|
202
|
+
});
|
|
203
|
+
} else {
|
|
204
|
+
entries = entries.filter(a => {
|
|
205
|
+
var _mainEntry;
|
|
206
|
+
return a.id !== ((_mainEntry = mainEntry) === null || _mainEntry === void 0 ? void 0 : _mainEntry.id);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
178
209
|
mainEntry = null;
|
|
179
210
|
}
|
|
180
211
|
let needsBundleQueue = this.shouldBundleQueue(this.bundle);
|
|
181
212
|
|
|
182
213
|
// If any of the entry assets are wrapped, call parcelRequire so they are executed.
|
|
183
214
|
for (let entry of entries) {
|
|
184
|
-
if (this.wrappedAssets.has(entry
|
|
215
|
+
if (this.wrappedAssets.has(entry) && !this.isScriptEntry(entry)) {
|
|
185
216
|
var _entry$symbols$get;
|
|
186
217
|
let parcelRequire = `parcelRequire(${JSON.stringify(this.bundleGraph.getAssetPublicId(entry))});\n`;
|
|
187
218
|
let entryExports = (_entry$symbols$get = entry.symbols.get('*')) === null || _entry$symbols$get === void 0 ? void 0 : _entry$symbols$get.local;
|
|
@@ -211,13 +242,14 @@ class ScopeHoistingPackager {
|
|
|
211
242
|
let {
|
|
212
243
|
code,
|
|
213
244
|
map: mapBuffer
|
|
214
|
-
} = (0, _nullthrows().default)(this.assetOutputs.get(mainEntry
|
|
245
|
+
} = (0, _nullthrows().default)(this.assetOutputs.get(mainEntry));
|
|
215
246
|
let map;
|
|
216
247
|
if (mapBuffer) {
|
|
217
248
|
map = new (_sourceMap2().default)(this.options.projectRoot, mapBuffer);
|
|
218
249
|
}
|
|
219
250
|
res += (0, _utils2.replaceScriptDependencies)(this.bundleGraph, this.bundle, code, map, this.parcelRequireName);
|
|
220
251
|
if (sourceMap && map) {
|
|
252
|
+
// @ts-expect-error TS2339 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
221
253
|
sourceMap.addSourceMap(map, lineCount);
|
|
222
254
|
}
|
|
223
255
|
}
|
|
@@ -231,18 +263,18 @@ class ScopeHoistingPackager {
|
|
|
231
263
|
let hasHtmlReference = referencingBundles.some(b => b.type === 'html');
|
|
232
264
|
let hasConditionalReference = false;
|
|
233
265
|
let isConditionalBundle = false;
|
|
234
|
-
if ((0, _featureFlags().getFeatureFlag)('conditionalBundlingApi')
|
|
266
|
+
if ((0, _featureFlags().getFeatureFlag)('conditionalBundlingApi')) {
|
|
235
267
|
// If the bundle has a conditional bundle reference (has an importCond)
|
|
236
268
|
hasConditionalReference = this.bundleGraph.getReferencedConditionalBundles(bundle).length > 0;
|
|
237
269
|
// If the bundle is a conditional bundle
|
|
238
270
|
isConditionalBundle = this.hasConditionalDependency();
|
|
239
271
|
}
|
|
240
|
-
return this.useAsyncBundleRuntime && bundle.type === 'js' && bundle.bundleBehavior !== 'inline' && bundle.env.outputFormat === 'esmodule' && !bundle.env.isIsolated() && bundle.bundleBehavior !== 'isolated' && (hasHtmlReference || hasConditionalReference || isConditionalBundle);
|
|
272
|
+
return this.useAsyncBundleRuntime && bundle.type === 'js' && bundle.bundleBehavior !== 'inline' && bundle.bundleBehavior !== 'inlineIsolated' && bundle.env.outputFormat === 'esmodule' && !bundle.env.isIsolated() && bundle.bundleBehavior !== 'isolated' && (hasHtmlReference || hasConditionalReference || isConditionalBundle);
|
|
241
273
|
}
|
|
242
274
|
runWhenReady(bundle, codeToRun) {
|
|
243
275
|
let deps = this.bundleGraph.getReferencedBundles(bundle).filter(b => this.shouldBundleQueue(b)).map(b => b.publicId);
|
|
244
276
|
const conditions = [];
|
|
245
|
-
if ((0, _featureFlags().getFeatureFlag)('conditionalBundlingApi')
|
|
277
|
+
if ((0, _featureFlags().getFeatureFlag)('conditionalBundlingApi')) {
|
|
246
278
|
const conditionSet = this.bundleGraph.getConditionalBundleMapping().get(bundle.id);
|
|
247
279
|
for (const [key, {
|
|
248
280
|
ifTrueBundles,
|
|
@@ -264,11 +296,10 @@ class ScopeHoistingPackager {
|
|
|
264
296
|
let queue = new (_utils().PromiseQueue)({
|
|
265
297
|
maxConcurrent: 32
|
|
266
298
|
});
|
|
267
|
-
let wrapped = [];
|
|
268
299
|
this.bundle.traverseAssets(asset => {
|
|
269
300
|
queue.add(async () => {
|
|
270
301
|
let [code, map] = await Promise.all([asset.getCode(), this.bundle.env.sourceMap ? asset.getMapBuffer() : null]);
|
|
271
|
-
return [asset
|
|
302
|
+
return [asset, {
|
|
272
303
|
code,
|
|
273
304
|
map
|
|
274
305
|
}];
|
|
@@ -276,40 +307,86 @@ class ScopeHoistingPackager {
|
|
|
276
307
|
if (asset.meta.shouldWrap || this.bundle.env.sourceType === 'script' || this.bundleGraph.isAssetReferenced(this.bundle, asset) || this.bundleGraph.getIncomingDependencies(asset).some(dep => dep.meta.shouldWrap && dep.specifierType !== 'url')) {
|
|
277
308
|
// Don't wrap constant "entry" modules _except_ if they are referenced by any lazy dependency
|
|
278
309
|
if (!asset.meta.isConstantModule || this.bundleGraph.getIncomingDependencies(asset).some(dep => dep.priority === 'lazy')) {
|
|
279
|
-
this.wrappedAssets.add(asset
|
|
280
|
-
|
|
310
|
+
this.wrappedAssets.add(asset);
|
|
311
|
+
} else if (((0, _featureFlags().getFeatureFlag)('inlineConstOptimisationFix') || this.useBothScopeHoistingImprovements) && asset.meta.isConstantModule) {
|
|
312
|
+
this.constantAssets.add(asset);
|
|
281
313
|
}
|
|
282
314
|
}
|
|
283
315
|
});
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// In particular this can force an async bundle to be scope hoisted where it previously would not be
|
|
297
|
-
// due to the entry asset being wrapped.
|
|
298
|
-
if (this.forceSkipWrapAssets.length > 0 && this.forceSkipWrapAssets.some(p => p === _path().default.relative(this.options.projectRoot, asset.filePath))) {
|
|
299
|
-
this.logger.verbose({
|
|
300
|
-
message: `Force skipping wrapping of ${_path().default.relative(this.options.projectRoot, asset.filePath)}`
|
|
301
|
-
});
|
|
302
|
-
actions.skipChildren();
|
|
303
|
-
return;
|
|
316
|
+
if (this.useBothScopeHoistingImprovements) {
|
|
317
|
+
// Tracks which assets have been assigned to a wrap group
|
|
318
|
+
let assignedAssets = new Set();
|
|
319
|
+
|
|
320
|
+
// In V2 scope hoisting, we iterate from the main entry, rather than
|
|
321
|
+
// wrapping the entry assets
|
|
322
|
+
if (!(0, _featureFlags().getFeatureFlag)('applyScopeHoistingImprovementV2')) {
|
|
323
|
+
// Make all entry assets wrapped, to avoid any top level hoisting
|
|
324
|
+
for (let entryAsset of this.bundle.getEntryAssets()) {
|
|
325
|
+
if (!this.wrappedAssets.has(entryAsset)) {
|
|
326
|
+
this.wrappedAssets.add(entryAsset);
|
|
327
|
+
}
|
|
304
328
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// We need to make a new copy here so that we can add to the list and
|
|
332
|
+
// iterate the newly added items, without mutating the wrappedAssets set
|
|
333
|
+
let moduleGroupParents = [...this.wrappedAssets.values()];
|
|
334
|
+
if ((0, _featureFlags().getFeatureFlag)('applyScopeHoistingImprovementV2')) {
|
|
335
|
+
// The main entry needs to be check to find assets that would have gone in
|
|
336
|
+
// the top level scope
|
|
337
|
+
let mainEntry = this.bundle.getMainEntry();
|
|
338
|
+
if (mainEntry && !this.wrappedAssets.has(mainEntry)) {
|
|
339
|
+
moduleGroupParents.unshift(mainEntry);
|
|
308
340
|
}
|
|
309
|
-
}
|
|
341
|
+
}
|
|
342
|
+
for (let moduleGroupParentAsset of moduleGroupParents) {
|
|
343
|
+
this.bundle.traverseAssets((asset, _, actions) => {
|
|
344
|
+
if (asset === moduleGroupParentAsset) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
if (this.wrappedAssets.has(asset)) {
|
|
348
|
+
actions.skipChildren();
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
if (!asset.meta.isConstantModule && (assignedAssets.has(asset) || this.isReExported(asset))) {
|
|
352
|
+
this.wrappedAssets.add(asset);
|
|
353
|
+
|
|
354
|
+
// This also needs to be added to the traversal so that we iterate
|
|
355
|
+
// it during this check.
|
|
356
|
+
moduleGroupParents.push(asset);
|
|
357
|
+
actions.skipChildren();
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
assignedAssets.add(asset);
|
|
361
|
+
}, moduleGroupParentAsset);
|
|
362
|
+
}
|
|
363
|
+
} else {
|
|
364
|
+
for (let wrappedAssetRoot of this.wrappedAssets) {
|
|
365
|
+
this.bundle.traverseAssets((asset, _, actions) => {
|
|
366
|
+
if (asset === wrappedAssetRoot) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (this.wrappedAssets.has(asset)) {
|
|
370
|
+
actions.skipChildren();
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (!asset.meta.isConstantModule) {
|
|
374
|
+
this.wrappedAssets.add(asset);
|
|
375
|
+
}
|
|
376
|
+
}, wrappedAssetRoot);
|
|
377
|
+
}
|
|
310
378
|
}
|
|
311
379
|
this.assetOutputs = new Map(await queue.run());
|
|
312
|
-
|
|
380
|
+
}
|
|
381
|
+
isReExported(asset) {
|
|
382
|
+
let parentSymbols = this.bundleGraph.getIncomingDependencies(asset).map(dep => this.bundleGraph.getAssetWithDependency(dep)).flatMap(parent => {
|
|
383
|
+
if (parent == null) {
|
|
384
|
+
return [];
|
|
385
|
+
}
|
|
386
|
+
return this.bundleGraph.getExportedSymbols(parent, this.bundle);
|
|
387
|
+
});
|
|
388
|
+
let assetSymbols = this.bundleGraph.getExportedSymbols(asset, this.bundle);
|
|
389
|
+
return assetSymbols.some(assetSymbol => parentSymbols.some(parentSymbol => parentSymbol.symbol === assetSymbol.symbol));
|
|
313
390
|
}
|
|
314
391
|
buildExportedSymbols() {
|
|
315
392
|
if (!this.bundle.env.isLibrary || this.bundle.env.outputFormat !== 'esmodule') {
|
|
@@ -318,7 +395,7 @@ class ScopeHoistingPackager {
|
|
|
318
395
|
|
|
319
396
|
// TODO: handle ESM exports of wrapped entry assets...
|
|
320
397
|
let entry = this.bundle.getMainEntry();
|
|
321
|
-
if (entry && !this.wrappedAssets.has(entry
|
|
398
|
+
if (entry && !this.wrappedAssets.has(entry)) {
|
|
322
399
|
let hasNamespace = entry.symbols.hasExportSymbol('*');
|
|
323
400
|
for (let {
|
|
324
401
|
asset,
|
|
@@ -387,16 +464,19 @@ class ScopeHoistingPackager {
|
|
|
387
464
|
return `${obj}[${JSON.stringify(property)}]`;
|
|
388
465
|
}
|
|
389
466
|
visitAsset(asset) {
|
|
390
|
-
(0, _assert().default)(!this.seenAssets.has(asset
|
|
391
|
-
this.seenAssets.add(asset
|
|
467
|
+
(0, _assert().default)(!this.seenAssets.has(asset), 'Already visited asset');
|
|
468
|
+
this.seenAssets.add(asset);
|
|
392
469
|
let {
|
|
393
470
|
code,
|
|
394
471
|
map
|
|
395
|
-
} = (0, _nullthrows().default)(this.assetOutputs.get(asset
|
|
472
|
+
} = (0, _nullthrows().default)(this.assetOutputs.get(asset));
|
|
396
473
|
return this.buildAsset(asset, code, map);
|
|
397
474
|
}
|
|
475
|
+
getAssetFilePath(asset) {
|
|
476
|
+
return _path().default.relative(this.options.projectRoot, asset.filePath);
|
|
477
|
+
}
|
|
398
478
|
buildAsset(asset, code, map) {
|
|
399
|
-
let shouldWrap = this.wrappedAssets.has(asset
|
|
479
|
+
let shouldWrap = this.wrappedAssets.has(asset);
|
|
400
480
|
let deps = this.bundleGraph.getDependencies(asset);
|
|
401
481
|
let sourceMap = this.bundle.env.sourceMap && map ? new (_sourceMap2().default)(this.options.projectRoot, map) : null;
|
|
402
482
|
|
|
@@ -416,13 +496,21 @@ class ScopeHoistingPackager {
|
|
|
416
496
|
}
|
|
417
497
|
continue;
|
|
418
498
|
}
|
|
419
|
-
if (this.bundle.hasAsset(resolved) && !this.seenAssets.has(resolved
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
499
|
+
if (this.bundle.hasAsset(resolved) && !this.seenAssets.has(resolved)) {
|
|
500
|
+
if (this.useBothScopeHoistingImprovements && this.wrappedAssets.has(resolved)) {
|
|
501
|
+
// When the dep is wrapped then we just need to drop a side effect
|
|
502
|
+
// require instead of inlining
|
|
503
|
+
depCode += `parcelRequire("${this.bundleGraph.getAssetPublicId(resolved)}");\n`;
|
|
504
|
+
lineCount += 1;
|
|
505
|
+
} else {
|
|
506
|
+
let [code, map, lines] = this.visitAsset(resolved);
|
|
507
|
+
depCode += code + '\n';
|
|
508
|
+
if (sourceMap && map) {
|
|
509
|
+
// @ts-expect-error TS2551 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
510
|
+
sourceMap.addSourceMap(map, lineCount);
|
|
511
|
+
}
|
|
512
|
+
lineCount += lines + 1;
|
|
424
513
|
}
|
|
425
|
-
lineCount += lines + 1;
|
|
426
514
|
}
|
|
427
515
|
}
|
|
428
516
|
return [depCode, sourceMap, lineCount];
|
|
@@ -482,20 +570,51 @@ class ScopeHoistingPackager {
|
|
|
482
570
|
// after the dependency is declared. This handles the case where the resulting asset
|
|
483
571
|
// is wrapped, but the dependency in this asset is not marked as wrapped. This means
|
|
484
572
|
// that it was imported/required at the top-level, so its side effects should run immediately.
|
|
485
|
-
let
|
|
573
|
+
let res = '';
|
|
574
|
+
let lines = 0;
|
|
486
575
|
let map;
|
|
487
|
-
if (
|
|
576
|
+
if (!(0, _featureFlags().getFeatureFlag)('applyScopeHoistingImprovementV2')) {
|
|
577
|
+
[res, lines] = this.getHoistedParcelRequires(asset, dep, resolved);
|
|
578
|
+
}
|
|
579
|
+
if (this.bundle.hasAsset(resolved) && !this.seenAssets.has(resolved)) {
|
|
488
580
|
// If this asset is wrapped, we need to hoist the code for the dependency
|
|
489
581
|
// outside our parcelRequire.register wrapper. This is safe because all
|
|
490
582
|
// assets referenced by this asset will also be wrapped. Otherwise, inline the
|
|
491
583
|
// asset content where the import statement was.
|
|
492
|
-
if (
|
|
493
|
-
|
|
584
|
+
if (this.useBothScopeHoistingImprovements) {
|
|
585
|
+
if (!resolved.meta.isConstantModule && !this.wrappedAssets.has(resolved)) {
|
|
586
|
+
let [depCode, depMap, depLines] = this.visitAsset(resolved);
|
|
587
|
+
if (_utils().debugTools['asset-file-names-in-output']) {
|
|
588
|
+
let resolvedPath = this.getAssetFilePath(resolved);
|
|
589
|
+
res = (0, _outdent().outdent)`
|
|
590
|
+
/* Scope hoisted asset: ${resolvedPath} */
|
|
591
|
+
${depCode}
|
|
592
|
+
/* End: ${resolvedPath} */
|
|
593
|
+
${res}
|
|
594
|
+
`;
|
|
595
|
+
lines += 3 + depLines;
|
|
596
|
+
} else {
|
|
597
|
+
res = depCode + '\n' + res;
|
|
598
|
+
lines += 1 + depLines;
|
|
599
|
+
}
|
|
600
|
+
map = depMap;
|
|
601
|
+
}
|
|
494
602
|
} else {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
603
|
+
if (shouldWrap) {
|
|
604
|
+
depContent.push(this.visitAsset(resolved));
|
|
605
|
+
} else {
|
|
606
|
+
let [depCode, depMap, depLines] = this.visitAsset(resolved);
|
|
607
|
+
res = depCode + '\n' + res;
|
|
608
|
+
lines += 1 + depLines;
|
|
609
|
+
map = depMap;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if ((0, _featureFlags().getFeatureFlag)('applyScopeHoistingImprovementV2')) {
|
|
614
|
+
let [requiresCode, requiresLines] = this.getHoistedParcelRequires(asset, dep, resolved);
|
|
615
|
+
if (requiresCode) {
|
|
616
|
+
res = requiresCode + '\n' + res;
|
|
617
|
+
lines += requiresLines + 1;
|
|
499
618
|
}
|
|
500
619
|
}
|
|
501
620
|
|
|
@@ -506,6 +625,7 @@ class ScopeHoistingPackager {
|
|
|
506
625
|
sourceMap.offsetLines(lineCount + 1, lines);
|
|
507
626
|
}
|
|
508
627
|
if (map) {
|
|
628
|
+
// @ts-expect-error TS2551 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
509
629
|
sourceMap.addSourceMap(map, lineCount);
|
|
510
630
|
}
|
|
511
631
|
}
|
|
@@ -542,10 +662,15 @@ ${code}
|
|
|
542
662
|
});
|
|
543
663
|
`;
|
|
544
664
|
lineCount += 2;
|
|
665
|
+
if (_utils().debugTools['asset-file-names-in-output']) {
|
|
666
|
+
code = `/* ${this.getAssetFilePath(asset)} */\n` + code;
|
|
667
|
+
lineCount += 1;
|
|
668
|
+
}
|
|
545
669
|
for (let [depCode, map, lines] of depContent) {
|
|
546
670
|
if (!depCode) continue;
|
|
547
671
|
code += depCode + '\n';
|
|
548
672
|
if (sourceMap && map) {
|
|
673
|
+
// @ts-expect-error TS2551 - addSourceMap method exists but missing from @parcel/source-map type definitions
|
|
549
674
|
sourceMap.addSourceMap(map, lineCount);
|
|
550
675
|
}
|
|
551
676
|
lineCount += lines + 1;
|
|
@@ -614,7 +739,7 @@ ${code}
|
|
|
614
739
|
|
|
615
740
|
// If this asset is wrapped, we need to replace the exports namespace with `module.exports`,
|
|
616
741
|
// which will be provided to us by the wrapper.
|
|
617
|
-
if (this.wrappedAssets.has(asset
|
|
742
|
+
if (this.wrappedAssets.has(asset) || this.bundle.env.outputFormat === 'commonjs' && asset === this.bundle.getMainEntry()) {
|
|
618
743
|
var _asset$symbols$get;
|
|
619
744
|
let exportsName = ((_asset$symbols$get = asset.symbols.get('*')) === null || _asset$symbols$get === void 0 ? void 0 : _asset$symbols$get.local) || `$${assetId}$exports`;
|
|
620
745
|
replacements.set(exportsName, 'module.exports');
|
|
@@ -648,6 +773,7 @@ ${code}
|
|
|
648
773
|
local
|
|
649
774
|
}] of dep.symbols) {
|
|
650
775
|
// If already imported, just add the already renamed variable to the mapping.
|
|
776
|
+
|
|
651
777
|
let renamed = external.get(imported);
|
|
652
778
|
if (renamed && local !== '*' && replacements) {
|
|
653
779
|
replacements.set(local, renamed);
|
|
@@ -711,7 +837,7 @@ ${code}
|
|
|
711
837
|
continue;
|
|
712
838
|
}
|
|
713
839
|
}
|
|
714
|
-
renamed = this.bundleGraph.getSymbolResolution(entry, imported, this.bundle).symbol;
|
|
840
|
+
renamed = this.bundleGraph.getSymbolResolution(entry, imported, this.bundle).symbol || undefined;
|
|
715
841
|
}
|
|
716
842
|
}
|
|
717
843
|
|
|
@@ -752,7 +878,7 @@ ${code}
|
|
|
752
878
|
}
|
|
753
879
|
return false;
|
|
754
880
|
}
|
|
755
|
-
return !this.bundle.hasAsset(resolved) && !this.externalAssets.has(resolved) || this.wrappedAssets.has(resolved
|
|
881
|
+
return !this.bundle.hasAsset(resolved) && !this.externalAssets.has(resolved) || this.wrappedAssets.has(resolved) && resolved !== parentAsset;
|
|
756
882
|
}
|
|
757
883
|
getSymbolResolution(parentAsset, resolved, imported, dep, replacements) {
|
|
758
884
|
let {
|
|
@@ -779,12 +905,12 @@ ${code}
|
|
|
779
905
|
// Only do this if the asset is part of a different bundle (so it was definitely
|
|
780
906
|
// parcelRequire.register'ed there), or if it is indeed registered in this bundle.
|
|
781
907
|
!this.bundle.hasAsset(resolvedAsset) || !this.shouldSkipAsset(resolvedAsset))) {
|
|
782
|
-
let hoisted = this.hoistedRequires.get(dep
|
|
908
|
+
let hoisted = this.hoistedRequires.get(dep);
|
|
783
909
|
if (!hoisted) {
|
|
784
910
|
hoisted = new Map();
|
|
785
|
-
this.hoistedRequires.set(dep
|
|
911
|
+
this.hoistedRequires.set(dep, hoisted);
|
|
786
912
|
}
|
|
787
|
-
hoisted.set(resolvedAsset
|
|
913
|
+
hoisted.set(resolvedAsset, `var $${publicId} = parcelRequire(${JSON.stringify(publicId)});`);
|
|
788
914
|
}
|
|
789
915
|
if (isWrapped) {
|
|
790
916
|
this.needsPrelude = true;
|
|
@@ -813,7 +939,7 @@ ${code}
|
|
|
813
939
|
}
|
|
814
940
|
if (imported === '*' || exportSymbol === '*' || isDefaultInterop) {
|
|
815
941
|
// Resolve to the namespace object if requested or this is a CJS default interop reqiure.
|
|
816
|
-
if (parentAsset === resolvedAsset && this.wrappedAssets.has(resolvedAsset
|
|
942
|
+
if (parentAsset === resolvedAsset && this.wrappedAssets.has(resolvedAsset)) {
|
|
817
943
|
// Directly use module.exports for wrapped assets importing themselves.
|
|
818
944
|
return 'module.exports';
|
|
819
945
|
} else {
|
|
@@ -841,7 +967,7 @@ ${code}
|
|
|
841
967
|
if (resolved.type !== 'js') {
|
|
842
968
|
return ['', 0];
|
|
843
969
|
}
|
|
844
|
-
let hoisted = this.hoistedRequires.get(dep
|
|
970
|
+
let hoisted = this.hoistedRequires.get(dep);
|
|
845
971
|
let res = '';
|
|
846
972
|
let lineCount = 0;
|
|
847
973
|
let isWrapped = this.isWrapped(resolved, parentAsset);
|
|
@@ -850,14 +976,23 @@ ${code}
|
|
|
850
976
|
// we need to run side effects when this asset runs. If the resolved asset is not
|
|
851
977
|
// the first one in the hoisted requires, we need to insert a parcelRequire here
|
|
852
978
|
// so it runs first.
|
|
853
|
-
if (isWrapped && !dep.meta.shouldWrap && (!hoisted || hoisted.keys().next().value !== resolved
|
|
979
|
+
if (isWrapped && !dep.meta.shouldWrap && (!hoisted || hoisted.keys().next().value !== resolved) && !this.bundleGraph.isDependencySkipped(dep) && !this.shouldSkipAsset(resolved)) {
|
|
854
980
|
this.needsPrelude = true;
|
|
855
981
|
res += `parcelRequire(${JSON.stringify(this.bundleGraph.getAssetPublicId(resolved))});`;
|
|
856
982
|
}
|
|
857
983
|
if (hoisted) {
|
|
858
984
|
this.needsPrelude = true;
|
|
859
|
-
|
|
860
|
-
|
|
985
|
+
if ((0, _featureFlags().getFeatureFlag)('applyScopeHoistingImprovementV2')) {
|
|
986
|
+
let hoistedValues = [...hoisted.values()].filter(val => !this.seenHoistedRequires.has(val));
|
|
987
|
+
for (let val of hoistedValues) {
|
|
988
|
+
this.seenHoistedRequires.add(val);
|
|
989
|
+
}
|
|
990
|
+
res += '\n' + hoistedValues.join('\n');
|
|
991
|
+
lineCount += hoisted.size;
|
|
992
|
+
} else {
|
|
993
|
+
res += '\n' + [...hoisted.values()].join('\n');
|
|
994
|
+
lineCount += hoisted.size;
|
|
995
|
+
}
|
|
861
996
|
}
|
|
862
997
|
return [res, lineCount];
|
|
863
998
|
}
|
|
@@ -865,7 +1000,7 @@ ${code}
|
|
|
865
1000
|
let prepend = '';
|
|
866
1001
|
let prependLineCount = 0;
|
|
867
1002
|
let append = '';
|
|
868
|
-
let shouldWrap = this.wrappedAssets.has(asset
|
|
1003
|
+
let shouldWrap = this.wrappedAssets.has(asset);
|
|
869
1004
|
let usedSymbols = (0, _nullthrows().default)(this.bundleGraph.getUsedSymbols(asset));
|
|
870
1005
|
let assetId = asset.meta.id;
|
|
871
1006
|
(0, _assert().default)(typeof assetId === 'string');
|
|
@@ -874,20 +1009,28 @@ ${code}
|
|
|
874
1009
|
// If there's no __esModule flag, and default is a used symbol, we need
|
|
875
1010
|
// to insert an interop helper.
|
|
876
1011
|
let defaultInterop = asset.symbols.hasExportSymbol('*') && usedSymbols.has('default') && !asset.symbols.hasExportSymbol('__esModule');
|
|
877
|
-
let usedNamespace
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1012
|
+
let usedNamespace;
|
|
1013
|
+
if ((0, _featureFlags().getFeatureFlag)('inlineConstOptimisationFix') && asset.meta.isConstantModule) {
|
|
1014
|
+
// Only set usedNamespace if there is an incoming dependency in the current bundle that uses '*'
|
|
1015
|
+
usedNamespace = this.bundleGraph.getIncomingDependencies(asset).some(dep => this.bundle.hasDependency(dep) && (0, _nullthrows().default)(this.bundleGraph.getUsedSymbols(dep)).has('*'));
|
|
1016
|
+
} else {
|
|
1017
|
+
usedNamespace =
|
|
1018
|
+
// If the asset has * in its used symbols, we might need the exports namespace.
|
|
1019
|
+
// The one case where this isn't true is in ESM library entries, where the only
|
|
1020
|
+
// dependency on * is the entry dependency. In this case, we will use ESM exports
|
|
1021
|
+
// instead of the namespace object.
|
|
1022
|
+
|
|
1023
|
+
usedSymbols.has('*') && (this.bundle.env.outputFormat !== 'esmodule' || !this.bundle.env.isLibrary || asset !== this.bundle.getMainEntry() || this.bundleGraph.getIncomingDependencies(asset).some(dep => !dep.isEntry && this.bundle.hasDependency(dep) && (0, _nullthrows().default)(this.bundleGraph.getUsedSymbols(dep)).has('*'))) ||
|
|
1024
|
+
// If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
|
|
1025
|
+
// we fallback on the namespace object.
|
|
1026
|
+
|
|
1027
|
+
asset.symbols.hasExportSymbol('*') && [...usedSymbols].some(s => !asset.symbols.hasExportSymbol(s)) ||
|
|
1028
|
+
// If the exports has this asset's namespace (e.g. ESM output from CJS input),
|
|
1029
|
+
// include the namespace object for the default export.
|
|
1030
|
+
this.exportedSymbols.has(`$${assetId}$exports`) ||
|
|
1031
|
+
// CommonJS library bundle entries always need a namespace.
|
|
1032
|
+
this.bundle.env.isLibrary && this.bundle.env.outputFormat === 'commonjs' && asset === this.bundle.getMainEntry();
|
|
1033
|
+
}
|
|
891
1034
|
|
|
892
1035
|
// If the asset doesn't have static exports, should wrap, the namespace is used,
|
|
893
1036
|
// or we need default interop, then we need to synthesize a namespace object for
|
|
@@ -905,6 +1048,7 @@ ${code}
|
|
|
905
1048
|
// Insert the __esModule interop flag for this module if it has a `default` export
|
|
906
1049
|
// and the namespace symbol is used.
|
|
907
1050
|
// TODO: only if required by CJS?
|
|
1051
|
+
|
|
908
1052
|
if (asset.symbols.hasExportSymbol('default') && usedSymbols.has('*')) {
|
|
909
1053
|
prepend += `\n$parcel$defineInteropFlag($${assetId}$exports);\n`;
|
|
910
1054
|
prependLineCount += 2;
|
|
@@ -988,16 +1132,22 @@ ${code}
|
|
|
988
1132
|
// for the symbol so that when the value changes the object property also changes. This is
|
|
989
1133
|
// required to simulate ESM live bindings. It's easier to do it this way rather than inserting
|
|
990
1134
|
// additional assignments after each mutation of the original binding.
|
|
991
|
-
|
|
1135
|
+
for (let exp of usedExports) {
|
|
992
1136
|
var _asset$symbols$get2;
|
|
993
1137
|
let resolved = this.getSymbolResolution(asset, asset, exp, undefined, replacements);
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1138
|
+
const meta = (_asset$symbols$get2 = asset.symbols.get(exp)) === null || _asset$symbols$get2 === void 0 ? void 0 : _asset$symbols$get2.meta;
|
|
1139
|
+
if ((0, _featureFlags().getFeatureFlag)('exportsRebindingOptimisation') && meta !== null && meta !== void 0 && meta.isStaticBindingSafe) {
|
|
1140
|
+
append += `$${assetId}$exports[${JSON.stringify(exp)}] = ${resolved};\n`;
|
|
1141
|
+
} else {
|
|
1142
|
+
var _asset$symbols$get3;
|
|
1143
|
+
let get = this.buildFunctionExpression([], resolved);
|
|
1144
|
+
let isEsmExport = !!((_asset$symbols$get3 = asset.symbols.get(exp)) !== null && _asset$symbols$get3 !== void 0 && (_asset$symbols$get3 = _asset$symbols$get3.meta) !== null && _asset$symbols$get3 !== void 0 && _asset$symbols$get3.isEsm);
|
|
1145
|
+
let set = !isEsmExport && asset.meta.hasCJSExports ? ', ' + this.buildFunctionExpression(['v'], `${resolved} = v`) : '';
|
|
1146
|
+
prepend += `$parcel$export($${assetId}$exports, ${JSON.stringify(exp)}, ${get}${set});\n`;
|
|
1147
|
+
this.usedHelpers.add('$parcel$export');
|
|
1148
|
+
prependLineCount += 1 + usedExports.length;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1001
1151
|
}
|
|
1002
1152
|
}
|
|
1003
1153
|
return [prepend, prependLineCount, append];
|
|
@@ -1041,11 +1191,11 @@ ${code}
|
|
|
1041
1191
|
// Add the prelude if this is potentially the first JS bundle to load in a
|
|
1042
1192
|
// particular context (e.g. entry scripts in HTML, workers, etc.).
|
|
1043
1193
|
let parentBundles = this.bundleGraph.getParentBundles(this.bundle);
|
|
1044
|
-
let mightBeFirstJS = parentBundles.length === 0 || parentBundles.some(b => b.type !== 'js') || this.bundleGraph.getBundleGroupsContainingBundle(this.bundle).some(g => this.bundleGraph.isEntryBundleGroup(g)) || this.bundle.env.isIsolated() || this.bundle.bundleBehavior === 'isolated' ||
|
|
1194
|
+
let mightBeFirstJS = parentBundles.length === 0 || parentBundles.some(b => b.type !== 'js') || this.bundleGraph.getBundleGroupsContainingBundle(this.bundle).some(g => this.bundleGraph.isEntryBundleGroup(g)) || this.bundle.env.isIsolated() || this.bundle.bundleBehavior === 'isolated' || this.bundle.bundleBehavior === 'inlineIsolated' ||
|
|
1045
1195
|
// Conditional deps may be loaded before entrypoints on the server
|
|
1046
1196
|
this.hasConditionalDependency();
|
|
1047
1197
|
if (mightBeFirstJS) {
|
|
1048
|
-
let preludeCode = (0, _helpers.
|
|
1198
|
+
let preludeCode = ((0, _featureFlags().getFeatureFlag)('useNewPrelude') ? _helpers.preludeNew : _helpers.preludeOld)(this.parcelRequireName);
|
|
1049
1199
|
res += preludeCode;
|
|
1050
1200
|
if (enableSourceMaps) {
|
|
1051
1201
|
lines += (0, _utils().countLines)(preludeCode) - 1;
|
|
@@ -1068,7 +1218,7 @@ ${code}
|
|
|
1068
1218
|
}
|
|
1069
1219
|
|
|
1070
1220
|
// Add importScripts for sibling bundles in workers.
|
|
1071
|
-
if (this.bundle.env.isWorker() || this.bundle.env.isWorklet()) {
|
|
1221
|
+
if (this.bundle.env.isWorker() || this.bundle.env.isTesseract() || this.bundle.env.isWorklet()) {
|
|
1072
1222
|
let importScripts = '';
|
|
1073
1223
|
let bundles = this.bundleGraph.getReferencedBundles(this.bundle);
|
|
1074
1224
|
for (let b of bundles) {
|