@atlaspack/packager-js 2.23.1 → 2.23.2-dev-ts-project-refs-d30e9754f.0
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/LICENSE +201 -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 +1359 -0
- package/dist/helpers.js +170 -0
- package/dist/index.js +101 -0
- package/dist/utils.js +60 -0
- package/package.json +10 -10
- package/tsconfig.json +25 -2
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,1359 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.ScopeHoistingPackager = void 0;
|
|
40
|
+
const utils_1 = require("@atlaspack/utils");
|
|
41
|
+
const source_map_1 = __importDefault(require("@parcel/source-map"));
|
|
42
|
+
const nullthrows_1 = __importDefault(require("nullthrows"));
|
|
43
|
+
const assert_1 = __importStar(require("assert"));
|
|
44
|
+
const diagnostic_1 = __importStar(require("@atlaspack/diagnostic"));
|
|
45
|
+
const globals_1 = __importDefault(require("globals"));
|
|
46
|
+
const path_1 = __importDefault(require("path"));
|
|
47
|
+
const feature_flags_1 = require("@atlaspack/feature-flags");
|
|
48
|
+
const outdent_1 = require("outdent");
|
|
49
|
+
const ESMOutputFormat_1 = require("./ESMOutputFormat");
|
|
50
|
+
const CJSOutputFormat_1 = require("./CJSOutputFormat");
|
|
51
|
+
const GlobalOutputFormat_1 = require("./GlobalOutputFormat");
|
|
52
|
+
const helpers_1 = require("./helpers");
|
|
53
|
+
const utils_2 = require("./utils");
|
|
54
|
+
// General regex used to replace imports with the resolved code, references with resolutions,
|
|
55
|
+
// and count the number of newlines in the file for source maps.
|
|
56
|
+
// For conditional bundling the only difference in this regex is adding `importCond` where we have `importAsync` etc..
|
|
57
|
+
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;
|
|
58
|
+
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;
|
|
59
|
+
const BUILTINS = Object.keys(globals_1.default.builtin);
|
|
60
|
+
const GLOBALS_BY_CONTEXT = {
|
|
61
|
+
browser: new Set([...BUILTINS, ...Object.keys(globals_1.default.browser)]),
|
|
62
|
+
'web-worker': new Set([...BUILTINS, ...Object.keys(globals_1.default.worker)]),
|
|
63
|
+
'service-worker': new Set([
|
|
64
|
+
...BUILTINS,
|
|
65
|
+
...Object.keys(globals_1.default.serviceworker),
|
|
66
|
+
]),
|
|
67
|
+
worklet: new Set([...BUILTINS]),
|
|
68
|
+
tesseract: new Set([...BUILTINS, ...Object.keys(globals_1.default.worker)]),
|
|
69
|
+
node: new Set([...BUILTINS, ...Object.keys(globals_1.default.node)]),
|
|
70
|
+
'electron-main': new Set([...BUILTINS, ...Object.keys(globals_1.default.node)]),
|
|
71
|
+
'electron-renderer': new Set([
|
|
72
|
+
...BUILTINS,
|
|
73
|
+
...Object.keys(globals_1.default.node),
|
|
74
|
+
...Object.keys(globals_1.default.browser),
|
|
75
|
+
]),
|
|
76
|
+
};
|
|
77
|
+
const OUTPUT_FORMATS = {
|
|
78
|
+
esmodule: ESMOutputFormat_1.ESMOutputFormat,
|
|
79
|
+
commonjs: CJSOutputFormat_1.CJSOutputFormat,
|
|
80
|
+
global: GlobalOutputFormat_1.GlobalOutputFormat,
|
|
81
|
+
};
|
|
82
|
+
class ScopeHoistingPackager {
|
|
83
|
+
constructor(options, bundleGraph, bundle, parcelRequireName, useAsyncBundleRuntime, logger) {
|
|
84
|
+
this.exportedSymbols = new Map();
|
|
85
|
+
this.externals = new Map();
|
|
86
|
+
this.topLevelNames = new Map();
|
|
87
|
+
this.seenAssets = new Set();
|
|
88
|
+
this.wrappedAssets = new Set();
|
|
89
|
+
this.hoistedRequires = new Map();
|
|
90
|
+
this.seenHoistedRequires = new Set();
|
|
91
|
+
this.needsPrelude = false;
|
|
92
|
+
this.usedHelpers = new Set();
|
|
93
|
+
this.externalAssets = new Set();
|
|
94
|
+
this.useBothScopeHoistingImprovements = (0, feature_flags_1.getFeatureFlag)('applyScopeHoistingImprovementV2') ||
|
|
95
|
+
(0, feature_flags_1.getFeatureFlag)('applyScopeHoistingImprovement');
|
|
96
|
+
this.options = options;
|
|
97
|
+
this.bundleGraph = bundleGraph;
|
|
98
|
+
this.bundle = bundle;
|
|
99
|
+
this.parcelRequireName = parcelRequireName;
|
|
100
|
+
this.useAsyncBundleRuntime = useAsyncBundleRuntime;
|
|
101
|
+
this.logger = logger;
|
|
102
|
+
let OutputFormat = OUTPUT_FORMATS[this.bundle.env.outputFormat];
|
|
103
|
+
this.outputFormat = new OutputFormat(this);
|
|
104
|
+
this.isAsyncBundle =
|
|
105
|
+
this.bundleGraph.hasParentBundleOfType(this.bundle, 'js') &&
|
|
106
|
+
!this.bundle.env.isIsolated() &&
|
|
107
|
+
this.bundle.bundleBehavior !== 'isolated' &&
|
|
108
|
+
this.bundle.bundleBehavior !== 'inlineIsolated';
|
|
109
|
+
this.globalNames = GLOBALS_BY_CONTEXT[bundle.env.context];
|
|
110
|
+
}
|
|
111
|
+
async package() {
|
|
112
|
+
let { wrapped: wrappedAssets, constant: constantAssets } = await this.loadAssets();
|
|
113
|
+
this.buildExportedSymbols();
|
|
114
|
+
// If building a library, the target is actually another bundler rather
|
|
115
|
+
// than the final output that could be loaded in a browser. So, loader
|
|
116
|
+
// runtimes are excluded, and instead we add imports into the entry bundle
|
|
117
|
+
// of each bundle group pointing at the sibling bundles. These can be
|
|
118
|
+
// picked up by another bundler later at which point runtimes will be added.
|
|
119
|
+
if (this.bundle.env.isLibrary ||
|
|
120
|
+
this.bundle.env.outputFormat === 'commonjs') {
|
|
121
|
+
for (let b of this.bundleGraph.getReferencedBundles(this.bundle, {
|
|
122
|
+
recursive: false,
|
|
123
|
+
})) {
|
|
124
|
+
this.externals.set((0, utils_1.relativeBundlePath)(this.bundle, b), new Map());
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
let res = '';
|
|
128
|
+
let lineCount = 0;
|
|
129
|
+
// @ts-expect-error TS7034
|
|
130
|
+
let sourceMap = null;
|
|
131
|
+
let processAsset = (asset) => {
|
|
132
|
+
this.seenHoistedRequires.clear();
|
|
133
|
+
let [content, map, lines] = this.visitAsset(asset);
|
|
134
|
+
// @ts-expect-error TS7005
|
|
135
|
+
if (sourceMap && map) {
|
|
136
|
+
sourceMap.addSourceMap(map, lineCount);
|
|
137
|
+
}
|
|
138
|
+
else if (this.bundle.env.sourceMap) {
|
|
139
|
+
sourceMap = map;
|
|
140
|
+
}
|
|
141
|
+
res += content + '\n';
|
|
142
|
+
lineCount += lines + 1;
|
|
143
|
+
};
|
|
144
|
+
if ((0, feature_flags_1.getFeatureFlag)('inlineConstOptimisationFix') ||
|
|
145
|
+
this.useBothScopeHoistingImprovements) {
|
|
146
|
+
// Write out all constant modules used by this bundle
|
|
147
|
+
for (let asset of constantAssets) {
|
|
148
|
+
if (!this.seenAssets.has(asset.id)) {
|
|
149
|
+
processAsset(asset);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Hoist wrapped asset to the top of the bundle to ensure that they are registered
|
|
154
|
+
// before they are used.
|
|
155
|
+
for (let asset of wrappedAssets) {
|
|
156
|
+
if (!this.seenAssets.has(asset.id)) {
|
|
157
|
+
processAsset(asset);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Add each asset that is directly connected to the bundle. Dependencies will be handled
|
|
161
|
+
// by replacing `import` statements in the code.
|
|
162
|
+
this.bundle.traverseAssets((asset, _, actions) => {
|
|
163
|
+
if (this.seenAssets.has(asset.id)) {
|
|
164
|
+
actions.skipChildren();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
processAsset(asset);
|
|
168
|
+
actions.skipChildren();
|
|
169
|
+
});
|
|
170
|
+
let [prelude, preludeLines] = this.buildBundlePrelude();
|
|
171
|
+
res = prelude + res;
|
|
172
|
+
lineCount += preludeLines;
|
|
173
|
+
// @ts-expect-error TS2339
|
|
174
|
+
sourceMap?.offsetLines(1, preludeLines);
|
|
175
|
+
let entries = this.bundle.getEntryAssets();
|
|
176
|
+
let mainEntry = this.bundle.getMainEntry();
|
|
177
|
+
if (this.isAsyncBundle) {
|
|
178
|
+
if (this.useBothScopeHoistingImprovements ||
|
|
179
|
+
(0, feature_flags_1.getFeatureFlag)('supportWebpackChunkName')) {
|
|
180
|
+
// Generally speaking, async bundles should not be executed on load, as
|
|
181
|
+
// they're just collections of assets that other assets require.
|
|
182
|
+
// However, there are some special cases where a runtime asset needs to be
|
|
183
|
+
// injected, but no other asset will require it (mostly the bundle
|
|
184
|
+
// manifest).
|
|
185
|
+
// In this case, those assets need to be required on load.
|
|
186
|
+
entries = entries.filter((a) => a.meta?.runtimeAssetRequiringExecutionOnLoad);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
entries = entries.filter((a) => a.id !== mainEntry?.id);
|
|
190
|
+
}
|
|
191
|
+
mainEntry = null;
|
|
192
|
+
}
|
|
193
|
+
let needsBundleQueue = this.shouldBundleQueue(this.bundle);
|
|
194
|
+
// If any of the entry assets are wrapped, call parcelRequire so they are executed.
|
|
195
|
+
for (let entry of entries) {
|
|
196
|
+
if (this.wrappedAssets.has(entry.id) && !this.isScriptEntry(entry)) {
|
|
197
|
+
let parcelRequire = `parcelRequire(${JSON.stringify(this.bundleGraph.getAssetPublicId(entry))});\n`;
|
|
198
|
+
let entryExports = entry.symbols.get('*')?.local;
|
|
199
|
+
if (entryExports &&
|
|
200
|
+
entry === mainEntry &&
|
|
201
|
+
this.exportedSymbols.has(entryExports)) {
|
|
202
|
+
(0, assert_1.default)(!needsBundleQueue, 'Entry exports are not yet compaitble with async bundles');
|
|
203
|
+
res += `\nvar ${entryExports} = ${parcelRequire}`;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
if (needsBundleQueue) {
|
|
207
|
+
parcelRequire = this.runWhenReady(this.bundle, parcelRequire);
|
|
208
|
+
}
|
|
209
|
+
res += `\n${parcelRequire}`;
|
|
210
|
+
}
|
|
211
|
+
lineCount += 2;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
let [postlude, postludeLines] = this.outputFormat.buildBundlePostlude();
|
|
215
|
+
res += postlude;
|
|
216
|
+
lineCount += postludeLines;
|
|
217
|
+
// The entry asset of a script bundle gets hoisted outside the bundle wrapper so that
|
|
218
|
+
// its top-level variables become globals like a real browser script. We need to replace
|
|
219
|
+
// all dependency references for runtimes with a parcelRequire call.
|
|
220
|
+
if (this.bundle.env.outputFormat === 'global' &&
|
|
221
|
+
this.bundle.env.sourceType === 'script') {
|
|
222
|
+
res += '\n';
|
|
223
|
+
lineCount++;
|
|
224
|
+
let mainEntry = (0, nullthrows_1.default)(this.bundle.getMainEntry());
|
|
225
|
+
let { code, map: mapBuffer } = (0, nullthrows_1.default)(this.assetOutputs.get(mainEntry.id));
|
|
226
|
+
let map;
|
|
227
|
+
if (mapBuffer) {
|
|
228
|
+
map = new source_map_1.default(this.options.projectRoot, mapBuffer);
|
|
229
|
+
}
|
|
230
|
+
res += (0, utils_2.replaceScriptDependencies)(this.bundleGraph, this.bundle, code, map, this.parcelRequireName);
|
|
231
|
+
if (sourceMap && map) {
|
|
232
|
+
// @ts-expect-error TS2339
|
|
233
|
+
sourceMap.addSourceMap(map, lineCount);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
contents: res,
|
|
238
|
+
map: sourceMap,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
shouldBundleQueue(bundle) {
|
|
242
|
+
let referencingBundles = this.bundleGraph.getReferencingBundles(bundle);
|
|
243
|
+
let hasHtmlReference = referencingBundles.some((b) => b.type === 'html');
|
|
244
|
+
let hasConditionalReference = false;
|
|
245
|
+
let isConditionalBundle = false;
|
|
246
|
+
if ((0, feature_flags_1.getFeatureFlag)('conditionalBundlingApi')) {
|
|
247
|
+
// If the bundle has a conditional bundle reference (has an importCond)
|
|
248
|
+
hasConditionalReference =
|
|
249
|
+
this.bundleGraph.getReferencedConditionalBundles(bundle).length > 0;
|
|
250
|
+
// If the bundle is a conditional bundle
|
|
251
|
+
isConditionalBundle = this.hasConditionalDependency();
|
|
252
|
+
}
|
|
253
|
+
return (this.useAsyncBundleRuntime &&
|
|
254
|
+
bundle.type === 'js' &&
|
|
255
|
+
bundle.bundleBehavior !== 'inline' &&
|
|
256
|
+
bundle.bundleBehavior !== 'inlineIsolated' &&
|
|
257
|
+
bundle.env.outputFormat === 'esmodule' &&
|
|
258
|
+
!bundle.env.isIsolated() &&
|
|
259
|
+
bundle.bundleBehavior !== 'isolated' &&
|
|
260
|
+
(hasHtmlReference || hasConditionalReference || isConditionalBundle));
|
|
261
|
+
}
|
|
262
|
+
runWhenReady(bundle, codeToRun) {
|
|
263
|
+
let deps = this.bundleGraph
|
|
264
|
+
.getReferencedBundles(bundle)
|
|
265
|
+
.filter((b) => this.shouldBundleQueue(b))
|
|
266
|
+
.map((b) => b.publicId);
|
|
267
|
+
const conditions = [];
|
|
268
|
+
if ((0, feature_flags_1.getFeatureFlag)('conditionalBundlingApi')) {
|
|
269
|
+
const conditionSet = this.bundleGraph
|
|
270
|
+
.getConditionalBundleMapping()
|
|
271
|
+
.get(bundle.id);
|
|
272
|
+
for (const [key, { ifTrueBundles, ifFalseBundles },] of conditionSet?.entries() ?? []) {
|
|
273
|
+
const ifTrueBundleIds = ifTrueBundles
|
|
274
|
+
.map((b) => `"${b.publicId}"`)
|
|
275
|
+
.join(',');
|
|
276
|
+
const ifFalseBundleIds = ifFalseBundles
|
|
277
|
+
.map((b) => `"${b.publicId}"`)
|
|
278
|
+
.join(',');
|
|
279
|
+
conditions.push(`(globalThis.__MCOND && globalThis.__MCOND('${key}') ? [${ifTrueBundleIds}] : [${ifFalseBundleIds}])`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (deps.length === 0 && conditions.length === 0) {
|
|
283
|
+
// If no deps we can safely execute immediately
|
|
284
|
+
return codeToRun;
|
|
285
|
+
}
|
|
286
|
+
let params = [
|
|
287
|
+
JSON.stringify(this.bundle.publicId),
|
|
288
|
+
(0, helpers_1.fnExpr)(this.bundle.env, [], [codeToRun]),
|
|
289
|
+
`${JSON.stringify(deps)}${conditions.length > 0
|
|
290
|
+
? `.concat([${conditions
|
|
291
|
+
.map((conditions) => `...${conditions}`)
|
|
292
|
+
.join(',')}])`
|
|
293
|
+
: ''}`,
|
|
294
|
+
];
|
|
295
|
+
return `$parcel$global.rwr(${params.join(', ')});`;
|
|
296
|
+
}
|
|
297
|
+
async loadAssets() {
|
|
298
|
+
let queue = new utils_1.PromiseQueue({ maxConcurrent: 32 });
|
|
299
|
+
let wrapped = [];
|
|
300
|
+
let constant = [];
|
|
301
|
+
this.bundle.traverseAssets((asset) => {
|
|
302
|
+
queue.add(async () => {
|
|
303
|
+
let [code, map] = await Promise.all([
|
|
304
|
+
asset.getCode(),
|
|
305
|
+
this.bundle.env.sourceMap ? asset.getMapBuffer() : null,
|
|
306
|
+
]);
|
|
307
|
+
return [asset.id, { code, map }];
|
|
308
|
+
});
|
|
309
|
+
if (asset.meta.shouldWrap ||
|
|
310
|
+
this.bundle.env.sourceType === 'script' ||
|
|
311
|
+
this.bundleGraph.isAssetReferenced(this.bundle, asset) ||
|
|
312
|
+
this.bundleGraph
|
|
313
|
+
.getIncomingDependencies(asset)
|
|
314
|
+
.some((dep) => dep.meta.shouldWrap && dep.specifierType !== 'url')) {
|
|
315
|
+
// Don't wrap constant "entry" modules _except_ if they are referenced by any lazy dependency
|
|
316
|
+
if (!asset.meta.isConstantModule ||
|
|
317
|
+
this.bundleGraph
|
|
318
|
+
.getIncomingDependencies(asset)
|
|
319
|
+
.some((dep) => dep.priority === 'lazy')) {
|
|
320
|
+
this.wrappedAssets.add(asset.id);
|
|
321
|
+
wrapped.push(asset);
|
|
322
|
+
}
|
|
323
|
+
else if (((0, feature_flags_1.getFeatureFlag)('inlineConstOptimisationFix') ||
|
|
324
|
+
this.useBothScopeHoistingImprovements) &&
|
|
325
|
+
asset.meta.isConstantModule) {
|
|
326
|
+
constant.push(asset);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
});
|
|
330
|
+
if (this.useBothScopeHoistingImprovements) {
|
|
331
|
+
// Tracks which assets have been assigned to a wrap group
|
|
332
|
+
let assignedAssets = new Set();
|
|
333
|
+
// In V2 scope hoisting, we iterate from the main entry, rather than
|
|
334
|
+
// wrapping the entry assets
|
|
335
|
+
if (!(0, feature_flags_1.getFeatureFlag)('applyScopeHoistingImprovementV2')) {
|
|
336
|
+
// Make all entry assets wrapped, to avoid any top level hoisting
|
|
337
|
+
for (let entryAsset of this.bundle.getEntryAssets()) {
|
|
338
|
+
if (!this.wrappedAssets.has(entryAsset.id)) {
|
|
339
|
+
this.wrappedAssets.add(entryAsset.id);
|
|
340
|
+
wrapped.push(entryAsset);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
let moduleGroupParents = [...wrapped];
|
|
345
|
+
if ((0, feature_flags_1.getFeatureFlag)('applyScopeHoistingImprovementV2')) {
|
|
346
|
+
// The main entry needs to be check to find assets that would have gone in
|
|
347
|
+
// the top level scope
|
|
348
|
+
let mainEntry = this.bundle.getMainEntry();
|
|
349
|
+
if (mainEntry && !this.wrappedAssets.has(mainEntry.id)) {
|
|
350
|
+
moduleGroupParents.unshift(mainEntry);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
for (let moduleGroupParentAsset of moduleGroupParents) {
|
|
354
|
+
this.bundle.traverseAssets((asset, _, actions) => {
|
|
355
|
+
if (asset === moduleGroupParentAsset) {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
if (this.wrappedAssets.has(asset.id)) {
|
|
359
|
+
actions.skipChildren();
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (!asset.meta.isConstantModule &&
|
|
363
|
+
(assignedAssets.has(asset) || this.isReExported(asset))) {
|
|
364
|
+
wrapped.push(asset);
|
|
365
|
+
this.wrappedAssets.add(asset.id);
|
|
366
|
+
// This also needs to be added to the traversal so that we iterate
|
|
367
|
+
// it during this check.
|
|
368
|
+
moduleGroupParents.push(asset);
|
|
369
|
+
actions.skipChildren();
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
assignedAssets.add(asset);
|
|
373
|
+
}, moduleGroupParentAsset);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
for (let wrappedAssetRoot of [...wrapped]) {
|
|
378
|
+
this.bundle.traverseAssets((asset, _, actions) => {
|
|
379
|
+
if (asset === wrappedAssetRoot) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (this.wrappedAssets.has(asset.id)) {
|
|
383
|
+
actions.skipChildren();
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
if (!asset.meta.isConstantModule) {
|
|
387
|
+
this.wrappedAssets.add(asset.id);
|
|
388
|
+
wrapped.push(asset);
|
|
389
|
+
}
|
|
390
|
+
}, wrappedAssetRoot);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
// @ts-expect-error TS2769
|
|
394
|
+
this.assetOutputs = new Map(await queue.run());
|
|
395
|
+
return { wrapped, constant };
|
|
396
|
+
}
|
|
397
|
+
isReExported(asset) {
|
|
398
|
+
let parentSymbols = this.bundleGraph
|
|
399
|
+
.getIncomingDependencies(asset)
|
|
400
|
+
.map((dep) => this.bundleGraph.getAssetWithDependency(dep))
|
|
401
|
+
.flatMap((parent) => {
|
|
402
|
+
if (parent == null) {
|
|
403
|
+
return [];
|
|
404
|
+
}
|
|
405
|
+
return this.bundleGraph.getExportedSymbols(parent, this.bundle);
|
|
406
|
+
});
|
|
407
|
+
let assetSymbols = this.bundleGraph.getExportedSymbols(asset, this.bundle);
|
|
408
|
+
return assetSymbols.some((assetSymbol) => parentSymbols.some((parentSymbol) => parentSymbol.symbol === assetSymbol.symbol));
|
|
409
|
+
}
|
|
410
|
+
buildExportedSymbols() {
|
|
411
|
+
if (!this.bundle.env.isLibrary ||
|
|
412
|
+
this.bundle.env.outputFormat !== 'esmodule') {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
// TODO: handle ESM exports of wrapped entry assets...
|
|
416
|
+
let entry = this.bundle.getMainEntry();
|
|
417
|
+
if (entry && !this.wrappedAssets.has(entry.id)) {
|
|
418
|
+
let hasNamespace = entry.symbols.hasExportSymbol('*');
|
|
419
|
+
for (let { asset, exportAs, symbol, exportSymbol, } of this.bundleGraph.getExportedSymbols(entry)) {
|
|
420
|
+
if (typeof symbol === 'string') {
|
|
421
|
+
// If the module has a namespace (e.g. commonjs), and this is not an entry, only export the namespace
|
|
422
|
+
// as default, without individual exports. This mirrors the importing logic in addExternal, avoiding
|
|
423
|
+
// extra unused exports and potential for non-identifier export names.
|
|
424
|
+
if (hasNamespace && this.isAsyncBundle && exportAs !== '*') {
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
427
|
+
let symbols = this.exportedSymbols.get(symbol === '*' ? (0, nullthrows_1.default)(entry.symbols.get('*')?.local) : symbol)?.exportAs;
|
|
428
|
+
if (!symbols) {
|
|
429
|
+
symbols = [];
|
|
430
|
+
this.exportedSymbols.set(symbol, {
|
|
431
|
+
asset,
|
|
432
|
+
exportSymbol,
|
|
433
|
+
local: symbol,
|
|
434
|
+
exportAs: symbols,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
if (exportAs === '*') {
|
|
438
|
+
exportAs = 'default';
|
|
439
|
+
}
|
|
440
|
+
symbols.push(exportAs);
|
|
441
|
+
}
|
|
442
|
+
else if (symbol === null) {
|
|
443
|
+
// TODO `meta.exportsIdentifier[exportSymbol]` should be exported
|
|
444
|
+
// let relativePath = relative(options.projectRoot, asset.filePath);
|
|
445
|
+
// throw getThrowableDiagnosticForNode(
|
|
446
|
+
// md`${relativePath} couldn't be statically analyzed when importing '${exportSymbol}'`,
|
|
447
|
+
// entry.filePath,
|
|
448
|
+
// loc,
|
|
449
|
+
// );
|
|
450
|
+
}
|
|
451
|
+
else if (symbol !== false) {
|
|
452
|
+
// let relativePath = relative(options.projectRoot, asset.filePath);
|
|
453
|
+
// throw getThrowableDiagnosticForNode(
|
|
454
|
+
// md`${relativePath} does not export '${exportSymbol}'`,
|
|
455
|
+
// entry.filePath,
|
|
456
|
+
// loc,
|
|
457
|
+
// );
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
getTopLevelName(name) {
|
|
463
|
+
name = (0, utils_2.makeValidIdentifier)(name);
|
|
464
|
+
if (this.globalNames.has(name)) {
|
|
465
|
+
name = '_' + name;
|
|
466
|
+
}
|
|
467
|
+
let count = this.topLevelNames.get(name);
|
|
468
|
+
if (count == null) {
|
|
469
|
+
this.topLevelNames.set(name, 1);
|
|
470
|
+
return name;
|
|
471
|
+
}
|
|
472
|
+
this.topLevelNames.set(name, count + 1);
|
|
473
|
+
return name + count;
|
|
474
|
+
}
|
|
475
|
+
getPropertyAccess(obj, property) {
|
|
476
|
+
if ((0, utils_2.isValidIdentifier)(property)) {
|
|
477
|
+
return `${obj}.${property}`;
|
|
478
|
+
}
|
|
479
|
+
return `${obj}[${JSON.stringify(property)}]`;
|
|
480
|
+
}
|
|
481
|
+
visitAsset(asset) {
|
|
482
|
+
(0, assert_1.default)(!this.seenAssets.has(asset.id), 'Already visited asset');
|
|
483
|
+
this.seenAssets.add(asset.id);
|
|
484
|
+
let { code, map } = (0, nullthrows_1.default)(this.assetOutputs.get(asset.id));
|
|
485
|
+
return this.buildAsset(asset, code, map);
|
|
486
|
+
}
|
|
487
|
+
getAssetFilePath(asset) {
|
|
488
|
+
return path_1.default.relative(this.options.projectRoot, asset.filePath);
|
|
489
|
+
}
|
|
490
|
+
buildAsset(asset, code, map) {
|
|
491
|
+
let shouldWrap = this.wrappedAssets.has(asset.id);
|
|
492
|
+
let deps = this.bundleGraph.getDependencies(asset);
|
|
493
|
+
let sourceMap = this.bundle.env.sourceMap && map
|
|
494
|
+
? new source_map_1.default(this.options.projectRoot, map)
|
|
495
|
+
: null;
|
|
496
|
+
// If this asset is skipped, just add dependencies and not the asset's content.
|
|
497
|
+
if (this.shouldSkipAsset(asset)) {
|
|
498
|
+
let depCode = '';
|
|
499
|
+
let lineCount = 0;
|
|
500
|
+
for (let dep of deps) {
|
|
501
|
+
let resolved = this.bundleGraph.getResolvedAsset(dep, this.bundle);
|
|
502
|
+
let skipped = this.bundleGraph.isDependencySkipped(dep);
|
|
503
|
+
if (skipped) {
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
506
|
+
if (!resolved) {
|
|
507
|
+
if (!dep.isOptional) {
|
|
508
|
+
this.addExternal(dep);
|
|
509
|
+
}
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
if (this.bundle.hasAsset(resolved) &&
|
|
513
|
+
!this.seenAssets.has(resolved.id)) {
|
|
514
|
+
let [code, map, lines] = this.visitAsset(resolved);
|
|
515
|
+
depCode += code + '\n';
|
|
516
|
+
if (sourceMap && map) {
|
|
517
|
+
// @ts-expect-error TS2551
|
|
518
|
+
sourceMap.addSourceMap(map, lineCount);
|
|
519
|
+
}
|
|
520
|
+
lineCount += lines + 1;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return [depCode, sourceMap, lineCount];
|
|
524
|
+
}
|
|
525
|
+
// TODO: maybe a meta prop?
|
|
526
|
+
if (code.includes('$parcel$global')) {
|
|
527
|
+
this.usedHelpers.add('$parcel$global');
|
|
528
|
+
}
|
|
529
|
+
if (this.bundle.env.isNode() && asset.meta.has_node_replacements) {
|
|
530
|
+
const relPath = (0, utils_1.normalizeSeparators)(path_1.default.relative(this.bundle.target.distDir, path_1.default.dirname(asset.filePath)));
|
|
531
|
+
code = code.replace('$parcel$dirnameReplace', relPath);
|
|
532
|
+
code = code.replace('$parcel$filenameReplace', relPath);
|
|
533
|
+
}
|
|
534
|
+
let [depMap, replacements] = this.buildReplacements(asset, deps);
|
|
535
|
+
let [prepend, prependLines, append] = this.buildAssetPrelude(asset, deps, replacements);
|
|
536
|
+
if (prependLines > 0) {
|
|
537
|
+
sourceMap?.offsetLines(1, prependLines);
|
|
538
|
+
code = prepend + code;
|
|
539
|
+
}
|
|
540
|
+
code += append;
|
|
541
|
+
let lineCount = 0;
|
|
542
|
+
// @ts-expect-error TS2552
|
|
543
|
+
let depContent = [];
|
|
544
|
+
if (depMap.size === 0 && replacements.size === 0) {
|
|
545
|
+
// If there are no dependencies or replacements, use a simple function to count the number of lines.
|
|
546
|
+
lineCount = (0, utils_1.countLines)(code) - 1;
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
// Otherwise, use a regular expression to perform replacements.
|
|
550
|
+
// We need to track how many newlines there are for source maps, replace
|
|
551
|
+
// all import statements with dependency code, and perform inline replacements
|
|
552
|
+
// of all imported symbols with their resolved export symbols. This is all done
|
|
553
|
+
// in a single regex so that we only do one pass over the whole code.
|
|
554
|
+
let offset = 0;
|
|
555
|
+
let columnStartIndex = 0;
|
|
556
|
+
code = code.replace((0, feature_flags_1.getFeatureFlag)('conditionalBundlingApi')
|
|
557
|
+
? REPLACEMENT_RE_CONDITIONAL
|
|
558
|
+
: REPLACEMENT_RE, (m, d, i) => {
|
|
559
|
+
if (m === '\n') {
|
|
560
|
+
columnStartIndex = i + offset + 1;
|
|
561
|
+
lineCount++;
|
|
562
|
+
return '\n';
|
|
563
|
+
}
|
|
564
|
+
// If we matched an import, replace with the source code for the dependency.
|
|
565
|
+
if (d != null) {
|
|
566
|
+
let deps = depMap.get(d);
|
|
567
|
+
if (!deps) {
|
|
568
|
+
return m;
|
|
569
|
+
}
|
|
570
|
+
let replacement = '';
|
|
571
|
+
// A single `${id}:${specifier}:esm` might have been resolved to multiple assets due to
|
|
572
|
+
// reexports.
|
|
573
|
+
for (let dep of deps) {
|
|
574
|
+
let resolved = this.bundleGraph.getResolvedAsset(dep, this.bundle);
|
|
575
|
+
let skipped = this.bundleGraph.isDependencySkipped(dep);
|
|
576
|
+
if (resolved && !skipped) {
|
|
577
|
+
// Hoist variable declarations for the referenced parcelRequire dependencies
|
|
578
|
+
// after the dependency is declared. This handles the case where the resulting asset
|
|
579
|
+
// is wrapped, but the dependency in this asset is not marked as wrapped. This means
|
|
580
|
+
// that it was imported/required at the top-level, so its side effects should run immediately.
|
|
581
|
+
let res = '';
|
|
582
|
+
let lines = 0;
|
|
583
|
+
let map;
|
|
584
|
+
if (!(0, feature_flags_1.getFeatureFlag)('applyScopeHoistingImprovementV2')) {
|
|
585
|
+
[res, lines] = this.getHoistedParcelRequires(asset, dep, resolved);
|
|
586
|
+
}
|
|
587
|
+
if (this.bundle.hasAsset(resolved) &&
|
|
588
|
+
!this.seenAssets.has(resolved.id)) {
|
|
589
|
+
// If this asset is wrapped, we need to hoist the code for the dependency
|
|
590
|
+
// outside our parcelRequire.register wrapper. This is safe because all
|
|
591
|
+
// assets referenced by this asset will also be wrapped. Otherwise, inline the
|
|
592
|
+
// asset content where the import statement was.
|
|
593
|
+
if (this.useBothScopeHoistingImprovements) {
|
|
594
|
+
if (!resolved.meta.isConstantModule &&
|
|
595
|
+
!this.wrappedAssets.has(resolved.id)) {
|
|
596
|
+
let [depCode, depMap, depLines] = this.visitAsset(resolved);
|
|
597
|
+
if (utils_1.debugTools['asset-file-names-in-output']) {
|
|
598
|
+
let resolvedPath = this.getAssetFilePath(resolved);
|
|
599
|
+
res = (0, outdent_1.outdent) `
|
|
600
|
+
/* Scope hoisted asset: ${resolvedPath} */
|
|
601
|
+
${depCode}
|
|
602
|
+
/* End: ${resolvedPath} */
|
|
603
|
+
${res}
|
|
604
|
+
`;
|
|
605
|
+
lines += 3 + depLines;
|
|
606
|
+
}
|
|
607
|
+
else {
|
|
608
|
+
res = depCode + '\n' + res;
|
|
609
|
+
lines += 1 + depLines;
|
|
610
|
+
}
|
|
611
|
+
map = depMap;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
if (shouldWrap) {
|
|
616
|
+
depContent.push(this.visitAsset(resolved));
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
619
|
+
let [depCode, depMap, depLines] = this.visitAsset(resolved);
|
|
620
|
+
res = depCode + '\n' + res;
|
|
621
|
+
lines += 1 + depLines;
|
|
622
|
+
map = depMap;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
if ((0, feature_flags_1.getFeatureFlag)('applyScopeHoistingImprovementV2')) {
|
|
627
|
+
let [requiresCode, requiresLines] = this.getHoistedParcelRequires(asset, dep, resolved);
|
|
628
|
+
if (requiresCode) {
|
|
629
|
+
res = requiresCode + '\n' + res;
|
|
630
|
+
lines += requiresLines + 1;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
// Push this asset's source mappings down by the number of lines in the dependency
|
|
634
|
+
// plus the number of hoisted parcelRequires. Then insert the source map for the dependency.
|
|
635
|
+
if (sourceMap) {
|
|
636
|
+
if (lines > 0) {
|
|
637
|
+
sourceMap.offsetLines(lineCount + 1, lines);
|
|
638
|
+
}
|
|
639
|
+
if (map) {
|
|
640
|
+
// @ts-expect-error TS2551
|
|
641
|
+
sourceMap.addSourceMap(map, lineCount);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
replacement += res;
|
|
645
|
+
lineCount += lines;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return replacement;
|
|
649
|
+
}
|
|
650
|
+
// If it wasn't a dependency, then it was an inline replacement (e.g. $id$import$foo -> $id$export$foo).
|
|
651
|
+
let replacement = replacements.get(m) ?? m;
|
|
652
|
+
if (sourceMap) {
|
|
653
|
+
// Offset the source map columns for this line if the replacement was a different length.
|
|
654
|
+
// This assumes that the match and replacement both do not contain any newlines.
|
|
655
|
+
let lengthDifference = replacement.length - m.length;
|
|
656
|
+
if (lengthDifference !== 0) {
|
|
657
|
+
sourceMap.offsetColumns(lineCount + 1, i + offset - columnStartIndex + m.length, lengthDifference);
|
|
658
|
+
offset += lengthDifference;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return replacement;
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
// If the asset is wrapped, we need to insert the dependency code outside the parcelRequire.register
|
|
665
|
+
// wrapper. Dependencies must be inserted AFTER the asset is registered so that circular dependencies work.
|
|
666
|
+
if (shouldWrap) {
|
|
667
|
+
// Offset by one line for the parcelRequire.register wrapper.
|
|
668
|
+
sourceMap?.offsetLines(1, 1);
|
|
669
|
+
lineCount++;
|
|
670
|
+
code = `parcelRegister(${JSON.stringify(this.bundleGraph.getAssetPublicId(asset))}, function(module, exports) {
|
|
671
|
+
${code}
|
|
672
|
+
});
|
|
673
|
+
`;
|
|
674
|
+
lineCount += 2;
|
|
675
|
+
if (utils_1.debugTools['asset-file-names-in-output']) {
|
|
676
|
+
code = `/* ${this.getAssetFilePath(asset)} */\n` + code;
|
|
677
|
+
lineCount += 1;
|
|
678
|
+
}
|
|
679
|
+
for (let [depCode, map, lines] of depContent) {
|
|
680
|
+
if (!depCode)
|
|
681
|
+
continue;
|
|
682
|
+
code += depCode + '\n';
|
|
683
|
+
if (sourceMap && map) {
|
|
684
|
+
// @ts-expect-error TS2551
|
|
685
|
+
sourceMap.addSourceMap(map, lineCount);
|
|
686
|
+
}
|
|
687
|
+
lineCount += lines + 1;
|
|
688
|
+
}
|
|
689
|
+
this.needsPrelude = true;
|
|
690
|
+
}
|
|
691
|
+
if (!shouldWrap &&
|
|
692
|
+
this.shouldBundleQueue(this.bundle) &&
|
|
693
|
+
this.bundle.getEntryAssets().some((entry) => entry.id === asset.id)) {
|
|
694
|
+
code = this.runWhenReady(this.bundle, code);
|
|
695
|
+
}
|
|
696
|
+
return [code, sourceMap, lineCount];
|
|
697
|
+
}
|
|
698
|
+
buildReplacements(asset, deps) {
|
|
699
|
+
let assetId = asset.meta.id;
|
|
700
|
+
(0, assert_1.default)(typeof assetId === 'string');
|
|
701
|
+
// Build two maps: one of import specifiers, and one of imported symbols to replace.
|
|
702
|
+
// These will be used to build a regex below.
|
|
703
|
+
let depMap = new utils_1.DefaultMap(() => []);
|
|
704
|
+
let replacements = new Map();
|
|
705
|
+
for (let dep of deps) {
|
|
706
|
+
let specifierType = dep.specifierType === 'esm' ? `:${dep.specifierType}` : '';
|
|
707
|
+
depMap
|
|
708
|
+
.get(`${assetId}:${(0, utils_2.getSpecifier)(dep)}${!dep.meta.placeholder ? specifierType : ''}`)
|
|
709
|
+
.push(dep);
|
|
710
|
+
let asyncResolution = this.bundleGraph.resolveAsyncDependency(dep, this.bundle);
|
|
711
|
+
let resolved = asyncResolution?.type === 'asset'
|
|
712
|
+
? // Prefer the underlying asset over a runtime to load it. It will
|
|
713
|
+
// be wrapped in Promise.resolve() later.
|
|
714
|
+
asyncResolution.value
|
|
715
|
+
: this.bundleGraph.getResolvedAsset(dep, this.bundle);
|
|
716
|
+
if (!resolved &&
|
|
717
|
+
!dep.isOptional &&
|
|
718
|
+
!this.bundleGraph.isDependencySkipped(dep)) {
|
|
719
|
+
this.addExternal(dep, replacements);
|
|
720
|
+
}
|
|
721
|
+
if (!resolved) {
|
|
722
|
+
continue;
|
|
723
|
+
}
|
|
724
|
+
// Handle imports from other bundles in libraries.
|
|
725
|
+
if (this.bundle.env.isLibrary && !this.bundle.hasAsset(resolved)) {
|
|
726
|
+
let referencedBundle = this.bundleGraph.getReferencedBundle(dep, this.bundle);
|
|
727
|
+
if (referencedBundle &&
|
|
728
|
+
referencedBundle.getMainEntry() === resolved &&
|
|
729
|
+
referencedBundle.type === 'js' &&
|
|
730
|
+
!this.bundleGraph.isAssetReferenced(referencedBundle, resolved)) {
|
|
731
|
+
this.addExternal(dep, replacements, referencedBundle);
|
|
732
|
+
this.externalAssets.add(resolved);
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
for (let [imported, { local }] of dep.symbols) {
|
|
737
|
+
if (local === '*') {
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
let symbol = this.getSymbolResolution(asset, resolved, imported, dep);
|
|
741
|
+
replacements.set(local,
|
|
742
|
+
// If this was an internalized async asset, wrap in a Promise.resolve.
|
|
743
|
+
asyncResolution?.type === 'asset'
|
|
744
|
+
? `Promise.resolve(${symbol})`
|
|
745
|
+
: symbol);
|
|
746
|
+
}
|
|
747
|
+
// Async dependencies need a namespace object even if all used symbols were statically analyzed.
|
|
748
|
+
// This is recorded in the promiseSymbol meta property set by the transformer rather than in
|
|
749
|
+
// symbols so that we don't mark all symbols as used.
|
|
750
|
+
if ((dep.priority === 'lazy' || dep.priority === 'conditional') &&
|
|
751
|
+
dep.meta.promiseSymbol) {
|
|
752
|
+
let promiseSymbol = dep.meta.promiseSymbol;
|
|
753
|
+
(0, assert_1.default)(typeof promiseSymbol === 'string');
|
|
754
|
+
let symbol = this.getSymbolResolution(asset, resolved, '*', dep);
|
|
755
|
+
replacements.set(promiseSymbol, asyncResolution?.type === 'asset'
|
|
756
|
+
? `Promise.resolve(${symbol})`
|
|
757
|
+
: symbol);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
// If this asset is wrapped, we need to replace the exports namespace with `module.exports`,
|
|
761
|
+
// which will be provided to us by the wrapper.
|
|
762
|
+
if (this.wrappedAssets.has(asset.id) ||
|
|
763
|
+
(this.bundle.env.outputFormat === 'commonjs' &&
|
|
764
|
+
asset === this.bundle.getMainEntry())) {
|
|
765
|
+
let exportsName = asset.symbols.get('*')?.local || `$${assetId}$exports`;
|
|
766
|
+
replacements.set(exportsName, 'module.exports');
|
|
767
|
+
}
|
|
768
|
+
return [depMap, replacements];
|
|
769
|
+
}
|
|
770
|
+
addExternal(dep, replacements, referencedBundle) {
|
|
771
|
+
if (this.bundle.env.outputFormat === 'global') {
|
|
772
|
+
throw new diagnostic_1.default({
|
|
773
|
+
diagnostic: {
|
|
774
|
+
message: 'External modules are not supported when building for browser',
|
|
775
|
+
codeFrames: [
|
|
776
|
+
{
|
|
777
|
+
filePath: (0, nullthrows_1.default)(dep.sourcePath),
|
|
778
|
+
codeHighlights: dep.loc
|
|
779
|
+
? [(0, diagnostic_1.convertSourceLocationToHighlight)(dep.loc)]
|
|
780
|
+
: [],
|
|
781
|
+
},
|
|
782
|
+
],
|
|
783
|
+
},
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
let specifier = dep.specifier;
|
|
787
|
+
if (referencedBundle) {
|
|
788
|
+
specifier = (0, utils_1.relativeBundlePath)(this.bundle, referencedBundle);
|
|
789
|
+
}
|
|
790
|
+
// Map of DependencySpecifier -> Map<ExportedSymbol, Identifier>>
|
|
791
|
+
let external = this.externals.get(specifier);
|
|
792
|
+
if (!external) {
|
|
793
|
+
external = new Map();
|
|
794
|
+
this.externals.set(specifier, external);
|
|
795
|
+
}
|
|
796
|
+
for (let [imported, { local }] of dep.symbols) {
|
|
797
|
+
// If already imported, just add the already renamed variable to the mapping.
|
|
798
|
+
let renamed = external.get(imported);
|
|
799
|
+
if (renamed && local !== '*' && replacements) {
|
|
800
|
+
replacements.set(local, renamed);
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
// For CJS output, always use a property lookup so that exports remain live.
|
|
804
|
+
// For ESM output, use named imports which are always live.
|
|
805
|
+
if (this.bundle.env.outputFormat === 'commonjs') {
|
|
806
|
+
renamed = external.get('*');
|
|
807
|
+
if (!renamed) {
|
|
808
|
+
if (referencedBundle) {
|
|
809
|
+
let entry = (0, nullthrows_1.default)(referencedBundle.getMainEntry());
|
|
810
|
+
renamed =
|
|
811
|
+
entry.symbols.get('*')?.local ??
|
|
812
|
+
`$${String(entry.meta.id)}$exports`;
|
|
813
|
+
}
|
|
814
|
+
else {
|
|
815
|
+
renamed = this.getTopLevelName(`$${this.bundle.publicId}$${specifier}`);
|
|
816
|
+
}
|
|
817
|
+
external.set('*', renamed);
|
|
818
|
+
}
|
|
819
|
+
if (local !== '*' && replacements) {
|
|
820
|
+
let replacement;
|
|
821
|
+
if (imported === '*') {
|
|
822
|
+
replacement = renamed;
|
|
823
|
+
}
|
|
824
|
+
else if (imported === 'default') {
|
|
825
|
+
let needsDefaultInterop = true;
|
|
826
|
+
if (referencedBundle) {
|
|
827
|
+
let entry = (0, nullthrows_1.default)(referencedBundle.getMainEntry());
|
|
828
|
+
needsDefaultInterop = this.needsDefaultInterop(entry);
|
|
829
|
+
}
|
|
830
|
+
if (needsDefaultInterop) {
|
|
831
|
+
replacement = `($parcel$interopDefault(${renamed}))`;
|
|
832
|
+
this.usedHelpers.add('$parcel$interopDefault');
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
replacement = `${renamed}.default`;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
else {
|
|
839
|
+
replacement = this.getPropertyAccess(renamed, imported);
|
|
840
|
+
}
|
|
841
|
+
replacements.set(local, replacement);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
else {
|
|
845
|
+
let property;
|
|
846
|
+
if (referencedBundle) {
|
|
847
|
+
let entry = (0, nullthrows_1.default)(referencedBundle.getMainEntry());
|
|
848
|
+
if (entry.symbols.hasExportSymbol('*')) {
|
|
849
|
+
// If importing * and the referenced module has a * export (e.g. CJS), use default instead.
|
|
850
|
+
// This mirrors the logic in buildExportedSymbols.
|
|
851
|
+
property = imported;
|
|
852
|
+
imported =
|
|
853
|
+
referencedBundle?.env.outputFormat === 'esmodule'
|
|
854
|
+
? 'default'
|
|
855
|
+
: '*';
|
|
856
|
+
}
|
|
857
|
+
else {
|
|
858
|
+
if (imported === '*') {
|
|
859
|
+
let exportedSymbols = this.bundleGraph.getExportedSymbols(entry);
|
|
860
|
+
if (local === '*') {
|
|
861
|
+
// Re-export all symbols.
|
|
862
|
+
for (let exported of exportedSymbols) {
|
|
863
|
+
if (exported.symbol) {
|
|
864
|
+
external.set(exported.exportSymbol, exported.symbol);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
continue;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
// @ts-expect-error TS2322
|
|
871
|
+
renamed = this.bundleGraph.getSymbolResolution(entry, imported, this.bundle).symbol;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
// Rename the specifier so that multiple local imports of the same imported specifier
|
|
875
|
+
// are deduplicated. We have to prefix the imported name with the bundle id so that
|
|
876
|
+
// local variables do not shadow it.
|
|
877
|
+
if (!renamed) {
|
|
878
|
+
if (this.exportedSymbols.has(local)) {
|
|
879
|
+
renamed = local;
|
|
880
|
+
}
|
|
881
|
+
else if (imported === 'default' || imported === '*') {
|
|
882
|
+
renamed = this.getTopLevelName(`$${this.bundle.publicId}$${specifier}`);
|
|
883
|
+
}
|
|
884
|
+
else {
|
|
885
|
+
renamed = this.getTopLevelName(`$${this.bundle.publicId}$${imported}`);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
external.set(imported, renamed);
|
|
889
|
+
if (local !== '*' && replacements) {
|
|
890
|
+
let replacement = renamed;
|
|
891
|
+
if (property === '*') {
|
|
892
|
+
replacement = renamed;
|
|
893
|
+
}
|
|
894
|
+
else if (property === 'default') {
|
|
895
|
+
replacement = `($parcel$interopDefault(${renamed}))`;
|
|
896
|
+
this.usedHelpers.add('$parcel$interopDefault');
|
|
897
|
+
}
|
|
898
|
+
else if (property) {
|
|
899
|
+
replacement = this.getPropertyAccess(renamed, property);
|
|
900
|
+
}
|
|
901
|
+
replacements.set(local, replacement);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
isWrapped(resolved, parentAsset) {
|
|
907
|
+
if (resolved.meta.isConstantModule) {
|
|
908
|
+
if (!this.bundle.hasAsset(resolved)) {
|
|
909
|
+
throw new assert_1.AssertionError({
|
|
910
|
+
message: `Constant module ${path_1.default.relative(this.options.projectRoot, resolved.filePath)} referenced from ${path_1.default.relative(this.options.projectRoot, parentAsset.filePath)} not found in bundle ${this.bundle.name}`,
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
return false;
|
|
914
|
+
}
|
|
915
|
+
return ((!this.bundle.hasAsset(resolved) && !this.externalAssets.has(resolved)) ||
|
|
916
|
+
(this.wrappedAssets.has(resolved.id) && resolved !== parentAsset));
|
|
917
|
+
}
|
|
918
|
+
getSymbolResolution(parentAsset, resolved, imported, dep, replacements) {
|
|
919
|
+
let { asset: resolvedAsset, exportSymbol, symbol, } = this.bundleGraph.getSymbolResolution(resolved, imported, this.bundle);
|
|
920
|
+
if (resolvedAsset.type !== 'js' ||
|
|
921
|
+
(dep && this.bundleGraph.isDependencySkipped(dep))) {
|
|
922
|
+
// Graceful fallback for non-js imports or when trying to resolve a symbol
|
|
923
|
+
// that is actually unused but we still need a placeholder value.
|
|
924
|
+
return '{}';
|
|
925
|
+
}
|
|
926
|
+
let isWrapped = this.isWrapped(resolvedAsset, parentAsset);
|
|
927
|
+
let staticExports = resolvedAsset.meta.staticExports !== false;
|
|
928
|
+
let publicId = this.bundleGraph.getAssetPublicId(resolvedAsset);
|
|
929
|
+
// External CommonJS dependencies need to be accessed as an object property rather than imported
|
|
930
|
+
// directly to maintain live binding.
|
|
931
|
+
let isExternalCommonJS = !isWrapped &&
|
|
932
|
+
this.bundle.env.isLibrary &&
|
|
933
|
+
this.bundle.env.outputFormat === 'commonjs' &&
|
|
934
|
+
!this.bundle.hasAsset(resolvedAsset);
|
|
935
|
+
// If the resolved asset is wrapped, but imported at the top-level by this asset,
|
|
936
|
+
// then we hoist parcelRequire calls to the top of this asset so side effects run immediately.
|
|
937
|
+
if (isWrapped &&
|
|
938
|
+
dep &&
|
|
939
|
+
!dep?.meta.shouldWrap &&
|
|
940
|
+
symbol !== false &&
|
|
941
|
+
// Only do this if the asset is part of a different bundle (so it was definitely
|
|
942
|
+
// parcelRequire.register'ed there), or if it is indeed registered in this bundle.
|
|
943
|
+
(!this.bundle.hasAsset(resolvedAsset) ||
|
|
944
|
+
!this.shouldSkipAsset(resolvedAsset))) {
|
|
945
|
+
let hoisted = this.hoistedRequires.get(dep.id);
|
|
946
|
+
if (!hoisted) {
|
|
947
|
+
hoisted = new Map();
|
|
948
|
+
this.hoistedRequires.set(dep.id, hoisted);
|
|
949
|
+
}
|
|
950
|
+
hoisted.set(resolvedAsset.id, `var $${publicId} = parcelRequire(${JSON.stringify(publicId)});`);
|
|
951
|
+
}
|
|
952
|
+
if (isWrapped) {
|
|
953
|
+
this.needsPrelude = true;
|
|
954
|
+
}
|
|
955
|
+
// If this is an ESM default import of a CJS module with a `default` symbol,
|
|
956
|
+
// and no __esModule flag, we need to resolve to the namespace instead.
|
|
957
|
+
let isDefaultInterop = exportSymbol === 'default' &&
|
|
958
|
+
staticExports &&
|
|
959
|
+
!isWrapped &&
|
|
960
|
+
(dep?.meta.kind === 'Import' || dep?.meta.kind === 'Export') &&
|
|
961
|
+
resolvedAsset.symbols.hasExportSymbol('*') &&
|
|
962
|
+
resolvedAsset.symbols.hasExportSymbol('default') &&
|
|
963
|
+
!resolvedAsset.symbols.hasExportSymbol('__esModule');
|
|
964
|
+
// Find the namespace object for the resolved module. If wrapped and this
|
|
965
|
+
// is an inline require (not top-level), use a parcelRequire call, otherwise
|
|
966
|
+
// the hoisted variable declared above. Otherwise, if not wrapped, use the
|
|
967
|
+
// namespace export symbol.
|
|
968
|
+
let assetId = resolvedAsset.meta.id;
|
|
969
|
+
(0, assert_1.default)(typeof assetId === 'string');
|
|
970
|
+
let obj;
|
|
971
|
+
if (isWrapped && (!dep || dep?.meta.shouldWrap)) {
|
|
972
|
+
// Wrap in extra parenthesis to not change semantics, e.g.`new (parcelRequire("..."))()`.
|
|
973
|
+
obj = `(parcelRequire(${JSON.stringify(publicId)}))`;
|
|
974
|
+
}
|
|
975
|
+
else if (isWrapped && dep) {
|
|
976
|
+
obj = `$${publicId}`;
|
|
977
|
+
}
|
|
978
|
+
else {
|
|
979
|
+
obj = resolvedAsset.symbols.get('*')?.local || `$${assetId}$exports`;
|
|
980
|
+
obj = replacements?.get(obj) || obj;
|
|
981
|
+
}
|
|
982
|
+
if (imported === '*' || exportSymbol === '*' || isDefaultInterop) {
|
|
983
|
+
// Resolve to the namespace object if requested or this is a CJS default interop reqiure.
|
|
984
|
+
if (parentAsset === resolvedAsset &&
|
|
985
|
+
this.wrappedAssets.has(resolvedAsset.id)) {
|
|
986
|
+
// Directly use module.exports for wrapped assets importing themselves.
|
|
987
|
+
return 'module.exports';
|
|
988
|
+
}
|
|
989
|
+
else {
|
|
990
|
+
return obj;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
else if ((!staticExports || isWrapped || !symbol || isExternalCommonJS) &&
|
|
994
|
+
resolvedAsset !== parentAsset) {
|
|
995
|
+
// If the resolved asset is wrapped or has non-static exports,
|
|
996
|
+
// we need to use a member access off the namespace object rather
|
|
997
|
+
// than a direct reference. If importing default from a CJS module,
|
|
998
|
+
// use a helper to check the __esModule flag at runtime.
|
|
999
|
+
let kind = dep?.meta.kind;
|
|
1000
|
+
if ((!dep || kind === 'Import' || kind === 'Export') &&
|
|
1001
|
+
exportSymbol === 'default' &&
|
|
1002
|
+
resolvedAsset.symbols.hasExportSymbol('*') &&
|
|
1003
|
+
this.needsDefaultInterop(resolvedAsset)) {
|
|
1004
|
+
this.usedHelpers.add('$parcel$interopDefault');
|
|
1005
|
+
return `(/*@__PURE__*/$parcel$interopDefault(${obj}))`;
|
|
1006
|
+
}
|
|
1007
|
+
else {
|
|
1008
|
+
return this.getPropertyAccess(obj, exportSymbol);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
else if (!symbol) {
|
|
1012
|
+
(0, assert_1.default)(false, 'Asset was skipped or not found.');
|
|
1013
|
+
}
|
|
1014
|
+
else {
|
|
1015
|
+
return replacements?.get(symbol) || symbol;
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
getHoistedParcelRequires(parentAsset, dep, resolved) {
|
|
1019
|
+
if (resolved.type !== 'js') {
|
|
1020
|
+
return ['', 0];
|
|
1021
|
+
}
|
|
1022
|
+
let hoisted = this.hoistedRequires.get(dep.id);
|
|
1023
|
+
let res = '';
|
|
1024
|
+
let lineCount = 0;
|
|
1025
|
+
let isWrapped = this.isWrapped(resolved, parentAsset);
|
|
1026
|
+
// If the resolved asset is wrapped and is imported in the top-level by this asset,
|
|
1027
|
+
// we need to run side effects when this asset runs. If the resolved asset is not
|
|
1028
|
+
// the first one in the hoisted requires, we need to insert a parcelRequire here
|
|
1029
|
+
// so it runs first.
|
|
1030
|
+
if (isWrapped &&
|
|
1031
|
+
!dep.meta.shouldWrap &&
|
|
1032
|
+
(!hoisted || hoisted.keys().next().value !== resolved.id) &&
|
|
1033
|
+
!this.bundleGraph.isDependencySkipped(dep) &&
|
|
1034
|
+
!this.shouldSkipAsset(resolved)) {
|
|
1035
|
+
this.needsPrelude = true;
|
|
1036
|
+
res += `parcelRequire(${JSON.stringify(this.bundleGraph.getAssetPublicId(resolved))});`;
|
|
1037
|
+
}
|
|
1038
|
+
if (hoisted) {
|
|
1039
|
+
this.needsPrelude = true;
|
|
1040
|
+
if ((0, feature_flags_1.getFeatureFlag)('applyScopeHoistingImprovementV2')) {
|
|
1041
|
+
let hoistedValues = [...hoisted.values()].filter((val) => !this.seenHoistedRequires.has(val));
|
|
1042
|
+
for (let val of hoistedValues) {
|
|
1043
|
+
this.seenHoistedRequires.add(val);
|
|
1044
|
+
}
|
|
1045
|
+
res += '\n' + hoistedValues.join('\n');
|
|
1046
|
+
lineCount += hoisted.size;
|
|
1047
|
+
}
|
|
1048
|
+
else {
|
|
1049
|
+
res += '\n' + [...hoisted.values()].join('\n');
|
|
1050
|
+
lineCount += hoisted.size;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
return [res, lineCount];
|
|
1054
|
+
}
|
|
1055
|
+
buildAssetPrelude(asset, deps, replacements) {
|
|
1056
|
+
let prepend = '';
|
|
1057
|
+
let prependLineCount = 0;
|
|
1058
|
+
let append = '';
|
|
1059
|
+
let shouldWrap = this.wrappedAssets.has(asset.id);
|
|
1060
|
+
let usedSymbols = (0, nullthrows_1.default)(this.bundleGraph.getUsedSymbols(asset));
|
|
1061
|
+
let assetId = asset.meta.id;
|
|
1062
|
+
(0, assert_1.default)(typeof assetId === 'string');
|
|
1063
|
+
// If the asset has a namespace export symbol, it is CommonJS.
|
|
1064
|
+
// If there's no __esModule flag, and default is a used symbol, we need
|
|
1065
|
+
// to insert an interop helper.
|
|
1066
|
+
let defaultInterop = asset.symbols.hasExportSymbol('*') &&
|
|
1067
|
+
usedSymbols.has('default') &&
|
|
1068
|
+
!asset.symbols.hasExportSymbol('__esModule');
|
|
1069
|
+
let usedNamespace;
|
|
1070
|
+
if ((0, feature_flags_1.getFeatureFlag)('inlineConstOptimisationFix') &&
|
|
1071
|
+
asset.meta.isConstantModule) {
|
|
1072
|
+
// Only set usedNamespace if there is an incoming dependency in the current bundle that uses '*'
|
|
1073
|
+
usedNamespace = this.bundleGraph
|
|
1074
|
+
.getIncomingDependencies(asset)
|
|
1075
|
+
.some((dep) => this.bundle.hasDependency(dep) &&
|
|
1076
|
+
(0, nullthrows_1.default)(this.bundleGraph.getUsedSymbols(dep)).has('*'));
|
|
1077
|
+
}
|
|
1078
|
+
else {
|
|
1079
|
+
usedNamespace =
|
|
1080
|
+
// If the asset has * in its used symbols, we might need the exports namespace.
|
|
1081
|
+
// The one case where this isn't true is in ESM library entries, where the only
|
|
1082
|
+
// dependency on * is the entry dependency. In this case, we will use ESM exports
|
|
1083
|
+
// instead of the namespace object.
|
|
1084
|
+
(usedSymbols.has('*') &&
|
|
1085
|
+
(this.bundle.env.outputFormat !== 'esmodule' ||
|
|
1086
|
+
!this.bundle.env.isLibrary ||
|
|
1087
|
+
asset !== this.bundle.getMainEntry() ||
|
|
1088
|
+
this.bundleGraph
|
|
1089
|
+
.getIncomingDependencies(asset)
|
|
1090
|
+
.some((dep) => !dep.isEntry &&
|
|
1091
|
+
this.bundle.hasDependency(dep) &&
|
|
1092
|
+
(0, nullthrows_1.default)(this.bundleGraph.getUsedSymbols(dep)).has('*')))) ||
|
|
1093
|
+
// If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
|
|
1094
|
+
// we fallback on the namespace object.
|
|
1095
|
+
(asset.symbols.hasExportSymbol('*') &&
|
|
1096
|
+
[...usedSymbols].some((s) => !asset.symbols.hasExportSymbol(s))) ||
|
|
1097
|
+
// If the exports has this asset's namespace (e.g. ESM output from CJS input),
|
|
1098
|
+
// include the namespace object for the default export.
|
|
1099
|
+
this.exportedSymbols.has(`$${assetId}$exports`) ||
|
|
1100
|
+
// CommonJS library bundle entries always need a namespace.
|
|
1101
|
+
(this.bundle.env.isLibrary &&
|
|
1102
|
+
this.bundle.env.outputFormat === 'commonjs' &&
|
|
1103
|
+
asset === this.bundle.getMainEntry());
|
|
1104
|
+
}
|
|
1105
|
+
// If the asset doesn't have static exports, should wrap, the namespace is used,
|
|
1106
|
+
// or we need default interop, then we need to synthesize a namespace object for
|
|
1107
|
+
// this asset.
|
|
1108
|
+
if (asset.meta.staticExports === false ||
|
|
1109
|
+
shouldWrap ||
|
|
1110
|
+
usedNamespace ||
|
|
1111
|
+
defaultInterop) {
|
|
1112
|
+
// Insert a declaration for the exports namespace object. If the asset is wrapped
|
|
1113
|
+
// we don't need to do this, because we'll use the `module.exports` object provided
|
|
1114
|
+
// by the wrapper instead. This is also true of CommonJS entry assets, which will use
|
|
1115
|
+
// the `module.exports` object provided by CJS.
|
|
1116
|
+
if (!shouldWrap &&
|
|
1117
|
+
(this.bundle.env.outputFormat !== 'commonjs' ||
|
|
1118
|
+
asset !== this.bundle.getMainEntry())) {
|
|
1119
|
+
prepend += `var $${assetId}$exports = {};\n`;
|
|
1120
|
+
prependLineCount++;
|
|
1121
|
+
}
|
|
1122
|
+
// Insert the __esModule interop flag for this module if it has a `default` export
|
|
1123
|
+
// and the namespace symbol is used.
|
|
1124
|
+
// TODO: only if required by CJS?
|
|
1125
|
+
if (asset.symbols.hasExportSymbol('default') && usedSymbols.has('*')) {
|
|
1126
|
+
prepend += `\n$parcel$defineInteropFlag($${assetId}$exports);\n`;
|
|
1127
|
+
prependLineCount += 2;
|
|
1128
|
+
this.usedHelpers.add('$parcel$defineInteropFlag');
|
|
1129
|
+
}
|
|
1130
|
+
// Find wildcard re-export dependencies, and make sure their exports are also included in
|
|
1131
|
+
// ours. Importantly, add them before the asset's own exports so that wildcard exports get
|
|
1132
|
+
// correctly overwritten by own exports of the same name.
|
|
1133
|
+
for (let dep of deps) {
|
|
1134
|
+
let resolved = this.bundleGraph.getResolvedAsset(dep, this.bundle);
|
|
1135
|
+
if (dep.isOptional || this.bundleGraph.isDependencySkipped(dep)) {
|
|
1136
|
+
continue;
|
|
1137
|
+
}
|
|
1138
|
+
let isWrapped = resolved && resolved.meta.shouldWrap;
|
|
1139
|
+
for (let [imported, { local }] of dep.symbols) {
|
|
1140
|
+
if (imported === '*' && local === '*') {
|
|
1141
|
+
if (!resolved) {
|
|
1142
|
+
// Re-exporting an external module. This should have already been handled in buildReplacements.
|
|
1143
|
+
let external = (0, nullthrows_1.default)((0, nullthrows_1.default)(this.externals.get(dep.specifier)).get('*'));
|
|
1144
|
+
append += `$parcel$exportWildcard($${assetId}$exports, ${external});\n`;
|
|
1145
|
+
this.usedHelpers.add('$parcel$exportWildcard');
|
|
1146
|
+
continue;
|
|
1147
|
+
}
|
|
1148
|
+
// If the resolved asset has an exports object, use the $parcel$exportWildcard helper
|
|
1149
|
+
// to re-export all symbols. Otherwise, if there's no namespace object available, add
|
|
1150
|
+
// $parcel$export calls for each used symbol of the dependency.
|
|
1151
|
+
if (isWrapped ||
|
|
1152
|
+
resolved.meta.staticExports === false ||
|
|
1153
|
+
(0, nullthrows_1.default)(this.bundleGraph.getUsedSymbols(resolved)).has('*') ||
|
|
1154
|
+
// an empty asset
|
|
1155
|
+
(!resolved.meta.hasCJSExports &&
|
|
1156
|
+
resolved.symbols.hasExportSymbol('*'))) {
|
|
1157
|
+
let obj = this.getSymbolResolution(asset, resolved, '*', dep, replacements);
|
|
1158
|
+
append += `$parcel$exportWildcard($${assetId}$exports, ${obj});\n`;
|
|
1159
|
+
this.usedHelpers.add('$parcel$exportWildcard');
|
|
1160
|
+
}
|
|
1161
|
+
else {
|
|
1162
|
+
for (let symbol of (0, nullthrows_1.default)(this.bundleGraph.getUsedSymbols(dep))) {
|
|
1163
|
+
if (symbol === 'default' || // `export * as ...` does not include the default export
|
|
1164
|
+
symbol === '__esModule') {
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
let resolvedSymbol = this.getSymbolResolution(asset, resolved, symbol, undefined, replacements);
|
|
1168
|
+
let get = this.buildFunctionExpression([], resolvedSymbol);
|
|
1169
|
+
let set = asset.meta.hasCJSExports
|
|
1170
|
+
? ', ' +
|
|
1171
|
+
this.buildFunctionExpression(['v'], `${resolvedSymbol} = v`)
|
|
1172
|
+
: '';
|
|
1173
|
+
prepend += `$parcel$export($${assetId}$exports, ${JSON.stringify(symbol)}, ${get}${set});\n`;
|
|
1174
|
+
this.usedHelpers.add('$parcel$export');
|
|
1175
|
+
prependLineCount++;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
// Find the used exports of this module. This is based on the used symbols of
|
|
1182
|
+
// incoming dependencies rather than the asset's own used exports so that we include
|
|
1183
|
+
// re-exported symbols rather than only symbols declared in this asset.
|
|
1184
|
+
let incomingDeps = this.bundleGraph.getIncomingDependencies(asset);
|
|
1185
|
+
let usedExports = [...asset.symbols.exportSymbols()].filter((symbol) => {
|
|
1186
|
+
if (symbol === '*') {
|
|
1187
|
+
return false;
|
|
1188
|
+
}
|
|
1189
|
+
// If we need default interop, then all symbols are needed because the `default`
|
|
1190
|
+
// symbol really maps to the whole namespace.
|
|
1191
|
+
if (defaultInterop) {
|
|
1192
|
+
return true;
|
|
1193
|
+
}
|
|
1194
|
+
let unused = incomingDeps.every((d) => {
|
|
1195
|
+
let symbols = this.bundleGraph.getUsedSymbols(d);
|
|
1196
|
+
// No used symbols available for the asset, make sure we keep all of them
|
|
1197
|
+
if (!symbols)
|
|
1198
|
+
return false;
|
|
1199
|
+
return !symbols.has(symbol) && !symbols.has('*');
|
|
1200
|
+
});
|
|
1201
|
+
return !unused;
|
|
1202
|
+
});
|
|
1203
|
+
if (usedExports.length > 0) {
|
|
1204
|
+
// Insert $parcel$export calls for each of the used exports. This creates a getter/setter
|
|
1205
|
+
// for the symbol so that when the value changes the object property also changes. This is
|
|
1206
|
+
// required to simulate ESM live bindings. It's easier to do it this way rather than inserting
|
|
1207
|
+
// additional assignments after each mutation of the original binding.
|
|
1208
|
+
for (let exp of usedExports) {
|
|
1209
|
+
let resolved = this.getSymbolResolution(asset, asset, exp, undefined, replacements);
|
|
1210
|
+
const meta = asset.symbols.get(exp)?.meta;
|
|
1211
|
+
if ((0, feature_flags_1.getFeatureFlag)('exportsRebindingOptimisation') &&
|
|
1212
|
+
meta?.isStaticBindingSafe) {
|
|
1213
|
+
append += `$${assetId}$exports[${JSON.stringify(exp)}] = ${resolved};\n`;
|
|
1214
|
+
}
|
|
1215
|
+
else {
|
|
1216
|
+
let get = this.buildFunctionExpression([], resolved);
|
|
1217
|
+
let isEsmExport = !!asset.symbols.get(exp)?.meta?.isEsm;
|
|
1218
|
+
let set = !isEsmExport && asset.meta.hasCJSExports
|
|
1219
|
+
? ', ' + this.buildFunctionExpression(['v'], `${resolved} = v`)
|
|
1220
|
+
: '';
|
|
1221
|
+
prepend += `$parcel$export($${assetId}$exports, ${JSON.stringify(exp)}, ${get}${set});\n`;
|
|
1222
|
+
this.usedHelpers.add('$parcel$export');
|
|
1223
|
+
prependLineCount += 1 + usedExports.length;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
return [prepend, prependLineCount, append];
|
|
1229
|
+
}
|
|
1230
|
+
buildBundlePrelude() {
|
|
1231
|
+
let enableSourceMaps = this.bundle.env.sourceMap;
|
|
1232
|
+
let res = '';
|
|
1233
|
+
let lines = 0;
|
|
1234
|
+
// Add hashbang if the entry asset recorded an interpreter.
|
|
1235
|
+
let mainEntry = this.bundle.getMainEntry();
|
|
1236
|
+
if (mainEntry &&
|
|
1237
|
+
!this.isAsyncBundle &&
|
|
1238
|
+
!this.bundle.target.env.isBrowser()) {
|
|
1239
|
+
let interpreter = mainEntry.meta.interpreter;
|
|
1240
|
+
(0, assert_1.default)(interpreter == null || typeof interpreter === 'string');
|
|
1241
|
+
if (interpreter != null) {
|
|
1242
|
+
res += `#!${interpreter}\n`;
|
|
1243
|
+
lines++;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
// The output format may have specific things to add at the start of the bundle (e.g. imports).
|
|
1247
|
+
let [outputFormatPrelude, outputFormatLines] = this.outputFormat.buildBundlePrelude();
|
|
1248
|
+
res += outputFormatPrelude;
|
|
1249
|
+
lines += outputFormatLines;
|
|
1250
|
+
// Add used helpers.
|
|
1251
|
+
if (this.needsPrelude) {
|
|
1252
|
+
this.usedHelpers.add('$parcel$global');
|
|
1253
|
+
}
|
|
1254
|
+
for (let helper of this.usedHelpers) {
|
|
1255
|
+
// @ts-expect-error TS7053
|
|
1256
|
+
let currentHelper = helpers_1.helpers[helper];
|
|
1257
|
+
if (typeof currentHelper === 'function') {
|
|
1258
|
+
// @ts-expect-error TS7053
|
|
1259
|
+
currentHelper = helpers_1.helpers[helper](this.bundle.env);
|
|
1260
|
+
}
|
|
1261
|
+
res += currentHelper;
|
|
1262
|
+
if (enableSourceMaps) {
|
|
1263
|
+
lines += (0, utils_1.countLines)(currentHelper) - 1;
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
if (this.needsPrelude) {
|
|
1267
|
+
// Add the prelude if this is potentially the first JS bundle to load in a
|
|
1268
|
+
// particular context (e.g. entry scripts in HTML, workers, etc.).
|
|
1269
|
+
let parentBundles = this.bundleGraph.getParentBundles(this.bundle);
|
|
1270
|
+
let mightBeFirstJS = parentBundles.length === 0 ||
|
|
1271
|
+
parentBundles.some((b) => b.type !== 'js') ||
|
|
1272
|
+
this.bundleGraph
|
|
1273
|
+
.getBundleGroupsContainingBundle(this.bundle)
|
|
1274
|
+
.some((g) => this.bundleGraph.isEntryBundleGroup(g)) ||
|
|
1275
|
+
this.bundle.env.isIsolated() ||
|
|
1276
|
+
this.bundle.bundleBehavior === 'isolated' ||
|
|
1277
|
+
this.bundle.bundleBehavior === 'inlineIsolated' ||
|
|
1278
|
+
// Conditional deps may be loaded before entrypoints on the server
|
|
1279
|
+
this.hasConditionalDependency();
|
|
1280
|
+
if (mightBeFirstJS) {
|
|
1281
|
+
let preludeCode = ((0, feature_flags_1.getFeatureFlag)('useNewPrelude') ? helpers_1.preludeNew : helpers_1.preludeOld)(this.parcelRequireName);
|
|
1282
|
+
res += preludeCode;
|
|
1283
|
+
if (enableSourceMaps) {
|
|
1284
|
+
lines += (0, utils_1.countLines)(preludeCode) - 1;
|
|
1285
|
+
}
|
|
1286
|
+
if (this.shouldBundleQueue(this.bundle)) {
|
|
1287
|
+
let bundleQueuePreludeCode = (0, helpers_1.bundleQueuePrelude)(this.bundle.env);
|
|
1288
|
+
res += bundleQueuePreludeCode;
|
|
1289
|
+
if (enableSourceMaps) {
|
|
1290
|
+
lines += (0, utils_1.countLines)(bundleQueuePreludeCode) - 1;
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
else {
|
|
1295
|
+
// Otherwise, get the current parcelRequire global.
|
|
1296
|
+
const escaped = JSON.stringify(this.parcelRequireName);
|
|
1297
|
+
res += `var parcelRequire = $parcel$global[${escaped}];\n`;
|
|
1298
|
+
lines++;
|
|
1299
|
+
res += `var parcelRegister = parcelRequire.register;\n`;
|
|
1300
|
+
lines++;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
// Add importScripts for sibling bundles in workers.
|
|
1304
|
+
if (this.bundle.env.isWorker() ||
|
|
1305
|
+
this.bundle.env.isTesseract() ||
|
|
1306
|
+
this.bundle.env.isWorklet()) {
|
|
1307
|
+
let importScripts = '';
|
|
1308
|
+
let bundles = this.bundleGraph.getReferencedBundles(this.bundle);
|
|
1309
|
+
for (let b of bundles) {
|
|
1310
|
+
if (this.bundle.env.outputFormat === 'esmodule') {
|
|
1311
|
+
// importScripts() is not allowed in native ES module workers.
|
|
1312
|
+
importScripts += `import "${(0, utils_1.relativeBundlePath)(this.bundle, b)}";\n`;
|
|
1313
|
+
}
|
|
1314
|
+
else {
|
|
1315
|
+
importScripts += `importScripts("${(0, utils_1.relativeBundlePath)(this.bundle, b)}");\n`;
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
res += importScripts;
|
|
1319
|
+
lines += bundles.length;
|
|
1320
|
+
}
|
|
1321
|
+
return [res, lines];
|
|
1322
|
+
}
|
|
1323
|
+
needsDefaultInterop(asset) {
|
|
1324
|
+
if (asset.symbols.hasExportSymbol('*') &&
|
|
1325
|
+
!asset.symbols.hasExportSymbol('default')) {
|
|
1326
|
+
return true;
|
|
1327
|
+
}
|
|
1328
|
+
return false;
|
|
1329
|
+
}
|
|
1330
|
+
shouldSkipAsset(asset) {
|
|
1331
|
+
if (this.isScriptEntry(asset)) {
|
|
1332
|
+
return true;
|
|
1333
|
+
}
|
|
1334
|
+
return (asset.sideEffects === false &&
|
|
1335
|
+
(0, nullthrows_1.default)(this.bundleGraph.getUsedSymbols(asset)).size == 0 &&
|
|
1336
|
+
!this.bundleGraph.isAssetReferenced(this.bundle, asset));
|
|
1337
|
+
}
|
|
1338
|
+
isScriptEntry(asset) {
|
|
1339
|
+
return (this.bundle.env.outputFormat === 'global' &&
|
|
1340
|
+
this.bundle.env.sourceType === 'script' &&
|
|
1341
|
+
asset === this.bundle.getMainEntry());
|
|
1342
|
+
}
|
|
1343
|
+
buildFunctionExpression(args, expr) {
|
|
1344
|
+
return this.bundle.env.supports('arrow-functions', true)
|
|
1345
|
+
? `(${args.join(', ')}) => ${expr}`
|
|
1346
|
+
: `function (${args.join(', ')}) { return ${expr}; }`;
|
|
1347
|
+
}
|
|
1348
|
+
hasConditionalDependency() {
|
|
1349
|
+
if (!(0, feature_flags_1.getFeatureFlag)('conditionalBundlingApi')) {
|
|
1350
|
+
return false;
|
|
1351
|
+
}
|
|
1352
|
+
return this.bundle
|
|
1353
|
+
.getEntryAssets()
|
|
1354
|
+
.some((entry) => this.bundleGraph
|
|
1355
|
+
.getIncomingDependencies(entry)
|
|
1356
|
+
.some((dep) => dep.priority === 'conditional'));
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
exports.ScopeHoistingPackager = ScopeHoistingPackager;
|