@parcel/packager-js 2.0.0-dev.1517 → 2.0.0-dev.1528
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/ESMOutputFormat.js +8 -1
- package/lib/ScopeHoistingPackager.js +98 -51
- package/lib/utils.js +17 -0
- package/package.json +8 -8
- package/src/ESMOutputFormat.js +8 -1
- package/src/ScopeHoistingPackager.js +147 -59
- package/src/utils.js +17 -0
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);
|
|
@@ -61,11 +61,6 @@ 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
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 && Object.prototype.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
63
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
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
|
-
|
|
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 = '';
|
|
@@ -256,7 +238,7 @@ class ScopeHoistingPackager {
|
|
|
256
238
|
map
|
|
257
239
|
}];
|
|
258
240
|
});
|
|
259
|
-
if (asset.meta.shouldWrap || this.
|
|
241
|
+
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')) {
|
|
260
242
|
if (!asset.meta.isConstantModule) {
|
|
261
243
|
this.wrappedAssets.add(asset.id);
|
|
262
244
|
wrapped.push(asset);
|
|
@@ -282,7 +264,7 @@ class ScopeHoistingPackager {
|
|
|
282
264
|
return wrapped;
|
|
283
265
|
}
|
|
284
266
|
buildExportedSymbols() {
|
|
285
|
-
if (
|
|
267
|
+
if (!this.bundle.env.isLibrary || this.bundle.env.outputFormat !== 'esmodule') {
|
|
286
268
|
return;
|
|
287
269
|
}
|
|
288
270
|
|
|
@@ -331,8 +313,8 @@ class ScopeHoistingPackager {
|
|
|
331
313
|
}
|
|
332
314
|
}
|
|
333
315
|
getTopLevelName(name) {
|
|
334
|
-
name =
|
|
335
|
-
if (
|
|
316
|
+
name = (0, _utils2.makeValidIdentifier)(name);
|
|
317
|
+
if (this.globalNames.has(name)) {
|
|
336
318
|
name = '_' + name;
|
|
337
319
|
}
|
|
338
320
|
let count = this.topLevelNames.get(name);
|
|
@@ -344,7 +326,7 @@ class ScopeHoistingPackager {
|
|
|
344
326
|
return name + count;
|
|
345
327
|
}
|
|
346
328
|
getPropertyAccess(obj, property) {
|
|
347
|
-
if (
|
|
329
|
+
if ((0, _utils2.isValidIdentifier)(property)) {
|
|
348
330
|
return `${obj}.${property}`;
|
|
349
331
|
}
|
|
350
332
|
return `${obj}[${JSON.stringify(property)}]`;
|
|
@@ -401,7 +383,7 @@ class ScopeHoistingPackager {
|
|
|
401
383
|
code = code.replace('$parcel$filenameReplace', relPath);
|
|
402
384
|
}
|
|
403
385
|
let [depMap, replacements] = this.buildReplacements(asset, deps);
|
|
404
|
-
let [prepend, prependLines, append] = this.buildAssetPrelude(asset, deps);
|
|
386
|
+
let [prepend, prependLines, append] = this.buildAssetPrelude(asset, deps, replacements);
|
|
405
387
|
if (prependLines > 0) {
|
|
406
388
|
sourceMap === null || sourceMap === void 0 || sourceMap.offsetLines(1, prependLines);
|
|
407
389
|
code = prepend + code;
|
|
@@ -543,6 +525,16 @@ ${code}
|
|
|
543
525
|
if (!resolved) {
|
|
544
526
|
continue;
|
|
545
527
|
}
|
|
528
|
+
|
|
529
|
+
// Handle imports from other bundles in libraries.
|
|
530
|
+
if (this.bundle.env.isLibrary && !this.bundle.hasAsset(resolved)) {
|
|
531
|
+
let referencedBundle = this.bundleGraph.getReferencedBundle(dep, this.bundle);
|
|
532
|
+
if (referencedBundle && referencedBundle.getMainEntry() === resolved && referencedBundle.type === 'js' && !this.bundleGraph.isAssetReferenced(referencedBundle, resolved)) {
|
|
533
|
+
this.addExternal(dep, replacements, referencedBundle);
|
|
534
|
+
this.externalAssets.add(resolved);
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
546
538
|
for (let [imported, {
|
|
547
539
|
local
|
|
548
540
|
}] of dep.symbols) {
|
|
@@ -575,7 +567,7 @@ ${code}
|
|
|
575
567
|
}
|
|
576
568
|
return [depMap, replacements];
|
|
577
569
|
}
|
|
578
|
-
addExternal(dep, replacements) {
|
|
570
|
+
addExternal(dep, replacements, referencedBundle) {
|
|
579
571
|
if (this.bundle.env.outputFormat === 'global') {
|
|
580
572
|
throw new (_diagnostic().default)({
|
|
581
573
|
diagnostic: {
|
|
@@ -587,12 +579,16 @@ ${code}
|
|
|
587
579
|
}
|
|
588
580
|
});
|
|
589
581
|
}
|
|
582
|
+
let specifier = dep.specifier;
|
|
583
|
+
if (referencedBundle) {
|
|
584
|
+
specifier = (0, _utils().relativeBundlePath)(this.bundle, referencedBundle);
|
|
585
|
+
}
|
|
590
586
|
|
|
591
587
|
// Map of DependencySpecifier -> Map<ExportedSymbol, Identifier>>
|
|
592
|
-
let external = this.externals.get(
|
|
588
|
+
let external = this.externals.get(specifier);
|
|
593
589
|
if (!external) {
|
|
594
590
|
external = new Map();
|
|
595
|
-
this.externals.set(
|
|
591
|
+
this.externals.set(specifier, external);
|
|
596
592
|
}
|
|
597
593
|
for (let [imported, {
|
|
598
594
|
local
|
|
@@ -609,7 +605,13 @@ ${code}
|
|
|
609
605
|
if (this.bundle.env.outputFormat === 'commonjs') {
|
|
610
606
|
renamed = external.get('*');
|
|
611
607
|
if (!renamed) {
|
|
612
|
-
|
|
608
|
+
if (referencedBundle) {
|
|
609
|
+
var _entry$symbols$get$lo, _entry$symbols$get3;
|
|
610
|
+
let entry = (0, _nullthrows().default)(referencedBundle.getMainEntry());
|
|
611
|
+
renamed = (_entry$symbols$get$lo = (_entry$symbols$get3 = entry.symbols.get('*')) === null || _entry$symbols$get3 === void 0 ? void 0 : _entry$symbols$get3.local) !== null && _entry$symbols$get$lo !== void 0 ? _entry$symbols$get$lo : `$${String(entry.meta.id)}$exports`;
|
|
612
|
+
} else {
|
|
613
|
+
renamed = this.getTopLevelName(`$${this.bundle.publicId}$${specifier}`);
|
|
614
|
+
}
|
|
613
615
|
external.set('*', renamed);
|
|
614
616
|
}
|
|
615
617
|
if (local !== '*' && replacements) {
|
|
@@ -625,19 +627,55 @@ ${code}
|
|
|
625
627
|
replacements.set(local, replacement);
|
|
626
628
|
}
|
|
627
629
|
} else {
|
|
630
|
+
let property;
|
|
631
|
+
if (referencedBundle) {
|
|
632
|
+
let entry = (0, _nullthrows().default)(referencedBundle.getMainEntry());
|
|
633
|
+
if (entry.symbols.hasExportSymbol('*')) {
|
|
634
|
+
// If importing * and the referenced module has a * export (e.g. CJS), use default instead.
|
|
635
|
+
// This mirrors the logic in buildExportedSymbols.
|
|
636
|
+
property = imported;
|
|
637
|
+
imported = (referencedBundle === null || referencedBundle === void 0 ? void 0 : referencedBundle.env.outputFormat) === 'esmodule' ? 'default' : '*';
|
|
638
|
+
} else {
|
|
639
|
+
if (imported === '*') {
|
|
640
|
+
let exportedSymbols = this.bundleGraph.getExportedSymbols(entry);
|
|
641
|
+
if (local === '*') {
|
|
642
|
+
// Re-export all symbols.
|
|
643
|
+
for (let exported of exportedSymbols) {
|
|
644
|
+
if (exported.symbol) {
|
|
645
|
+
external.set(exported.exportSymbol, exported.symbol);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
renamed = this.bundleGraph.getSymbolResolution(entry, imported, this.bundle).symbol;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
628
655
|
// Rename the specifier so that multiple local imports of the same imported specifier
|
|
629
656
|
// are deduplicated. We have to prefix the imported name with the bundle id so that
|
|
630
657
|
// local variables do not shadow it.
|
|
631
|
-
if (
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
658
|
+
if (!renamed) {
|
|
659
|
+
if (this.exportedSymbols.has(local)) {
|
|
660
|
+
renamed = local;
|
|
661
|
+
} else if (imported === 'default' || imported === '*') {
|
|
662
|
+
renamed = this.getTopLevelName(`$${this.bundle.publicId}$${specifier}`);
|
|
663
|
+
} else {
|
|
664
|
+
renamed = this.getTopLevelName(`$${this.bundle.publicId}$${imported}`);
|
|
665
|
+
}
|
|
637
666
|
}
|
|
638
667
|
external.set(imported, renamed);
|
|
639
668
|
if (local !== '*' && replacements) {
|
|
640
|
-
|
|
669
|
+
let replacement = renamed;
|
|
670
|
+
if (property === '*') {
|
|
671
|
+
replacement = renamed;
|
|
672
|
+
} else if (property === 'default') {
|
|
673
|
+
replacement = `($parcel$interopDefault(${renamed}))`;
|
|
674
|
+
this.usedHelpers.add('$parcel$interopDefault');
|
|
675
|
+
} else if (property) {
|
|
676
|
+
replacement = this.getPropertyAccess(renamed, property);
|
|
677
|
+
}
|
|
678
|
+
replacements.set(local, replacement);
|
|
641
679
|
}
|
|
642
680
|
}
|
|
643
681
|
}
|
|
@@ -649,8 +687,7 @@ ${code}
|
|
|
649
687
|
}
|
|
650
688
|
return !this.bundle.hasAsset(resolved) && !this.externalAssets.has(resolved) || this.wrappedAssets.has(resolved.id) && resolved !== parentAsset;
|
|
651
689
|
}
|
|
652
|
-
getSymbolResolution(parentAsset, resolved, imported, dep) {
|
|
653
|
-
var _resolvedAsset$symbol;
|
|
690
|
+
getSymbolResolution(parentAsset, resolved, imported, dep, replacements) {
|
|
654
691
|
let {
|
|
655
692
|
asset: resolvedAsset,
|
|
656
693
|
exportSymbol,
|
|
@@ -696,9 +733,17 @@ ${code}
|
|
|
696
733
|
// namespace export symbol.
|
|
697
734
|
let assetId = resolvedAsset.meta.id;
|
|
698
735
|
(0, _assert().default)(typeof assetId === 'string');
|
|
699
|
-
let obj
|
|
700
|
-
|
|
701
|
-
|
|
736
|
+
let obj;
|
|
737
|
+
if (isWrapped && (!dep || dep !== null && dep !== void 0 && dep.meta.shouldWrap)) {
|
|
738
|
+
// Wrap in extra parenthesis to not change semantics, e.g.`new (parcelRequire("..."))()`.
|
|
739
|
+
obj = `(parcelRequire(${JSON.stringify(publicId)}))`;
|
|
740
|
+
} else if (isWrapped && dep) {
|
|
741
|
+
obj = `$${publicId}`;
|
|
742
|
+
} else {
|
|
743
|
+
var _resolvedAsset$symbol;
|
|
744
|
+
obj = ((_resolvedAsset$symbol = resolvedAsset.symbols.get('*')) === null || _resolvedAsset$symbol === void 0 ? void 0 : _resolvedAsset$symbol.local) || `$${assetId}$exports`;
|
|
745
|
+
obj = (replacements === null || replacements === void 0 ? void 0 : replacements.get(obj)) || obj;
|
|
746
|
+
}
|
|
702
747
|
if (imported === '*' || exportSymbol === '*' || isDefaultInterop) {
|
|
703
748
|
// Resolve to the namespace object if requested or this is a CJS default interop reqiure.
|
|
704
749
|
if (parentAsset === resolvedAsset && this.wrappedAssets.has(resolvedAsset.id)) {
|
|
@@ -722,7 +767,7 @@ ${code}
|
|
|
722
767
|
} else if (!symbol) {
|
|
723
768
|
(0, _assert().default)(false, 'Asset was skipped or not found.');
|
|
724
769
|
} else {
|
|
725
|
-
return symbol;
|
|
770
|
+
return (replacements === null || replacements === void 0 ? void 0 : replacements.get(symbol)) || symbol;
|
|
726
771
|
}
|
|
727
772
|
}
|
|
728
773
|
getHoistedParcelRequires(parentAsset, dep, resolved) {
|
|
@@ -749,7 +794,7 @@ ${code}
|
|
|
749
794
|
}
|
|
750
795
|
return [res, lineCount];
|
|
751
796
|
}
|
|
752
|
-
buildAssetPrelude(asset, deps) {
|
|
797
|
+
buildAssetPrelude(asset, deps, replacements) {
|
|
753
798
|
let prepend = '';
|
|
754
799
|
let prependLineCount = 0;
|
|
755
800
|
let append = '';
|
|
@@ -767,13 +812,15 @@ ${code}
|
|
|
767
812
|
// The one case where this isn't true is in ESM library entries, where the only
|
|
768
813
|
// dependency on * is the entry dependency. In this case, we will use ESM exports
|
|
769
814
|
// 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('*'))) ||
|
|
815
|
+
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
816
|
// If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
|
|
772
817
|
// we fallback on the namespace object.
|
|
773
818
|
asset.symbols.hasExportSymbol('*') && [...usedSymbols].some(s => !asset.symbols.hasExportSymbol(s)) ||
|
|
774
819
|
// If the exports has this asset's namespace (e.g. ESM output from CJS input),
|
|
775
820
|
// include the namespace object for the default export.
|
|
776
|
-
this.exportedSymbols.has(`$${assetId}$exports`)
|
|
821
|
+
this.exportedSymbols.has(`$${assetId}$exports`) ||
|
|
822
|
+
// CommonJS library bundle entries always need a namespace.
|
|
823
|
+
this.bundle.env.isLibrary && this.bundle.env.outputFormat === 'commonjs' && asset === this.bundle.getMainEntry();
|
|
777
824
|
|
|
778
825
|
// If the asset doesn't have static exports, should wrap, the namespace is used,
|
|
779
826
|
// or we need default interop, then we need to synthesize a namespace object for
|
|
@@ -824,7 +871,7 @@ ${code}
|
|
|
824
871
|
if (isWrapped || resolved.meta.staticExports === false || (0, _nullthrows().default)(this.bundleGraph.getUsedSymbols(resolved)).has('*') ||
|
|
825
872
|
// an empty asset
|
|
826
873
|
!resolved.meta.hasCJSExports && resolved.symbols.hasExportSymbol('*')) {
|
|
827
|
-
let obj = this.getSymbolResolution(asset, resolved, '*', dep);
|
|
874
|
+
let obj = this.getSymbolResolution(asset, resolved, '*', dep, replacements);
|
|
828
875
|
append += `$parcel$exportWildcard($${assetId}$exports, ${obj});\n`;
|
|
829
876
|
this.usedHelpers.add('$parcel$exportWildcard');
|
|
830
877
|
} else {
|
|
@@ -834,7 +881,7 @@ ${code}
|
|
|
834
881
|
symbol === '__esModule') {
|
|
835
882
|
continue;
|
|
836
883
|
}
|
|
837
|
-
let resolvedSymbol = this.getSymbolResolution(asset, resolved, symbol);
|
|
884
|
+
let resolvedSymbol = this.getSymbolResolution(asset, resolved, symbol, undefined, replacements);
|
|
838
885
|
let get = this.buildFunctionExpression([], resolvedSymbol);
|
|
839
886
|
let set = asset.meta.hasCJSExports ? ', ' + this.buildFunctionExpression(['v'], `${resolvedSymbol} = v`) : '';
|
|
840
887
|
prepend += `$parcel$export($${assetId}$exports, ${JSON.stringify(symbol)}, ${get}${set});\n`;
|
|
@@ -873,7 +920,7 @@ ${code}
|
|
|
873
920
|
// additional assignments after each mutation of the original binding.
|
|
874
921
|
prepend += `\n${usedExports.map(exp => {
|
|
875
922
|
var _asset$symbols$get2;
|
|
876
|
-
let resolved = this.getSymbolResolution(asset, asset, exp);
|
|
923
|
+
let resolved = this.getSymbolResolution(asset, asset, exp, undefined, replacements);
|
|
877
924
|
let get = this.buildFunctionExpression([], resolved);
|
|
878
925
|
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
926
|
let set = !isEsmExport && asset.meta.hasCJSExports ? ', ' + this.buildFunctionExpression(['v'], `${resolved} = v`) : '';
|
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"));
|
|
@@ -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.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.1528+70889ca07",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -17,17 +17,17 @@
|
|
|
17
17
|
"source": "src/index.js",
|
|
18
18
|
"engines": {
|
|
19
19
|
"node": ">= 12.0.0",
|
|
20
|
-
"parcel": "^2.0.0-dev.
|
|
20
|
+
"parcel": "^2.0.0-dev.1526+70889ca07"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@parcel/diagnostic": "2.0.0-dev.
|
|
24
|
-
"@parcel/plugin": "2.0.0-dev.
|
|
25
|
-
"@parcel/rust": "2.12.1-dev.
|
|
23
|
+
"@parcel/diagnostic": "2.0.0-dev.1528+70889ca07",
|
|
24
|
+
"@parcel/plugin": "2.0.0-dev.1528+70889ca07",
|
|
25
|
+
"@parcel/rust": "2.12.1-dev.3151+70889ca07",
|
|
26
26
|
"@parcel/source-map": "^2.1.1",
|
|
27
|
-
"@parcel/types": "2.0.0-dev.
|
|
28
|
-
"@parcel/utils": "2.0.0-dev.
|
|
27
|
+
"@parcel/types": "2.0.0-dev.1528+70889ca07",
|
|
28
|
+
"@parcel/utils": "2.0.0-dev.1528+70889ca07",
|
|
29
29
|
"globals": "^13.2.0",
|
|
30
30
|
"nullthrows": "^1.1.1"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "70889ca07dccb95e21e4c6a2844d632e3723faf4"
|
|
33
33
|
}
|
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
|
|
|
@@ -28,12 +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
|
-
|
|
31
|
+
import {
|
|
32
|
+
replaceScriptDependencies,
|
|
33
|
+
getSpecifier,
|
|
34
|
+
isValidIdentifier,
|
|
35
|
+
makeValidIdentifier,
|
|
36
|
+
} from './utils';
|
|
37
37
|
|
|
38
38
|
// General regex used to replace imports with the resolved code, references with resolutions,
|
|
39
39
|
// and count the number of newlines in the file for source maps.
|
|
@@ -134,25 +134,10 @@ export class ScopeHoistingPackager {
|
|
|
134
134
|
this.bundle.env.isLibrary ||
|
|
135
135
|
this.bundle.env.outputFormat === 'commonjs'
|
|
136
136
|
) {
|
|
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);
|
|
137
|
+
for (let b of this.bundleGraph.getReferencedBundles(this.bundle, {
|
|
138
|
+
recursive: false,
|
|
139
|
+
})) {
|
|
140
|
+
this.externals.set(relativeBundlePath(this.bundle, b), new Map());
|
|
156
141
|
}
|
|
157
142
|
}
|
|
158
143
|
|
|
@@ -324,7 +309,6 @@ export class ScopeHoistingPackager {
|
|
|
324
309
|
|
|
325
310
|
if (
|
|
326
311
|
asset.meta.shouldWrap ||
|
|
327
|
-
this.isAsyncBundle ||
|
|
328
312
|
this.bundle.env.sourceType === 'script' ||
|
|
329
313
|
this.bundleGraph.isAssetReferenced(this.bundle, asset) ||
|
|
330
314
|
this.bundleGraph
|
|
@@ -361,7 +345,6 @@ export class ScopeHoistingPackager {
|
|
|
361
345
|
|
|
362
346
|
buildExportedSymbols() {
|
|
363
347
|
if (
|
|
364
|
-
this.isAsyncBundle ||
|
|
365
348
|
!this.bundle.env.isLibrary ||
|
|
366
349
|
this.bundle.env.outputFormat !== 'esmodule'
|
|
367
350
|
) {
|
|
@@ -418,8 +401,8 @@ export class ScopeHoistingPackager {
|
|
|
418
401
|
}
|
|
419
402
|
|
|
420
403
|
getTopLevelName(name: string): string {
|
|
421
|
-
name = name
|
|
422
|
-
if (
|
|
404
|
+
name = makeValidIdentifier(name);
|
|
405
|
+
if (this.globalNames.has(name)) {
|
|
423
406
|
name = '_' + name;
|
|
424
407
|
}
|
|
425
408
|
|
|
@@ -434,7 +417,7 @@ export class ScopeHoistingPackager {
|
|
|
434
417
|
}
|
|
435
418
|
|
|
436
419
|
getPropertyAccess(obj: string, property: string): string {
|
|
437
|
-
if (
|
|
420
|
+
if (isValidIdentifier(property)) {
|
|
438
421
|
return `${obj}.${property}`;
|
|
439
422
|
}
|
|
440
423
|
|
|
@@ -511,7 +494,11 @@ export class ScopeHoistingPackager {
|
|
|
511
494
|
}
|
|
512
495
|
|
|
513
496
|
let [depMap, replacements] = this.buildReplacements(asset, deps);
|
|
514
|
-
let [prepend, prependLines, append] = this.buildAssetPrelude(
|
|
497
|
+
let [prepend, prependLines, append] = this.buildAssetPrelude(
|
|
498
|
+
asset,
|
|
499
|
+
deps,
|
|
500
|
+
replacements,
|
|
501
|
+
);
|
|
515
502
|
if (prependLines > 0) {
|
|
516
503
|
sourceMap?.offsetLines(1, prependLines);
|
|
517
504
|
code = prepend + code;
|
|
@@ -703,6 +690,24 @@ ${code}
|
|
|
703
690
|
continue;
|
|
704
691
|
}
|
|
705
692
|
|
|
693
|
+
// Handle imports from other bundles in libraries.
|
|
694
|
+
if (this.bundle.env.isLibrary && !this.bundle.hasAsset(resolved)) {
|
|
695
|
+
let referencedBundle = this.bundleGraph.getReferencedBundle(
|
|
696
|
+
dep,
|
|
697
|
+
this.bundle,
|
|
698
|
+
);
|
|
699
|
+
if (
|
|
700
|
+
referencedBundle &&
|
|
701
|
+
referencedBundle.getMainEntry() === resolved &&
|
|
702
|
+
referencedBundle.type === 'js' &&
|
|
703
|
+
!this.bundleGraph.isAssetReferenced(referencedBundle, resolved)
|
|
704
|
+
) {
|
|
705
|
+
this.addExternal(dep, replacements, referencedBundle);
|
|
706
|
+
this.externalAssets.add(resolved);
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
706
711
|
for (let [imported, {local}] of dep.symbols) {
|
|
707
712
|
if (local === '*') {
|
|
708
713
|
continue;
|
|
@@ -748,7 +753,11 @@ ${code}
|
|
|
748
753
|
return [depMap, replacements];
|
|
749
754
|
}
|
|
750
755
|
|
|
751
|
-
addExternal(
|
|
756
|
+
addExternal(
|
|
757
|
+
dep: Dependency,
|
|
758
|
+
replacements?: Map<string, string>,
|
|
759
|
+
referencedBundle?: NamedBundle,
|
|
760
|
+
) {
|
|
752
761
|
if (this.bundle.env.outputFormat === 'global') {
|
|
753
762
|
throw new ThrowableDiagnostic({
|
|
754
763
|
diagnostic: {
|
|
@@ -766,11 +775,16 @@ ${code}
|
|
|
766
775
|
});
|
|
767
776
|
}
|
|
768
777
|
|
|
778
|
+
let specifier = dep.specifier;
|
|
779
|
+
if (referencedBundle) {
|
|
780
|
+
specifier = relativeBundlePath(this.bundle, referencedBundle);
|
|
781
|
+
}
|
|
782
|
+
|
|
769
783
|
// Map of DependencySpecifier -> Map<ExportedSymbol, Identifier>>
|
|
770
|
-
let external = this.externals.get(
|
|
784
|
+
let external = this.externals.get(specifier);
|
|
771
785
|
if (!external) {
|
|
772
786
|
external = new Map();
|
|
773
|
-
this.externals.set(
|
|
787
|
+
this.externals.set(specifier, external);
|
|
774
788
|
}
|
|
775
789
|
|
|
776
790
|
for (let [imported, {local}] of dep.symbols) {
|
|
@@ -786,9 +800,16 @@ ${code}
|
|
|
786
800
|
if (this.bundle.env.outputFormat === 'commonjs') {
|
|
787
801
|
renamed = external.get('*');
|
|
788
802
|
if (!renamed) {
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
803
|
+
if (referencedBundle) {
|
|
804
|
+
let entry = nullthrows(referencedBundle.getMainEntry());
|
|
805
|
+
renamed =
|
|
806
|
+
entry.symbols.get('*')?.local ??
|
|
807
|
+
`$${String(entry.meta.id)}$exports`;
|
|
808
|
+
} else {
|
|
809
|
+
renamed = this.getTopLevelName(
|
|
810
|
+
`$${this.bundle.publicId}$${specifier}`,
|
|
811
|
+
);
|
|
812
|
+
}
|
|
792
813
|
|
|
793
814
|
external.set('*', renamed);
|
|
794
815
|
}
|
|
@@ -807,24 +828,67 @@ ${code}
|
|
|
807
828
|
replacements.set(local, replacement);
|
|
808
829
|
}
|
|
809
830
|
} else {
|
|
831
|
+
let property;
|
|
832
|
+
if (referencedBundle) {
|
|
833
|
+
let entry = nullthrows(referencedBundle.getMainEntry());
|
|
834
|
+
if (entry.symbols.hasExportSymbol('*')) {
|
|
835
|
+
// If importing * and the referenced module has a * export (e.g. CJS), use default instead.
|
|
836
|
+
// This mirrors the logic in buildExportedSymbols.
|
|
837
|
+
property = imported;
|
|
838
|
+
imported =
|
|
839
|
+
referencedBundle?.env.outputFormat === 'esmodule'
|
|
840
|
+
? 'default'
|
|
841
|
+
: '*';
|
|
842
|
+
} else {
|
|
843
|
+
if (imported === '*') {
|
|
844
|
+
let exportedSymbols = this.bundleGraph.getExportedSymbols(entry);
|
|
845
|
+
if (local === '*') {
|
|
846
|
+
// Re-export all symbols.
|
|
847
|
+
for (let exported of exportedSymbols) {
|
|
848
|
+
if (exported.symbol) {
|
|
849
|
+
external.set(exported.exportSymbol, exported.symbol);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
continue;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
renamed = this.bundleGraph.getSymbolResolution(
|
|
856
|
+
entry,
|
|
857
|
+
imported,
|
|
858
|
+
this.bundle,
|
|
859
|
+
).symbol;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
810
863
|
// Rename the specifier so that multiple local imports of the same imported specifier
|
|
811
864
|
// are deduplicated. We have to prefix the imported name with the bundle id so that
|
|
812
865
|
// local variables do not shadow it.
|
|
813
|
-
if (
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
866
|
+
if (!renamed) {
|
|
867
|
+
if (this.exportedSymbols.has(local)) {
|
|
868
|
+
renamed = local;
|
|
869
|
+
} else if (imported === 'default' || imported === '*') {
|
|
870
|
+
renamed = this.getTopLevelName(
|
|
871
|
+
`$${this.bundle.publicId}$${specifier}`,
|
|
872
|
+
);
|
|
873
|
+
} else {
|
|
874
|
+
renamed = this.getTopLevelName(
|
|
875
|
+
`$${this.bundle.publicId}$${imported}`,
|
|
876
|
+
);
|
|
877
|
+
}
|
|
823
878
|
}
|
|
824
879
|
|
|
825
880
|
external.set(imported, renamed);
|
|
826
881
|
if (local !== '*' && replacements) {
|
|
827
|
-
|
|
882
|
+
let replacement = renamed;
|
|
883
|
+
if (property === '*') {
|
|
884
|
+
replacement = renamed;
|
|
885
|
+
} else if (property === 'default') {
|
|
886
|
+
replacement = `($parcel$interopDefault(${renamed}))`;
|
|
887
|
+
this.usedHelpers.add('$parcel$interopDefault');
|
|
888
|
+
} else if (property) {
|
|
889
|
+
replacement = this.getPropertyAccess(renamed, property);
|
|
890
|
+
}
|
|
891
|
+
replacements.set(local, replacement);
|
|
828
892
|
}
|
|
829
893
|
}
|
|
830
894
|
}
|
|
@@ -849,6 +913,7 @@ ${code}
|
|
|
849
913
|
resolved: Asset,
|
|
850
914
|
imported: string,
|
|
851
915
|
dep?: Dependency,
|
|
916
|
+
replacements?: Map<string, string>,
|
|
852
917
|
): string {
|
|
853
918
|
let {
|
|
854
919
|
asset: resolvedAsset,
|
|
@@ -922,13 +987,16 @@ ${code}
|
|
|
922
987
|
// namespace export symbol.
|
|
923
988
|
let assetId = resolvedAsset.meta.id;
|
|
924
989
|
invariant(typeof assetId === 'string');
|
|
925
|
-
let obj
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
990
|
+
let obj;
|
|
991
|
+
if (isWrapped && (!dep || dep?.meta.shouldWrap)) {
|
|
992
|
+
// Wrap in extra parenthesis to not change semantics, e.g.`new (parcelRequire("..."))()`.
|
|
993
|
+
obj = `(parcelRequire(${JSON.stringify(publicId)}))`;
|
|
994
|
+
} else if (isWrapped && dep) {
|
|
995
|
+
obj = `$${publicId}`;
|
|
996
|
+
} else {
|
|
997
|
+
obj = resolvedAsset.symbols.get('*')?.local || `$${assetId}$exports`;
|
|
998
|
+
obj = replacements?.get(obj) || obj;
|
|
999
|
+
}
|
|
932
1000
|
|
|
933
1001
|
if (imported === '*' || exportSymbol === '*' || isDefaultInterop) {
|
|
934
1002
|
// Resolve to the namespace object if requested or this is a CJS default interop reqiure.
|
|
@@ -964,7 +1032,7 @@ ${code}
|
|
|
964
1032
|
} else if (!symbol) {
|
|
965
1033
|
invariant(false, 'Asset was skipped or not found.');
|
|
966
1034
|
} else {
|
|
967
|
-
return symbol;
|
|
1035
|
+
return replacements?.get(symbol) || symbol;
|
|
968
1036
|
}
|
|
969
1037
|
}
|
|
970
1038
|
|
|
@@ -1011,6 +1079,7 @@ ${code}
|
|
|
1011
1079
|
buildAssetPrelude(
|
|
1012
1080
|
asset: Asset,
|
|
1013
1081
|
deps: Array<Dependency>,
|
|
1082
|
+
replacements: Map<string, string>,
|
|
1014
1083
|
): [string, number, string] {
|
|
1015
1084
|
let prepend = '';
|
|
1016
1085
|
let prependLineCount = 0;
|
|
@@ -1043,6 +1112,7 @@ ${code}
|
|
|
1043
1112
|
.some(
|
|
1044
1113
|
dep =>
|
|
1045
1114
|
!dep.isEntry &&
|
|
1115
|
+
this.bundle.hasDependency(dep) &&
|
|
1046
1116
|
nullthrows(this.bundleGraph.getUsedSymbols(dep)).has('*'),
|
|
1047
1117
|
))) ||
|
|
1048
1118
|
// If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
|
|
@@ -1051,7 +1121,11 @@ ${code}
|
|
|
1051
1121
|
[...usedSymbols].some(s => !asset.symbols.hasExportSymbol(s))) ||
|
|
1052
1122
|
// If the exports has this asset's namespace (e.g. ESM output from CJS input),
|
|
1053
1123
|
// include the namespace object for the default export.
|
|
1054
|
-
this.exportedSymbols.has(`$${assetId}$exports`)
|
|
1124
|
+
this.exportedSymbols.has(`$${assetId}$exports`) ||
|
|
1125
|
+
// CommonJS library bundle entries always need a namespace.
|
|
1126
|
+
(this.bundle.env.isLibrary &&
|
|
1127
|
+
this.bundle.env.outputFormat === 'commonjs' &&
|
|
1128
|
+
asset === this.bundle.getMainEntry());
|
|
1055
1129
|
|
|
1056
1130
|
// If the asset doesn't have static exports, should wrap, the namespace is used,
|
|
1057
1131
|
// or we need default interop, then we need to synthesize a namespace object for
|
|
@@ -1118,7 +1192,13 @@ ${code}
|
|
|
1118
1192
|
(!resolved.meta.hasCJSExports &&
|
|
1119
1193
|
resolved.symbols.hasExportSymbol('*'))
|
|
1120
1194
|
) {
|
|
1121
|
-
let obj = this.getSymbolResolution(
|
|
1195
|
+
let obj = this.getSymbolResolution(
|
|
1196
|
+
asset,
|
|
1197
|
+
resolved,
|
|
1198
|
+
'*',
|
|
1199
|
+
dep,
|
|
1200
|
+
replacements,
|
|
1201
|
+
);
|
|
1122
1202
|
append += `$parcel$exportWildcard($${assetId}$exports, ${obj});\n`;
|
|
1123
1203
|
this.usedHelpers.add('$parcel$exportWildcard');
|
|
1124
1204
|
} else {
|
|
@@ -1136,6 +1216,8 @@ ${code}
|
|
|
1136
1216
|
asset,
|
|
1137
1217
|
resolved,
|
|
1138
1218
|
symbol,
|
|
1219
|
+
undefined,
|
|
1220
|
+
replacements,
|
|
1139
1221
|
);
|
|
1140
1222
|
let get = this.buildFunctionExpression([], resolvedSymbol);
|
|
1141
1223
|
let set = asset.meta.hasCJSExports
|
|
@@ -1182,7 +1264,13 @@ ${code}
|
|
|
1182
1264
|
// additional assignments after each mutation of the original binding.
|
|
1183
1265
|
prepend += `\n${usedExports
|
|
1184
1266
|
.map(exp => {
|
|
1185
|
-
let resolved = this.getSymbolResolution(
|
|
1267
|
+
let resolved = this.getSymbolResolution(
|
|
1268
|
+
asset,
|
|
1269
|
+
asset,
|
|
1270
|
+
exp,
|
|
1271
|
+
undefined,
|
|
1272
|
+
replacements,
|
|
1273
|
+
);
|
|
1186
1274
|
let get = this.buildFunctionExpression([], resolved);
|
|
1187
1275
|
let isEsmExport = !!asset.symbols.get(exp)?.meta?.isEsm;
|
|
1188
1276
|
let set =
|
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
|
+
}
|