@parcel/packager-js 2.11.0 → 2.13.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/lib/DevPackager.js +6 -5
- package/lib/ESMOutputFormat.js +8 -1
- package/lib/ScopeHoistingPackager.js +130 -61
- package/lib/dev-prelude.js +1 -1
- package/lib/index.js +17 -18
- package/lib/utils.js +18 -1
- package/package.json +9 -9
- package/src/DevPackager.js +5 -5
- package/src/ESMOutputFormat.js +8 -1
- package/src/ScopeHoistingPackager.js +190 -69
- package/src/dev-prelude.js +1 -1
- package/src/index.js +19 -14
- package/src/utils.js +17 -0
package/lib/DevPackager.js
CHANGED
|
@@ -40,7 +40,7 @@ function _fs() {
|
|
|
40
40
|
return data;
|
|
41
41
|
}
|
|
42
42
|
var _utils2 = require("./utils");
|
|
43
|
-
function _interopRequireDefault(
|
|
43
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
44
44
|
const PRELUDE = _fs().default.readFileSync(_path().default.join(__dirname, 'dev-prelude.js'), 'utf8').trim().replace(/;$/, '');
|
|
45
45
|
class DevPackager {
|
|
46
46
|
constructor(options, bundleGraph, bundle, parcelRequireName) {
|
|
@@ -98,13 +98,14 @@ class DevPackager {
|
|
|
98
98
|
let dependencies = this.bundleGraph.getDependencies(asset);
|
|
99
99
|
for (let dep of dependencies) {
|
|
100
100
|
let resolved = this.bundleGraph.getResolvedAsset(dep, this.bundle);
|
|
101
|
+
let specifier = (0, _utils2.getSpecifier)(dep);
|
|
101
102
|
if (this.bundleGraph.isDependencySkipped(dep)) {
|
|
102
|
-
deps[
|
|
103
|
+
deps[specifier] = false;
|
|
103
104
|
} else if (resolved) {
|
|
104
|
-
deps[
|
|
105
|
+
deps[specifier] = this.bundleGraph.getAssetPublicId(resolved);
|
|
105
106
|
} else {
|
|
106
107
|
// An external module - map placeholder to original specifier.
|
|
107
|
-
deps[
|
|
108
|
+
deps[specifier] = dep.specifier;
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
111
|
let {
|
|
@@ -112,7 +113,7 @@ class DevPackager {
|
|
|
112
113
|
mapBuffer
|
|
113
114
|
} = results[i];
|
|
114
115
|
let output = code || '';
|
|
115
|
-
wrapped += JSON.stringify(this.bundleGraph.getAssetPublicId(asset)) + ':[function(require,module,exports) {\n' + output + '\n},';
|
|
116
|
+
wrapped += JSON.stringify(this.bundleGraph.getAssetPublicId(asset)) + ':[function(require,module,exports,__globalThis) {\n' + output + '\n},';
|
|
116
117
|
wrapped += JSON.stringify(deps);
|
|
117
118
|
wrapped += ']';
|
|
118
119
|
if (this.bundle.env.isNode() && asset.meta.has_node_replacements === true) {
|
package/lib/ESMOutputFormat.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.ESMOutputFormat = void 0;
|
|
7
|
+
var _utils = require("./utils");
|
|
7
8
|
class ESMOutputFormat {
|
|
8
9
|
constructor(packager) {
|
|
9
10
|
this.packager = packager;
|
|
@@ -22,6 +23,9 @@ class ESMOutputFormat {
|
|
|
22
23
|
namespaceSpecifier = `* as ${symbol}`;
|
|
23
24
|
} else {
|
|
24
25
|
let specifier = imported;
|
|
26
|
+
if (!(0, _utils.isValidIdentifier)(specifier)) {
|
|
27
|
+
specifier = JSON.stringify(specifier);
|
|
28
|
+
}
|
|
25
29
|
if (symbol !== imported) {
|
|
26
30
|
specifier += ` as ${symbol}`;
|
|
27
31
|
}
|
|
@@ -78,7 +82,10 @@ class ESMOutputFormat {
|
|
|
78
82
|
}
|
|
79
83
|
for (let as of exportAs) {
|
|
80
84
|
let specifier = local;
|
|
81
|
-
if (
|
|
85
|
+
if (as !== local) {
|
|
86
|
+
if (!(0, _utils.isValidIdentifier)(as)) {
|
|
87
|
+
as = JSON.stringify(as);
|
|
88
|
+
}
|
|
82
89
|
specifier += ` as ${as}`;
|
|
83
90
|
}
|
|
84
91
|
exportSpecifiers.push(specifier);
|
|
@@ -26,7 +26,7 @@ function _nullthrows() {
|
|
|
26
26
|
return data;
|
|
27
27
|
}
|
|
28
28
|
function _assert() {
|
|
29
|
-
const data =
|
|
29
|
+
const data = _interopRequireWildcard(require("assert"));
|
|
30
30
|
_assert = function () {
|
|
31
31
|
return data;
|
|
32
32
|
};
|
|
@@ -59,13 +59,8 @@ var _GlobalOutputFormat = require("./GlobalOutputFormat");
|
|
|
59
59
|
var _helpers = require("./helpers");
|
|
60
60
|
var _utils2 = require("./utils");
|
|
61
61
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
62
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u &&
|
|
63
|
-
function _interopRequireDefault(
|
|
64
|
-
// https://262.ecma-international.org/6.0/#sec-names-and-keywords
|
|
65
|
-
const IDENTIFIER_RE = /^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*$/u;
|
|
66
|
-
const ID_START_RE = /^[$_\p{ID_Start}]/u;
|
|
67
|
-
const NON_ID_CONTINUE_RE = /[^$_\u200C\u200D\p{ID_Continue}]/gu;
|
|
68
|
-
|
|
62
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
63
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
69
64
|
// General regex used to replace imports with the resolved code, references with resolutions,
|
|
70
65
|
// and count the number of newlines in the file for source maps.
|
|
71
66
|
const REPLACEMENT_RE = /\n|import\s+"([0-9a-f]{16}:.+?)";|(?:\$[0-9a-f]{16}\$exports)|(?:\$[0-9a-f]{16}\$(?:import|importAsync|require)\$[0-9a-f]+(?:\$[0-9a-f]+)?)/g;
|
|
@@ -116,23 +111,10 @@ class ScopeHoistingPackager {
|
|
|
116
111
|
// of each bundle group pointing at the sibling bundles. These can be
|
|
117
112
|
// picked up by another bundler later at which point runtimes will be added.
|
|
118
113
|
if (this.bundle.env.isLibrary || this.bundle.env.outputFormat === 'commonjs') {
|
|
119
|
-
for (let b of this.bundleGraph.getReferencedBundles(this.bundle
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.externalAssets.add(entry);
|
|
124
|
-
let usedSymbols = this.bundleGraph.getUsedSymbols(entry) || new Set();
|
|
125
|
-
for (let s of usedSymbols) {
|
|
126
|
-
// If the referenced bundle is ESM, and we are importing '*', use 'default' instead.
|
|
127
|
-
// This matches the logic below in buildExportedSymbols.
|
|
128
|
-
let imported = s;
|
|
129
|
-
if (imported === '*' && b.env.outputFormat === 'esmodule') {
|
|
130
|
-
imported = 'default';
|
|
131
|
-
}
|
|
132
|
-
symbols.set(imported, this.getSymbolResolution(entry, entry, s));
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
this.externals.set((0, _utils().relativeBundlePath)(this.bundle, b), symbols);
|
|
114
|
+
for (let b of this.bundleGraph.getReferencedBundles(this.bundle, {
|
|
115
|
+
recursive: false
|
|
116
|
+
})) {
|
|
117
|
+
this.externals.set((0, _utils().relativeBundlePath)(this.bundle, b), new Map());
|
|
136
118
|
}
|
|
137
119
|
}
|
|
138
120
|
let res = '';
|
|
@@ -232,7 +214,9 @@ class ScopeHoistingPackager {
|
|
|
232
214
|
};
|
|
233
215
|
}
|
|
234
216
|
shouldBundleQueue(bundle) {
|
|
235
|
-
|
|
217
|
+
let referencingBundles = this.bundleGraph.getReferencingBundles(bundle);
|
|
218
|
+
let hasHtmlReference = referencingBundles.some(b => b.type === 'html');
|
|
219
|
+
return this.useAsyncBundleRuntime && bundle.type === 'js' && bundle.bundleBehavior !== 'inline' && bundle.env.outputFormat === 'esmodule' && !bundle.env.isIsolated() && bundle.bundleBehavior !== 'isolated' && hasHtmlReference;
|
|
236
220
|
}
|
|
237
221
|
runWhenReady(bundle, codeToRun) {
|
|
238
222
|
let deps = this.bundleGraph.getReferencedBundles(bundle).filter(b => this.shouldBundleQueue(b)).map(b => b.publicId);
|
|
@@ -256,8 +240,9 @@ class ScopeHoistingPackager {
|
|
|
256
240
|
map
|
|
257
241
|
}];
|
|
258
242
|
});
|
|
259
|
-
if (asset.meta.shouldWrap || this.
|
|
260
|
-
if
|
|
243
|
+
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')) {
|
|
244
|
+
// Don't wrap constant "entry" modules _except_ if they are referenced by any lazy dependency
|
|
245
|
+
if (!asset.meta.isConstantModule || this.bundleGraph.getIncomingDependencies(asset).some(dep => dep.priority === 'lazy')) {
|
|
261
246
|
this.wrappedAssets.add(asset.id);
|
|
262
247
|
wrapped.push(asset);
|
|
263
248
|
}
|
|
@@ -282,13 +267,14 @@ class ScopeHoistingPackager {
|
|
|
282
267
|
return wrapped;
|
|
283
268
|
}
|
|
284
269
|
buildExportedSymbols() {
|
|
285
|
-
if (
|
|
270
|
+
if (!this.bundle.env.isLibrary || this.bundle.env.outputFormat !== 'esmodule') {
|
|
286
271
|
return;
|
|
287
272
|
}
|
|
288
273
|
|
|
289
274
|
// TODO: handle ESM exports of wrapped entry assets...
|
|
290
275
|
let entry = this.bundle.getMainEntry();
|
|
291
276
|
if (entry && !this.wrappedAssets.has(entry.id)) {
|
|
277
|
+
let hasNamespace = entry.symbols.hasExportSymbol('*');
|
|
292
278
|
for (let {
|
|
293
279
|
asset,
|
|
294
280
|
exportAs,
|
|
@@ -297,6 +283,12 @@ class ScopeHoistingPackager {
|
|
|
297
283
|
} of this.bundleGraph.getExportedSymbols(entry)) {
|
|
298
284
|
if (typeof symbol === 'string') {
|
|
299
285
|
var _this$exportedSymbols, _entry$symbols$get2;
|
|
286
|
+
// If the module has a namespace (e.g. commonjs), and this is not an entry, only export the namespace
|
|
287
|
+
// as default, without individual exports. This mirrors the importing logic in addExternal, avoiding
|
|
288
|
+
// extra unused exports and potential for non-identifier export names.
|
|
289
|
+
if (hasNamespace && this.isAsyncBundle && exportAs !== '*') {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
300
292
|
let symbols = (_this$exportedSymbols = this.exportedSymbols.get(symbol === '*' ? (0, _nullthrows().default)((_entry$symbols$get2 = entry.symbols.get('*')) === null || _entry$symbols$get2 === void 0 ? void 0 : _entry$symbols$get2.local) : symbol)) === null || _this$exportedSymbols === void 0 ? void 0 : _this$exportedSymbols.exportAs;
|
|
301
293
|
if (!symbols) {
|
|
302
294
|
symbols = [];
|
|
@@ -331,8 +323,8 @@ class ScopeHoistingPackager {
|
|
|
331
323
|
}
|
|
332
324
|
}
|
|
333
325
|
getTopLevelName(name) {
|
|
334
|
-
name =
|
|
335
|
-
if (
|
|
326
|
+
name = (0, _utils2.makeValidIdentifier)(name);
|
|
327
|
+
if (this.globalNames.has(name)) {
|
|
336
328
|
name = '_' + name;
|
|
337
329
|
}
|
|
338
330
|
let count = this.topLevelNames.get(name);
|
|
@@ -344,7 +336,7 @@ class ScopeHoistingPackager {
|
|
|
344
336
|
return name + count;
|
|
345
337
|
}
|
|
346
338
|
getPropertyAccess(obj, property) {
|
|
347
|
-
if (
|
|
339
|
+
if ((0, _utils2.isValidIdentifier)(property)) {
|
|
348
340
|
return `${obj}.${property}`;
|
|
349
341
|
}
|
|
350
342
|
return `${obj}[${JSON.stringify(property)}]`;
|
|
@@ -401,7 +393,7 @@ class ScopeHoistingPackager {
|
|
|
401
393
|
code = code.replace('$parcel$filenameReplace', relPath);
|
|
402
394
|
}
|
|
403
395
|
let [depMap, replacements] = this.buildReplacements(asset, deps);
|
|
404
|
-
let [prepend, prependLines, append] = this.buildAssetPrelude(asset, deps);
|
|
396
|
+
let [prepend, prependLines, append] = this.buildAssetPrelude(asset, deps, replacements);
|
|
405
397
|
if (prependLines > 0) {
|
|
406
398
|
sourceMap === null || sourceMap === void 0 || sourceMap.offsetLines(1, prependLines);
|
|
407
399
|
code = prepend + code;
|
|
@@ -421,7 +413,6 @@ class ScopeHoistingPackager {
|
|
|
421
413
|
let offset = 0;
|
|
422
414
|
let columnStartIndex = 0;
|
|
423
415
|
code = code.replace(REPLACEMENT_RE, (m, d, i) => {
|
|
424
|
-
var _replacements$get;
|
|
425
416
|
if (m === '\n') {
|
|
426
417
|
columnStartIndex = i + offset + 1;
|
|
427
418
|
lineCount++;
|
|
@@ -481,7 +472,7 @@ class ScopeHoistingPackager {
|
|
|
481
472
|
}
|
|
482
473
|
|
|
483
474
|
// If it wasn't a dependency, then it was an inline replacement (e.g. $id$import$foo -> $id$export$foo).
|
|
484
|
-
let replacement =
|
|
475
|
+
let replacement = replacements.get(m) ?? m;
|
|
485
476
|
if (sourceMap) {
|
|
486
477
|
// Offset the source map columns for this line if the replacement was a different length.
|
|
487
478
|
// This assumes that the match and replacement both do not contain any newlines.
|
|
@@ -543,6 +534,16 @@ ${code}
|
|
|
543
534
|
if (!resolved) {
|
|
544
535
|
continue;
|
|
545
536
|
}
|
|
537
|
+
|
|
538
|
+
// Handle imports from other bundles in libraries.
|
|
539
|
+
if (this.bundle.env.isLibrary && !this.bundle.hasAsset(resolved)) {
|
|
540
|
+
let referencedBundle = this.bundleGraph.getReferencedBundle(dep, this.bundle);
|
|
541
|
+
if (referencedBundle && referencedBundle.getMainEntry() === resolved && referencedBundle.type === 'js' && !this.bundleGraph.isAssetReferenced(referencedBundle, resolved)) {
|
|
542
|
+
this.addExternal(dep, replacements, referencedBundle);
|
|
543
|
+
this.externalAssets.add(resolved);
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
546
547
|
for (let [imported, {
|
|
547
548
|
local
|
|
548
549
|
}] of dep.symbols) {
|
|
@@ -575,7 +576,7 @@ ${code}
|
|
|
575
576
|
}
|
|
576
577
|
return [depMap, replacements];
|
|
577
578
|
}
|
|
578
|
-
addExternal(dep, replacements) {
|
|
579
|
+
addExternal(dep, replacements, referencedBundle) {
|
|
579
580
|
if (this.bundle.env.outputFormat === 'global') {
|
|
580
581
|
throw new (_diagnostic().default)({
|
|
581
582
|
diagnostic: {
|
|
@@ -587,12 +588,16 @@ ${code}
|
|
|
587
588
|
}
|
|
588
589
|
});
|
|
589
590
|
}
|
|
591
|
+
let specifier = dep.specifier;
|
|
592
|
+
if (referencedBundle) {
|
|
593
|
+
specifier = (0, _utils().relativeBundlePath)(this.bundle, referencedBundle);
|
|
594
|
+
}
|
|
590
595
|
|
|
591
596
|
// Map of DependencySpecifier -> Map<ExportedSymbol, Identifier>>
|
|
592
|
-
let external = this.externals.get(
|
|
597
|
+
let external = this.externals.get(specifier);
|
|
593
598
|
if (!external) {
|
|
594
599
|
external = new Map();
|
|
595
|
-
this.externals.set(
|
|
600
|
+
this.externals.set(specifier, external);
|
|
596
601
|
}
|
|
597
602
|
for (let [imported, {
|
|
598
603
|
local
|
|
@@ -609,7 +614,13 @@ ${code}
|
|
|
609
614
|
if (this.bundle.env.outputFormat === 'commonjs') {
|
|
610
615
|
renamed = external.get('*');
|
|
611
616
|
if (!renamed) {
|
|
612
|
-
|
|
617
|
+
if (referencedBundle) {
|
|
618
|
+
var _entry$symbols$get3;
|
|
619
|
+
let entry = (0, _nullthrows().default)(referencedBundle.getMainEntry());
|
|
620
|
+
renamed = ((_entry$symbols$get3 = entry.symbols.get('*')) === null || _entry$symbols$get3 === void 0 ? void 0 : _entry$symbols$get3.local) ?? `$${String(entry.meta.id)}$exports`;
|
|
621
|
+
} else {
|
|
622
|
+
renamed = this.getTopLevelName(`$${this.bundle.publicId}$${specifier}`);
|
|
623
|
+
}
|
|
613
624
|
external.set('*', renamed);
|
|
614
625
|
}
|
|
615
626
|
if (local !== '*' && replacements) {
|
|
@@ -617,40 +628,88 @@ ${code}
|
|
|
617
628
|
if (imported === '*') {
|
|
618
629
|
replacement = renamed;
|
|
619
630
|
} else if (imported === 'default') {
|
|
620
|
-
|
|
621
|
-
|
|
631
|
+
let needsDefaultInterop = true;
|
|
632
|
+
if (referencedBundle) {
|
|
633
|
+
let entry = (0, _nullthrows().default)(referencedBundle.getMainEntry());
|
|
634
|
+
needsDefaultInterop = this.needsDefaultInterop(entry);
|
|
635
|
+
}
|
|
636
|
+
if (needsDefaultInterop) {
|
|
637
|
+
replacement = `($parcel$interopDefault(${renamed}))`;
|
|
638
|
+
this.usedHelpers.add('$parcel$interopDefault');
|
|
639
|
+
} else {
|
|
640
|
+
replacement = `${renamed}.default`;
|
|
641
|
+
}
|
|
622
642
|
} else {
|
|
623
643
|
replacement = this.getPropertyAccess(renamed, imported);
|
|
624
644
|
}
|
|
625
645
|
replacements.set(local, replacement);
|
|
626
646
|
}
|
|
627
647
|
} else {
|
|
648
|
+
let property;
|
|
649
|
+
if (referencedBundle) {
|
|
650
|
+
let entry = (0, _nullthrows().default)(referencedBundle.getMainEntry());
|
|
651
|
+
if (entry.symbols.hasExportSymbol('*')) {
|
|
652
|
+
// If importing * and the referenced module has a * export (e.g. CJS), use default instead.
|
|
653
|
+
// This mirrors the logic in buildExportedSymbols.
|
|
654
|
+
property = imported;
|
|
655
|
+
imported = (referencedBundle === null || referencedBundle === void 0 ? void 0 : referencedBundle.env.outputFormat) === 'esmodule' ? 'default' : '*';
|
|
656
|
+
} else {
|
|
657
|
+
if (imported === '*') {
|
|
658
|
+
let exportedSymbols = this.bundleGraph.getExportedSymbols(entry);
|
|
659
|
+
if (local === '*') {
|
|
660
|
+
// Re-export all symbols.
|
|
661
|
+
for (let exported of exportedSymbols) {
|
|
662
|
+
if (exported.symbol) {
|
|
663
|
+
external.set(exported.exportSymbol, exported.symbol);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
renamed = this.bundleGraph.getSymbolResolution(entry, imported, this.bundle).symbol;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
628
673
|
// Rename the specifier so that multiple local imports of the same imported specifier
|
|
629
674
|
// are deduplicated. We have to prefix the imported name with the bundle id so that
|
|
630
675
|
// local variables do not shadow it.
|
|
631
|
-
if (
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
676
|
+
if (!renamed) {
|
|
677
|
+
if (this.exportedSymbols.has(local)) {
|
|
678
|
+
renamed = local;
|
|
679
|
+
} else if (imported === 'default' || imported === '*') {
|
|
680
|
+
renamed = this.getTopLevelName(`$${this.bundle.publicId}$${specifier}`);
|
|
681
|
+
} else {
|
|
682
|
+
renamed = this.getTopLevelName(`$${this.bundle.publicId}$${imported}`);
|
|
683
|
+
}
|
|
637
684
|
}
|
|
638
685
|
external.set(imported, renamed);
|
|
639
686
|
if (local !== '*' && replacements) {
|
|
640
|
-
|
|
687
|
+
let replacement = renamed;
|
|
688
|
+
if (property === '*') {
|
|
689
|
+
replacement = renamed;
|
|
690
|
+
} else if (property === 'default') {
|
|
691
|
+
replacement = `($parcel$interopDefault(${renamed}))`;
|
|
692
|
+
this.usedHelpers.add('$parcel$interopDefault');
|
|
693
|
+
} else if (property) {
|
|
694
|
+
replacement = this.getPropertyAccess(renamed, property);
|
|
695
|
+
}
|
|
696
|
+
replacements.set(local, replacement);
|
|
641
697
|
}
|
|
642
698
|
}
|
|
643
699
|
}
|
|
644
700
|
}
|
|
645
701
|
isWrapped(resolved, parentAsset) {
|
|
646
702
|
if (resolved.meta.isConstantModule) {
|
|
647
|
-
|
|
703
|
+
if (!this.bundle.hasAsset(resolved)) {
|
|
704
|
+
throw new (_assert().AssertionError)({
|
|
705
|
+
message: `Constant module ${_path().default.relative(this.options.projectRoot, resolved.filePath)} referenced from ${_path().default.relative(this.options.projectRoot, parentAsset.filePath)} not found in bundle ${this.bundle.name}`
|
|
706
|
+
});
|
|
707
|
+
}
|
|
648
708
|
return false;
|
|
649
709
|
}
|
|
650
710
|
return !this.bundle.hasAsset(resolved) && !this.externalAssets.has(resolved) || this.wrappedAssets.has(resolved.id) && resolved !== parentAsset;
|
|
651
711
|
}
|
|
652
|
-
getSymbolResolution(parentAsset, resolved, imported, dep) {
|
|
653
|
-
var _resolvedAsset$symbol;
|
|
712
|
+
getSymbolResolution(parentAsset, resolved, imported, dep, replacements) {
|
|
654
713
|
let {
|
|
655
714
|
asset: resolvedAsset,
|
|
656
715
|
exportSymbol,
|
|
@@ -696,9 +755,17 @@ ${code}
|
|
|
696
755
|
// namespace export symbol.
|
|
697
756
|
let assetId = resolvedAsset.meta.id;
|
|
698
757
|
(0, _assert().default)(typeof assetId === 'string');
|
|
699
|
-
let obj
|
|
700
|
-
|
|
701
|
-
|
|
758
|
+
let obj;
|
|
759
|
+
if (isWrapped && (!dep || dep !== null && dep !== void 0 && dep.meta.shouldWrap)) {
|
|
760
|
+
// Wrap in extra parenthesis to not change semantics, e.g.`new (parcelRequire("..."))()`.
|
|
761
|
+
obj = `(parcelRequire(${JSON.stringify(publicId)}))`;
|
|
762
|
+
} else if (isWrapped && dep) {
|
|
763
|
+
obj = `$${publicId}`;
|
|
764
|
+
} else {
|
|
765
|
+
var _resolvedAsset$symbol;
|
|
766
|
+
obj = ((_resolvedAsset$symbol = resolvedAsset.symbols.get('*')) === null || _resolvedAsset$symbol === void 0 ? void 0 : _resolvedAsset$symbol.local) || `$${assetId}$exports`;
|
|
767
|
+
obj = (replacements === null || replacements === void 0 ? void 0 : replacements.get(obj)) || obj;
|
|
768
|
+
}
|
|
702
769
|
if (imported === '*' || exportSymbol === '*' || isDefaultInterop) {
|
|
703
770
|
// Resolve to the namespace object if requested or this is a CJS default interop reqiure.
|
|
704
771
|
if (parentAsset === resolvedAsset && this.wrappedAssets.has(resolvedAsset.id)) {
|
|
@@ -722,7 +789,7 @@ ${code}
|
|
|
722
789
|
} else if (!symbol) {
|
|
723
790
|
(0, _assert().default)(false, 'Asset was skipped or not found.');
|
|
724
791
|
} else {
|
|
725
|
-
return symbol;
|
|
792
|
+
return (replacements === null || replacements === void 0 ? void 0 : replacements.get(symbol)) || symbol;
|
|
726
793
|
}
|
|
727
794
|
}
|
|
728
795
|
getHoistedParcelRequires(parentAsset, dep, resolved) {
|
|
@@ -749,7 +816,7 @@ ${code}
|
|
|
749
816
|
}
|
|
750
817
|
return [res, lineCount];
|
|
751
818
|
}
|
|
752
|
-
buildAssetPrelude(asset, deps) {
|
|
819
|
+
buildAssetPrelude(asset, deps, replacements) {
|
|
753
820
|
let prepend = '';
|
|
754
821
|
let prependLineCount = 0;
|
|
755
822
|
let append = '';
|
|
@@ -767,13 +834,15 @@ ${code}
|
|
|
767
834
|
// The one case where this isn't true is in ESM library entries, where the only
|
|
768
835
|
// dependency on * is the entry dependency. In this case, we will use ESM exports
|
|
769
836
|
// instead of the namespace object.
|
|
770
|
-
usedSymbols.has('*') && (this.bundle.env.outputFormat !== 'esmodule' || !this.bundle.env.isLibrary || asset !== this.bundle.getMainEntry() || this.bundleGraph.getIncomingDependencies(asset).some(dep => !dep.isEntry && (0, _nullthrows().default)(this.bundleGraph.getUsedSymbols(dep)).has('*'))) ||
|
|
837
|
+
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('*'))) ||
|
|
771
838
|
// If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
|
|
772
839
|
// we fallback on the namespace object.
|
|
773
840
|
asset.symbols.hasExportSymbol('*') && [...usedSymbols].some(s => !asset.symbols.hasExportSymbol(s)) ||
|
|
774
841
|
// If the exports has this asset's namespace (e.g. ESM output from CJS input),
|
|
775
842
|
// include the namespace object for the default export.
|
|
776
|
-
this.exportedSymbols.has(`$${assetId}$exports`)
|
|
843
|
+
this.exportedSymbols.has(`$${assetId}$exports`) ||
|
|
844
|
+
// CommonJS library bundle entries always need a namespace.
|
|
845
|
+
this.bundle.env.isLibrary && this.bundle.env.outputFormat === 'commonjs' && asset === this.bundle.getMainEntry();
|
|
777
846
|
|
|
778
847
|
// If the asset doesn't have static exports, should wrap, the namespace is used,
|
|
779
848
|
// or we need default interop, then we need to synthesize a namespace object for
|
|
@@ -824,7 +893,7 @@ ${code}
|
|
|
824
893
|
if (isWrapped || resolved.meta.staticExports === false || (0, _nullthrows().default)(this.bundleGraph.getUsedSymbols(resolved)).has('*') ||
|
|
825
894
|
// an empty asset
|
|
826
895
|
!resolved.meta.hasCJSExports && resolved.symbols.hasExportSymbol('*')) {
|
|
827
|
-
let obj = this.getSymbolResolution(asset, resolved, '*', dep);
|
|
896
|
+
let obj = this.getSymbolResolution(asset, resolved, '*', dep, replacements);
|
|
828
897
|
append += `$parcel$exportWildcard($${assetId}$exports, ${obj});\n`;
|
|
829
898
|
this.usedHelpers.add('$parcel$exportWildcard');
|
|
830
899
|
} else {
|
|
@@ -834,7 +903,7 @@ ${code}
|
|
|
834
903
|
symbol === '__esModule') {
|
|
835
904
|
continue;
|
|
836
905
|
}
|
|
837
|
-
let resolvedSymbol = this.getSymbolResolution(asset, resolved, symbol);
|
|
906
|
+
let resolvedSymbol = this.getSymbolResolution(asset, resolved, symbol, undefined, replacements);
|
|
838
907
|
let get = this.buildFunctionExpression([], resolvedSymbol);
|
|
839
908
|
let set = asset.meta.hasCJSExports ? ', ' + this.buildFunctionExpression(['v'], `${resolvedSymbol} = v`) : '';
|
|
840
909
|
prepend += `$parcel$export($${assetId}$exports, ${JSON.stringify(symbol)}, ${get}${set});\n`;
|
|
@@ -873,7 +942,7 @@ ${code}
|
|
|
873
942
|
// additional assignments after each mutation of the original binding.
|
|
874
943
|
prepend += `\n${usedExports.map(exp => {
|
|
875
944
|
var _asset$symbols$get2;
|
|
876
|
-
let resolved = this.getSymbolResolution(asset, asset, exp);
|
|
945
|
+
let resolved = this.getSymbolResolution(asset, asset, exp, undefined, replacements);
|
|
877
946
|
let get = this.buildFunctionExpression([], resolved);
|
|
878
947
|
let isEsmExport = !!((_asset$symbols$get2 = asset.symbols.get(exp)) !== null && _asset$symbols$get2 !== void 0 && (_asset$symbols$get2 = _asset$symbols$get2.meta) !== null && _asset$symbols$get2 !== void 0 && _asset$symbols$get2.isEsm);
|
|
879
948
|
let set = !isEsmExport && asset.meta.hasCJSExports ? ', ' + this.buildFunctionExpression(['v'], `${resolved} = v`) : '';
|
package/lib/dev-prelude.js
CHANGED
package/lib/index.js
CHANGED
|
@@ -32,13 +32,6 @@ function _rust() {
|
|
|
32
32
|
};
|
|
33
33
|
return data;
|
|
34
34
|
}
|
|
35
|
-
function _path() {
|
|
36
|
-
const data = _interopRequireDefault(require("path"));
|
|
37
|
-
_path = function () {
|
|
38
|
-
return data;
|
|
39
|
-
};
|
|
40
|
-
return data;
|
|
41
|
-
}
|
|
42
35
|
function _nullthrows() {
|
|
43
36
|
const data = _interopRequireDefault(require("nullthrows"));
|
|
44
37
|
_nullthrows = function () {
|
|
@@ -48,7 +41,7 @@ function _nullthrows() {
|
|
|
48
41
|
}
|
|
49
42
|
var _DevPackager = require("./DevPackager");
|
|
50
43
|
var _ScopeHoistingPackager = require("./ScopeHoistingPackager");
|
|
51
|
-
function _interopRequireDefault(
|
|
44
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
52
45
|
const CONFIG_SCHEMA = {
|
|
53
46
|
type: 'object',
|
|
54
47
|
properties: {
|
|
@@ -63,23 +56,29 @@ var _default = exports.default = new (_plugin().Packager)({
|
|
|
63
56
|
config,
|
|
64
57
|
options
|
|
65
58
|
}) {
|
|
66
|
-
var
|
|
67
|
-
// Generate a name for the global parcelRequire function that is unique to this project.
|
|
68
|
-
// This allows multiple parcel builds to coexist on the same page.
|
|
69
|
-
let pkg = await config.getConfigFrom(_path().default.join(options.projectRoot, 'index'), ['package.json']);
|
|
59
|
+
var _packageName$contents, _conf$contents;
|
|
70
60
|
let packageKey = '@parcel/packager-js';
|
|
71
|
-
|
|
61
|
+
let conf = await config.getConfigFrom(options.projectRoot + '/index', [], {
|
|
62
|
+
packageKey
|
|
63
|
+
});
|
|
64
|
+
if (conf !== null && conf !== void 0 && conf.contents) {
|
|
72
65
|
_utils().validateSchema.diagnostic(CONFIG_SCHEMA, {
|
|
73
|
-
data:
|
|
74
|
-
source: await options.inputFS.readFile(
|
|
75
|
-
filePath:
|
|
66
|
+
data: conf === null || conf === void 0 ? void 0 : conf.contents,
|
|
67
|
+
source: await options.inputFS.readFile(conf.filePath, 'utf8'),
|
|
68
|
+
filePath: conf.filePath,
|
|
76
69
|
prependKey: `/${(0, _diagnostic().encodeJSONKeyComponent)(packageKey)}`
|
|
77
70
|
}, packageKey, `Invalid config for ${packageKey}`);
|
|
78
71
|
}
|
|
79
|
-
|
|
72
|
+
|
|
73
|
+
// Generate a name for the global parcelRequire function that is unique to this project.
|
|
74
|
+
// This allows multiple parcel builds to coexist on the same page.
|
|
75
|
+
let packageName = await config.getConfigFrom(options.projectRoot + '/index', [], {
|
|
76
|
+
packageKey: 'name'
|
|
77
|
+
});
|
|
78
|
+
let name = (packageName === null || packageName === void 0 || (_packageName$contents = packageName.contents) === null || _packageName$contents === void 0 ? void 0 : _packageName$contents.name) ?? '';
|
|
80
79
|
return {
|
|
81
80
|
parcelRequireName: 'parcelRequire' + (0, _rust().hashString)(name).slice(-4),
|
|
82
|
-
unstable_asyncBundleRuntime: Boolean(
|
|
81
|
+
unstable_asyncBundleRuntime: Boolean(conf === null || conf === void 0 || (_conf$contents = conf.contents) === null || _conf$contents === void 0 ? void 0 : _conf$contents.unstable_asyncBundleRuntime)
|
|
83
82
|
};
|
|
84
83
|
},
|
|
85
84
|
async package({
|
package/lib/utils.js
CHANGED
|
@@ -4,6 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getSpecifier = getSpecifier;
|
|
7
|
+
exports.isValidIdentifier = isValidIdentifier;
|
|
8
|
+
exports.makeValidIdentifier = makeValidIdentifier;
|
|
7
9
|
exports.replaceScriptDependencies = replaceScriptDependencies;
|
|
8
10
|
function _nullthrows() {
|
|
9
11
|
const data = _interopRequireDefault(require("nullthrows"));
|
|
@@ -12,7 +14,7 @@ function _nullthrows() {
|
|
|
12
14
|
};
|
|
13
15
|
return data;
|
|
14
16
|
}
|
|
15
|
-
function _interopRequireDefault(
|
|
17
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
18
|
// This replaces __parcel__require__ references left by the transformer with
|
|
17
19
|
// parcelRequire calls of the resolved asset id. This lets runtimes work within
|
|
18
20
|
// script bundles, which must be outside the bundle wrapper so their variables are global.
|
|
@@ -48,4 +50,19 @@ function getSpecifier(dep) {
|
|
|
48
50
|
return dep.meta.placeholder;
|
|
49
51
|
}
|
|
50
52
|
return dep.specifier;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// https://262.ecma-international.org/6.0/#sec-names-and-keywords
|
|
56
|
+
const IDENTIFIER_RE = /^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*$/u;
|
|
57
|
+
const ID_START_RE = /^[$_\p{ID_Start}]/u;
|
|
58
|
+
const NON_ID_CONTINUE_RE = /[^$_\u200C\u200D\p{ID_Continue}]/gu;
|
|
59
|
+
function isValidIdentifier(id) {
|
|
60
|
+
return IDENTIFIER_RE.test(id);
|
|
61
|
+
}
|
|
62
|
+
function makeValidIdentifier(name) {
|
|
63
|
+
name = name.replace(NON_ID_CONTINUE_RE, '');
|
|
64
|
+
if (!ID_START_RE.test(name)) {
|
|
65
|
+
name = '_' + name;
|
|
66
|
+
}
|
|
67
|
+
return name;
|
|
51
68
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parcel/packager-js",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -16,18 +16,18 @@
|
|
|
16
16
|
"main": "lib/index.js",
|
|
17
17
|
"source": "src/index.js",
|
|
18
18
|
"engines": {
|
|
19
|
-
"node": ">=
|
|
20
|
-
"parcel": "^2.
|
|
19
|
+
"node": ">= 16.0.0",
|
|
20
|
+
"parcel": "^2.13.0"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@parcel/diagnostic": "2.
|
|
24
|
-
"@parcel/plugin": "2.
|
|
25
|
-
"@parcel/rust": "2.
|
|
23
|
+
"@parcel/diagnostic": "2.13.0",
|
|
24
|
+
"@parcel/plugin": "2.13.0",
|
|
25
|
+
"@parcel/rust": "2.13.0",
|
|
26
26
|
"@parcel/source-map": "^2.1.1",
|
|
27
|
-
"@parcel/types": "2.
|
|
28
|
-
"@parcel/utils": "2.
|
|
27
|
+
"@parcel/types": "2.13.0",
|
|
28
|
+
"@parcel/utils": "2.13.0",
|
|
29
29
|
"globals": "^13.2.0",
|
|
30
30
|
"nullthrows": "^1.1.1"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "a53f8f3ba1025c7ea8653e9719e0a61ef9717079"
|
|
33
33
|
}
|
package/src/DevPackager.js
CHANGED
|
@@ -101,14 +101,14 @@ export class DevPackager {
|
|
|
101
101
|
let dependencies = this.bundleGraph.getDependencies(asset);
|
|
102
102
|
for (let dep of dependencies) {
|
|
103
103
|
let resolved = this.bundleGraph.getResolvedAsset(dep, this.bundle);
|
|
104
|
+
let specifier = getSpecifier(dep);
|
|
104
105
|
if (this.bundleGraph.isDependencySkipped(dep)) {
|
|
105
|
-
deps[
|
|
106
|
+
deps[specifier] = false;
|
|
106
107
|
} else if (resolved) {
|
|
107
|
-
deps[
|
|
108
|
-
this.bundleGraph.getAssetPublicId(resolved);
|
|
108
|
+
deps[specifier] = this.bundleGraph.getAssetPublicId(resolved);
|
|
109
109
|
} else {
|
|
110
110
|
// An external module - map placeholder to original specifier.
|
|
111
|
-
deps[
|
|
111
|
+
deps[specifier] = dep.specifier;
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
@@ -116,7 +116,7 @@ export class DevPackager {
|
|
|
116
116
|
let output = code || '';
|
|
117
117
|
wrapped +=
|
|
118
118
|
JSON.stringify(this.bundleGraph.getAssetPublicId(asset)) +
|
|
119
|
-
':[function(require,module,exports) {\n' +
|
|
119
|
+
':[function(require,module,exports,__globalThis) {\n' +
|
|
120
120
|
output +
|
|
121
121
|
'\n},';
|
|
122
122
|
wrapped += JSON.stringify(deps);
|
package/src/ESMOutputFormat.js
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
ScopeHoistingPackager,
|
|
4
4
|
OutputFormat,
|
|
5
5
|
} from './ScopeHoistingPackager';
|
|
6
|
+
import {isValidIdentifier} from './utils';
|
|
6
7
|
|
|
7
8
|
export class ESMOutputFormat implements OutputFormat {
|
|
8
9
|
packager: ScopeHoistingPackager;
|
|
@@ -25,6 +26,9 @@ export class ESMOutputFormat implements OutputFormat {
|
|
|
25
26
|
namespaceSpecifier = `* as ${symbol}`;
|
|
26
27
|
} else {
|
|
27
28
|
let specifier = imported;
|
|
29
|
+
if (!isValidIdentifier(specifier)) {
|
|
30
|
+
specifier = JSON.stringify(specifier);
|
|
31
|
+
}
|
|
28
32
|
if (symbol !== imported) {
|
|
29
33
|
specifier += ` as ${symbol}`;
|
|
30
34
|
}
|
|
@@ -93,7 +97,10 @@ export class ESMOutputFormat implements OutputFormat {
|
|
|
93
97
|
|
|
94
98
|
for (let as of exportAs) {
|
|
95
99
|
let specifier = local;
|
|
96
|
-
if (
|
|
100
|
+
if (as !== local) {
|
|
101
|
+
if (!isValidIdentifier(as)) {
|
|
102
|
+
as = JSON.stringify(as);
|
|
103
|
+
}
|
|
97
104
|
specifier += ` as ${as}`;
|
|
98
105
|
}
|
|
99
106
|
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
} from '@parcel/utils';
|
|
18
18
|
import SourceMap from '@parcel/source-map';
|
|
19
19
|
import nullthrows from 'nullthrows';
|
|
20
|
-
import invariant from 'assert';
|
|
20
|
+
import invariant, {AssertionError} from 'assert';
|
|
21
21
|
import ThrowableDiagnostic, {
|
|
22
22
|
convertSourceLocationToHighlight,
|
|
23
23
|
} from '@parcel/diagnostic';
|
|
@@ -28,13 +28,12 @@ import {ESMOutputFormat} from './ESMOutputFormat';
|
|
|
28
28
|
import {CJSOutputFormat} from './CJSOutputFormat';
|
|
29
29
|
import {GlobalOutputFormat} from './GlobalOutputFormat';
|
|
30
30
|
import {prelude, helpers, bundleQueuePrelude, fnExpr} from './helpers';
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
import {
|
|
32
|
+
replaceScriptDependencies,
|
|
33
|
+
getSpecifier,
|
|
34
|
+
isValidIdentifier,
|
|
35
|
+
makeValidIdentifier,
|
|
36
|
+
} from './utils';
|
|
38
37
|
// General regex used to replace imports with the resolved code, references with resolutions,
|
|
39
38
|
// and count the number of newlines in the file for source maps.
|
|
40
39
|
const REPLACEMENT_RE =
|
|
@@ -134,25 +133,10 @@ export class ScopeHoistingPackager {
|
|
|
134
133
|
this.bundle.env.isLibrary ||
|
|
135
134
|
this.bundle.env.outputFormat === 'commonjs'
|
|
136
135
|
) {
|
|
137
|
-
for (let b of this.bundleGraph.getReferencedBundles(this.bundle
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
this.externalAssets.add(entry);
|
|
142
|
-
|
|
143
|
-
let usedSymbols = this.bundleGraph.getUsedSymbols(entry) || new Set();
|
|
144
|
-
for (let s of usedSymbols) {
|
|
145
|
-
// If the referenced bundle is ESM, and we are importing '*', use 'default' instead.
|
|
146
|
-
// This matches the logic below in buildExportedSymbols.
|
|
147
|
-
let imported = s;
|
|
148
|
-
if (imported === '*' && b.env.outputFormat === 'esmodule') {
|
|
149
|
-
imported = 'default';
|
|
150
|
-
}
|
|
151
|
-
symbols.set(imported, this.getSymbolResolution(entry, entry, s));
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
this.externals.set(relativeBundlePath(this.bundle, b), symbols);
|
|
136
|
+
for (let b of this.bundleGraph.getReferencedBundles(this.bundle, {
|
|
137
|
+
recursive: false,
|
|
138
|
+
})) {
|
|
139
|
+
this.externals.set(relativeBundlePath(this.bundle, b), new Map());
|
|
156
140
|
}
|
|
157
141
|
}
|
|
158
142
|
|
|
@@ -279,6 +263,9 @@ export class ScopeHoistingPackager {
|
|
|
279
263
|
}
|
|
280
264
|
|
|
281
265
|
shouldBundleQueue(bundle: NamedBundle): boolean {
|
|
266
|
+
let referencingBundles = this.bundleGraph.getReferencingBundles(bundle);
|
|
267
|
+
let hasHtmlReference = referencingBundles.some(b => b.type === 'html');
|
|
268
|
+
|
|
282
269
|
return (
|
|
283
270
|
this.useAsyncBundleRuntime &&
|
|
284
271
|
bundle.type === 'js' &&
|
|
@@ -286,7 +273,7 @@ export class ScopeHoistingPackager {
|
|
|
286
273
|
bundle.env.outputFormat === 'esmodule' &&
|
|
287
274
|
!bundle.env.isIsolated() &&
|
|
288
275
|
bundle.bundleBehavior !== 'isolated' &&
|
|
289
|
-
|
|
276
|
+
hasHtmlReference
|
|
290
277
|
);
|
|
291
278
|
}
|
|
292
279
|
|
|
@@ -324,14 +311,19 @@ export class ScopeHoistingPackager {
|
|
|
324
311
|
|
|
325
312
|
if (
|
|
326
313
|
asset.meta.shouldWrap ||
|
|
327
|
-
this.isAsyncBundle ||
|
|
328
314
|
this.bundle.env.sourceType === 'script' ||
|
|
329
315
|
this.bundleGraph.isAssetReferenced(this.bundle, asset) ||
|
|
330
316
|
this.bundleGraph
|
|
331
317
|
.getIncomingDependencies(asset)
|
|
332
318
|
.some(dep => dep.meta.shouldWrap && dep.specifierType !== 'url')
|
|
333
319
|
) {
|
|
334
|
-
if
|
|
320
|
+
// Don't wrap constant "entry" modules _except_ if they are referenced by any lazy dependency
|
|
321
|
+
if (
|
|
322
|
+
!asset.meta.isConstantModule ||
|
|
323
|
+
this.bundleGraph
|
|
324
|
+
.getIncomingDependencies(asset)
|
|
325
|
+
.some(dep => dep.priority === 'lazy')
|
|
326
|
+
) {
|
|
335
327
|
this.wrappedAssets.add(asset.id);
|
|
336
328
|
wrapped.push(asset);
|
|
337
329
|
}
|
|
@@ -361,7 +353,6 @@ export class ScopeHoistingPackager {
|
|
|
361
353
|
|
|
362
354
|
buildExportedSymbols() {
|
|
363
355
|
if (
|
|
364
|
-
this.isAsyncBundle ||
|
|
365
356
|
!this.bundle.env.isLibrary ||
|
|
366
357
|
this.bundle.env.outputFormat !== 'esmodule'
|
|
367
358
|
) {
|
|
@@ -371,6 +362,8 @@ export class ScopeHoistingPackager {
|
|
|
371
362
|
// TODO: handle ESM exports of wrapped entry assets...
|
|
372
363
|
let entry = this.bundle.getMainEntry();
|
|
373
364
|
if (entry && !this.wrappedAssets.has(entry.id)) {
|
|
365
|
+
let hasNamespace = entry.symbols.hasExportSymbol('*');
|
|
366
|
+
|
|
374
367
|
for (let {
|
|
375
368
|
asset,
|
|
376
369
|
exportAs,
|
|
@@ -378,6 +371,13 @@ export class ScopeHoistingPackager {
|
|
|
378
371
|
exportSymbol,
|
|
379
372
|
} of this.bundleGraph.getExportedSymbols(entry)) {
|
|
380
373
|
if (typeof symbol === 'string') {
|
|
374
|
+
// If the module has a namespace (e.g. commonjs), and this is not an entry, only export the namespace
|
|
375
|
+
// as default, without individual exports. This mirrors the importing logic in addExternal, avoiding
|
|
376
|
+
// extra unused exports and potential for non-identifier export names.
|
|
377
|
+
if (hasNamespace && this.isAsyncBundle && exportAs !== '*') {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
381
|
let symbols = this.exportedSymbols.get(
|
|
382
382
|
symbol === '*' ? nullthrows(entry.symbols.get('*')?.local) : symbol,
|
|
383
383
|
)?.exportAs;
|
|
@@ -418,8 +418,8 @@ export class ScopeHoistingPackager {
|
|
|
418
418
|
}
|
|
419
419
|
|
|
420
420
|
getTopLevelName(name: string): string {
|
|
421
|
-
name = name
|
|
422
|
-
if (
|
|
421
|
+
name = makeValidIdentifier(name);
|
|
422
|
+
if (this.globalNames.has(name)) {
|
|
423
423
|
name = '_' + name;
|
|
424
424
|
}
|
|
425
425
|
|
|
@@ -434,7 +434,7 @@ export class ScopeHoistingPackager {
|
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
getPropertyAccess(obj: string, property: string): string {
|
|
437
|
-
if (
|
|
437
|
+
if (isValidIdentifier(property)) {
|
|
438
438
|
return `${obj}.${property}`;
|
|
439
439
|
}
|
|
440
440
|
|
|
@@ -511,7 +511,11 @@ export class ScopeHoistingPackager {
|
|
|
511
511
|
}
|
|
512
512
|
|
|
513
513
|
let [depMap, replacements] = this.buildReplacements(asset, deps);
|
|
514
|
-
let [prepend, prependLines, append] = this.buildAssetPrelude(
|
|
514
|
+
let [prepend, prependLines, append] = this.buildAssetPrelude(
|
|
515
|
+
asset,
|
|
516
|
+
deps,
|
|
517
|
+
replacements,
|
|
518
|
+
);
|
|
515
519
|
if (prependLines > 0) {
|
|
516
520
|
sourceMap?.offsetLines(1, prependLines);
|
|
517
521
|
code = prepend + code;
|
|
@@ -703,6 +707,24 @@ ${code}
|
|
|
703
707
|
continue;
|
|
704
708
|
}
|
|
705
709
|
|
|
710
|
+
// Handle imports from other bundles in libraries.
|
|
711
|
+
if (this.bundle.env.isLibrary && !this.bundle.hasAsset(resolved)) {
|
|
712
|
+
let referencedBundle = this.bundleGraph.getReferencedBundle(
|
|
713
|
+
dep,
|
|
714
|
+
this.bundle,
|
|
715
|
+
);
|
|
716
|
+
if (
|
|
717
|
+
referencedBundle &&
|
|
718
|
+
referencedBundle.getMainEntry() === resolved &&
|
|
719
|
+
referencedBundle.type === 'js' &&
|
|
720
|
+
!this.bundleGraph.isAssetReferenced(referencedBundle, resolved)
|
|
721
|
+
) {
|
|
722
|
+
this.addExternal(dep, replacements, referencedBundle);
|
|
723
|
+
this.externalAssets.add(resolved);
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
706
728
|
for (let [imported, {local}] of dep.symbols) {
|
|
707
729
|
if (local === '*') {
|
|
708
730
|
continue;
|
|
@@ -748,7 +770,11 @@ ${code}
|
|
|
748
770
|
return [depMap, replacements];
|
|
749
771
|
}
|
|
750
772
|
|
|
751
|
-
addExternal(
|
|
773
|
+
addExternal(
|
|
774
|
+
dep: Dependency,
|
|
775
|
+
replacements?: Map<string, string>,
|
|
776
|
+
referencedBundle?: NamedBundle,
|
|
777
|
+
) {
|
|
752
778
|
if (this.bundle.env.outputFormat === 'global') {
|
|
753
779
|
throw new ThrowableDiagnostic({
|
|
754
780
|
diagnostic: {
|
|
@@ -766,11 +792,16 @@ ${code}
|
|
|
766
792
|
});
|
|
767
793
|
}
|
|
768
794
|
|
|
795
|
+
let specifier = dep.specifier;
|
|
796
|
+
if (referencedBundle) {
|
|
797
|
+
specifier = relativeBundlePath(this.bundle, referencedBundle);
|
|
798
|
+
}
|
|
799
|
+
|
|
769
800
|
// Map of DependencySpecifier -> Map<ExportedSymbol, Identifier>>
|
|
770
|
-
let external = this.externals.get(
|
|
801
|
+
let external = this.externals.get(specifier);
|
|
771
802
|
if (!external) {
|
|
772
803
|
external = new Map();
|
|
773
|
-
this.externals.set(
|
|
804
|
+
this.externals.set(specifier, external);
|
|
774
805
|
}
|
|
775
806
|
|
|
776
807
|
for (let [imported, {local}] of dep.symbols) {
|
|
@@ -786,9 +817,16 @@ ${code}
|
|
|
786
817
|
if (this.bundle.env.outputFormat === 'commonjs') {
|
|
787
818
|
renamed = external.get('*');
|
|
788
819
|
if (!renamed) {
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
820
|
+
if (referencedBundle) {
|
|
821
|
+
let entry = nullthrows(referencedBundle.getMainEntry());
|
|
822
|
+
renamed =
|
|
823
|
+
entry.symbols.get('*')?.local ??
|
|
824
|
+
`$${String(entry.meta.id)}$exports`;
|
|
825
|
+
} else {
|
|
826
|
+
renamed = this.getTopLevelName(
|
|
827
|
+
`$${this.bundle.publicId}$${specifier}`,
|
|
828
|
+
);
|
|
829
|
+
}
|
|
792
830
|
|
|
793
831
|
external.set('*', renamed);
|
|
794
832
|
}
|
|
@@ -798,8 +836,17 @@ ${code}
|
|
|
798
836
|
if (imported === '*') {
|
|
799
837
|
replacement = renamed;
|
|
800
838
|
} else if (imported === 'default') {
|
|
801
|
-
|
|
802
|
-
|
|
839
|
+
let needsDefaultInterop = true;
|
|
840
|
+
if (referencedBundle) {
|
|
841
|
+
let entry = nullthrows(referencedBundle.getMainEntry());
|
|
842
|
+
needsDefaultInterop = this.needsDefaultInterop(entry);
|
|
843
|
+
}
|
|
844
|
+
if (needsDefaultInterop) {
|
|
845
|
+
replacement = `($parcel$interopDefault(${renamed}))`;
|
|
846
|
+
this.usedHelpers.add('$parcel$interopDefault');
|
|
847
|
+
} else {
|
|
848
|
+
replacement = `${renamed}.default`;
|
|
849
|
+
}
|
|
803
850
|
} else {
|
|
804
851
|
replacement = this.getPropertyAccess(renamed, imported);
|
|
805
852
|
}
|
|
@@ -807,24 +854,67 @@ ${code}
|
|
|
807
854
|
replacements.set(local, replacement);
|
|
808
855
|
}
|
|
809
856
|
} else {
|
|
857
|
+
let property;
|
|
858
|
+
if (referencedBundle) {
|
|
859
|
+
let entry = nullthrows(referencedBundle.getMainEntry());
|
|
860
|
+
if (entry.symbols.hasExportSymbol('*')) {
|
|
861
|
+
// If importing * and the referenced module has a * export (e.g. CJS), use default instead.
|
|
862
|
+
// This mirrors the logic in buildExportedSymbols.
|
|
863
|
+
property = imported;
|
|
864
|
+
imported =
|
|
865
|
+
referencedBundle?.env.outputFormat === 'esmodule'
|
|
866
|
+
? 'default'
|
|
867
|
+
: '*';
|
|
868
|
+
} else {
|
|
869
|
+
if (imported === '*') {
|
|
870
|
+
let exportedSymbols = this.bundleGraph.getExportedSymbols(entry);
|
|
871
|
+
if (local === '*') {
|
|
872
|
+
// Re-export all symbols.
|
|
873
|
+
for (let exported of exportedSymbols) {
|
|
874
|
+
if (exported.symbol) {
|
|
875
|
+
external.set(exported.exportSymbol, exported.symbol);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
renamed = this.bundleGraph.getSymbolResolution(
|
|
882
|
+
entry,
|
|
883
|
+
imported,
|
|
884
|
+
this.bundle,
|
|
885
|
+
).symbol;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
|
|
810
889
|
// Rename the specifier so that multiple local imports of the same imported specifier
|
|
811
890
|
// are deduplicated. We have to prefix the imported name with the bundle id so that
|
|
812
891
|
// local variables do not shadow it.
|
|
813
|
-
if (
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
892
|
+
if (!renamed) {
|
|
893
|
+
if (this.exportedSymbols.has(local)) {
|
|
894
|
+
renamed = local;
|
|
895
|
+
} else if (imported === 'default' || imported === '*') {
|
|
896
|
+
renamed = this.getTopLevelName(
|
|
897
|
+
`$${this.bundle.publicId}$${specifier}`,
|
|
898
|
+
);
|
|
899
|
+
} else {
|
|
900
|
+
renamed = this.getTopLevelName(
|
|
901
|
+
`$${this.bundle.publicId}$${imported}`,
|
|
902
|
+
);
|
|
903
|
+
}
|
|
823
904
|
}
|
|
824
905
|
|
|
825
906
|
external.set(imported, renamed);
|
|
826
907
|
if (local !== '*' && replacements) {
|
|
827
|
-
|
|
908
|
+
let replacement = renamed;
|
|
909
|
+
if (property === '*') {
|
|
910
|
+
replacement = renamed;
|
|
911
|
+
} else if (property === 'default') {
|
|
912
|
+
replacement = `($parcel$interopDefault(${renamed}))`;
|
|
913
|
+
this.usedHelpers.add('$parcel$interopDefault');
|
|
914
|
+
} else if (property) {
|
|
915
|
+
replacement = this.getPropertyAccess(renamed, property);
|
|
916
|
+
}
|
|
917
|
+
replacements.set(local, replacement);
|
|
828
918
|
}
|
|
829
919
|
}
|
|
830
920
|
}
|
|
@@ -832,10 +922,17 @@ ${code}
|
|
|
832
922
|
|
|
833
923
|
isWrapped(resolved: Asset, parentAsset: Asset): boolean {
|
|
834
924
|
if (resolved.meta.isConstantModule) {
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
925
|
+
if (!this.bundle.hasAsset(resolved)) {
|
|
926
|
+
throw new AssertionError({
|
|
927
|
+
message: `Constant module ${path.relative(
|
|
928
|
+
this.options.projectRoot,
|
|
929
|
+
resolved.filePath,
|
|
930
|
+
)} referenced from ${path.relative(
|
|
931
|
+
this.options.projectRoot,
|
|
932
|
+
parentAsset.filePath,
|
|
933
|
+
)} not found in bundle ${this.bundle.name}`,
|
|
934
|
+
});
|
|
935
|
+
}
|
|
839
936
|
return false;
|
|
840
937
|
}
|
|
841
938
|
return (
|
|
@@ -849,6 +946,7 @@ ${code}
|
|
|
849
946
|
resolved: Asset,
|
|
850
947
|
imported: string,
|
|
851
948
|
dep?: Dependency,
|
|
949
|
+
replacements?: Map<string, string>,
|
|
852
950
|
): string {
|
|
853
951
|
let {
|
|
854
952
|
asset: resolvedAsset,
|
|
@@ -922,13 +1020,16 @@ ${code}
|
|
|
922
1020
|
// namespace export symbol.
|
|
923
1021
|
let assetId = resolvedAsset.meta.id;
|
|
924
1022
|
invariant(typeof assetId === 'string');
|
|
925
|
-
let obj
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
1023
|
+
let obj;
|
|
1024
|
+
if (isWrapped && (!dep || dep?.meta.shouldWrap)) {
|
|
1025
|
+
// Wrap in extra parenthesis to not change semantics, e.g.`new (parcelRequire("..."))()`.
|
|
1026
|
+
obj = `(parcelRequire(${JSON.stringify(publicId)}))`;
|
|
1027
|
+
} else if (isWrapped && dep) {
|
|
1028
|
+
obj = `$${publicId}`;
|
|
1029
|
+
} else {
|
|
1030
|
+
obj = resolvedAsset.symbols.get('*')?.local || `$${assetId}$exports`;
|
|
1031
|
+
obj = replacements?.get(obj) || obj;
|
|
1032
|
+
}
|
|
932
1033
|
|
|
933
1034
|
if (imported === '*' || exportSymbol === '*' || isDefaultInterop) {
|
|
934
1035
|
// Resolve to the namespace object if requested or this is a CJS default interop reqiure.
|
|
@@ -964,7 +1065,7 @@ ${code}
|
|
|
964
1065
|
} else if (!symbol) {
|
|
965
1066
|
invariant(false, 'Asset was skipped or not found.');
|
|
966
1067
|
} else {
|
|
967
|
-
return symbol;
|
|
1068
|
+
return replacements?.get(symbol) || symbol;
|
|
968
1069
|
}
|
|
969
1070
|
}
|
|
970
1071
|
|
|
@@ -1011,6 +1112,7 @@ ${code}
|
|
|
1011
1112
|
buildAssetPrelude(
|
|
1012
1113
|
asset: Asset,
|
|
1013
1114
|
deps: Array<Dependency>,
|
|
1115
|
+
replacements: Map<string, string>,
|
|
1014
1116
|
): [string, number, string] {
|
|
1015
1117
|
let prepend = '';
|
|
1016
1118
|
let prependLineCount = 0;
|
|
@@ -1043,6 +1145,7 @@ ${code}
|
|
|
1043
1145
|
.some(
|
|
1044
1146
|
dep =>
|
|
1045
1147
|
!dep.isEntry &&
|
|
1148
|
+
this.bundle.hasDependency(dep) &&
|
|
1046
1149
|
nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
|
|
1047
1150
|
))) ||
|
|
1048
1151
|
// If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
|
|
@@ -1051,7 +1154,11 @@ ${code}
|
|
|
1051
1154
|
[...usedSymbols].some(s => !asset.symbols.hasExportSymbol(s))) ||
|
|
1052
1155
|
// If the exports has this asset's namespace (e.g. ESM output from CJS input),
|
|
1053
1156
|
// include the namespace object for the default export.
|
|
1054
|
-
this.exportedSymbols.has(`$${assetId}$exports`)
|
|
1157
|
+
this.exportedSymbols.has(`$${assetId}$exports`) ||
|
|
1158
|
+
// CommonJS library bundle entries always need a namespace.
|
|
1159
|
+
(this.bundle.env.isLibrary &&
|
|
1160
|
+
this.bundle.env.outputFormat === 'commonjs' &&
|
|
1161
|
+
asset === this.bundle.getMainEntry());
|
|
1055
1162
|
|
|
1056
1163
|
// If the asset doesn't have static exports, should wrap, the namespace is used,
|
|
1057
1164
|
// or we need default interop, then we need to synthesize a namespace object for
|
|
@@ -1118,7 +1225,13 @@ ${code}
|
|
|
1118
1225
|
(!resolved.meta.hasCJSExports &&
|
|
1119
1226
|
resolved.symbols.hasExportSymbol('*'))
|
|
1120
1227
|
) {
|
|
1121
|
-
let obj = this.getSymbolResolution(
|
|
1228
|
+
let obj = this.getSymbolResolution(
|
|
1229
|
+
asset,
|
|
1230
|
+
resolved,
|
|
1231
|
+
'*',
|
|
1232
|
+
dep,
|
|
1233
|
+
replacements,
|
|
1234
|
+
);
|
|
1122
1235
|
append += `$parcel$exportWildcard($${assetId}$exports, ${obj});\n`;
|
|
1123
1236
|
this.usedHelpers.add('$parcel$exportWildcard');
|
|
1124
1237
|
} else {
|
|
@@ -1136,6 +1249,8 @@ ${code}
|
|
|
1136
1249
|
asset,
|
|
1137
1250
|
resolved,
|
|
1138
1251
|
symbol,
|
|
1252
|
+
undefined,
|
|
1253
|
+
replacements,
|
|
1139
1254
|
);
|
|
1140
1255
|
let get = this.buildFunctionExpression([], resolvedSymbol);
|
|
1141
1256
|
let set = asset.meta.hasCJSExports
|
|
@@ -1182,7 +1297,13 @@ ${code}
|
|
|
1182
1297
|
// additional assignments after each mutation of the original binding.
|
|
1183
1298
|
prepend += `\n${usedExports
|
|
1184
1299
|
.map(exp => {
|
|
1185
|
-
let resolved = this.getSymbolResolution(
|
|
1300
|
+
let resolved = this.getSymbolResolution(
|
|
1301
|
+
asset,
|
|
1302
|
+
asset,
|
|
1303
|
+
exp,
|
|
1304
|
+
undefined,
|
|
1305
|
+
replacements,
|
|
1306
|
+
);
|
|
1186
1307
|
let get = this.buildFunctionExpression([], resolved);
|
|
1187
1308
|
let isEsmExport = !!asset.symbols.get(exp)?.meta?.isEsm;
|
|
1188
1309
|
let set =
|
package/src/dev-prelude.js
CHANGED
package/src/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
} from '@parcel/utils';
|
|
11
11
|
import {encodeJSONKeyComponent} from '@parcel/diagnostic';
|
|
12
12
|
import {hashString} from '@parcel/rust';
|
|
13
|
-
import path from 'path';
|
|
14
13
|
import nullthrows from 'nullthrows';
|
|
15
14
|
import {DevPackager} from './DevPackager';
|
|
16
15
|
import {ScopeHoistingPackager} from './ScopeHoistingPackager';
|
|
@@ -32,22 +31,18 @@ const CONFIG_SCHEMA: SchemaEntity = {
|
|
|
32
31
|
|
|
33
32
|
export default (new Packager({
|
|
34
33
|
async loadConfig({config, options}): Promise<JSPackagerConfig> {
|
|
35
|
-
// Generate a name for the global parcelRequire function that is unique to this project.
|
|
36
|
-
// This allows multiple parcel builds to coexist on the same page.
|
|
37
|
-
let pkg = await config.getConfigFrom(
|
|
38
|
-
path.join(options.projectRoot, 'index'),
|
|
39
|
-
['package.json'],
|
|
40
|
-
);
|
|
41
|
-
|
|
42
34
|
let packageKey = '@parcel/packager-js';
|
|
35
|
+
let conf = await config.getConfigFrom(options.projectRoot + '/index', [], {
|
|
36
|
+
packageKey,
|
|
37
|
+
});
|
|
43
38
|
|
|
44
|
-
if (
|
|
39
|
+
if (conf?.contents) {
|
|
45
40
|
validateSchema.diagnostic(
|
|
46
41
|
CONFIG_SCHEMA,
|
|
47
42
|
{
|
|
48
|
-
data:
|
|
49
|
-
source: await options.inputFS.readFile(
|
|
50
|
-
filePath:
|
|
43
|
+
data: conf?.contents,
|
|
44
|
+
source: await options.inputFS.readFile(conf.filePath, 'utf8'),
|
|
45
|
+
filePath: conf.filePath,
|
|
51
46
|
prependKey: `/${encodeJSONKeyComponent(packageKey)}`,
|
|
52
47
|
},
|
|
53
48
|
packageKey,
|
|
@@ -55,11 +50,21 @@ export default (new Packager({
|
|
|
55
50
|
);
|
|
56
51
|
}
|
|
57
52
|
|
|
58
|
-
|
|
53
|
+
// Generate a name for the global parcelRequire function that is unique to this project.
|
|
54
|
+
// This allows multiple parcel builds to coexist on the same page.
|
|
55
|
+
let packageName = await config.getConfigFrom(
|
|
56
|
+
options.projectRoot + '/index',
|
|
57
|
+
[],
|
|
58
|
+
{
|
|
59
|
+
packageKey: 'name',
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
let name = packageName?.contents?.name ?? '';
|
|
59
64
|
return {
|
|
60
65
|
parcelRequireName: 'parcelRequire' + hashString(name).slice(-4),
|
|
61
66
|
unstable_asyncBundleRuntime: Boolean(
|
|
62
|
-
|
|
67
|
+
conf?.contents?.unstable_asyncBundleRuntime,
|
|
63
68
|
),
|
|
64
69
|
};
|
|
65
70
|
},
|
package/src/utils.js
CHANGED
|
@@ -55,3 +55,20 @@ export function getSpecifier(dep: Dependency): string {
|
|
|
55
55
|
|
|
56
56
|
return dep.specifier;
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
// https://262.ecma-international.org/6.0/#sec-names-and-keywords
|
|
60
|
+
const IDENTIFIER_RE = /^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*$/u;
|
|
61
|
+
const ID_START_RE = /^[$_\p{ID_Start}]/u;
|
|
62
|
+
const NON_ID_CONTINUE_RE = /[^$_\u200C\u200D\p{ID_Continue}]/gu;
|
|
63
|
+
|
|
64
|
+
export function isValidIdentifier(id: string): boolean {
|
|
65
|
+
return IDENTIFIER_RE.test(id);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function makeValidIdentifier(name: string): string {
|
|
69
|
+
name = name.replace(NON_ID_CONTINUE_RE, '');
|
|
70
|
+
if (!ID_START_RE.test(name)) {
|
|
71
|
+
name = '_' + name;
|
|
72
|
+
}
|
|
73
|
+
return name;
|
|
74
|
+
}
|