webfuscator 1.2.1 → 1.3.1
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/README.md +3 -3
- package/dist/analysis/constant.d.ts.map +1 -1
- package/dist/analysis/constant.js +10 -27
- package/dist/analysis/constant.js.map +1 -1
- package/dist/analysis/inlineability.d.ts.map +1 -1
- package/dist/analysis/inlineability.js +5 -13
- package/dist/analysis/inlineability.js.map +1 -1
- package/dist/analysis/purity.d.ts +3 -3
- package/dist/analysis/purity.d.ts.map +1 -1
- package/dist/analysis/purity.js +28 -75
- package/dist/analysis/purity.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/obfuscator.d.ts +2 -1
- package/dist/obfuscator.d.ts.map +1 -1
- package/dist/obfuscator.js +47 -12
- package/dist/obfuscator.js.map +1 -1
- package/dist/options.d.ts +17 -4
- package/dist/options.d.ts.map +1 -1
- package/dist/preparation/expand-destructuring.d.ts +2 -3
- package/dist/preparation/expand-destructuring.d.ts.map +1 -1
- package/dist/preparation/expand-destructuring.js +2 -8
- package/dist/preparation/expand-destructuring.js.map +1 -1
- package/dist/transforms/arguments-to-parameters.d.ts +5 -4
- package/dist/transforms/arguments-to-parameters.d.ts.map +1 -1
- package/dist/transforms/arguments-to-parameters.js +5 -4
- package/dist/transforms/arguments-to-parameters.js.map +1 -1
- package/dist/transforms/arrow-to-function.d.ts +4 -3
- package/dist/transforms/arrow-to-function.d.ts.map +1 -1
- package/dist/transforms/arrow-to-function.js +6 -10
- package/dist/transforms/arrow-to-function.js.map +1 -1
- package/dist/transforms/collapse-single-use-temps.d.ts +2 -1
- package/dist/transforms/collapse-single-use-temps.d.ts.map +1 -1
- package/dist/transforms/collapse-single-use-temps.js +12 -20
- package/dist/transforms/collapse-single-use-temps.js.map +1 -1
- package/dist/transforms/conceal-strings.d.ts +56 -0
- package/dist/transforms/conceal-strings.d.ts.map +1 -0
- package/dist/transforms/conceal-strings.js +356 -0
- package/dist/transforms/conceal-strings.js.map +1 -0
- package/dist/transforms/const-let-to-var.d.ts +4 -3
- package/dist/transforms/const-let-to-var.d.ts.map +1 -1
- package/dist/transforms/const-let-to-var.js +8 -67
- package/dist/transforms/const-let-to-var.js.map +1 -1
- package/dist/transforms/const-to-let.d.ts +1 -3
- package/dist/transforms/const-to-let.d.ts.map +1 -1
- package/dist/transforms/const-to-let.js +1 -8
- package/dist/transforms/const-to-let.js.map +1 -1
- package/dist/transforms/drop-console.d.ts.map +1 -1
- package/dist/transforms/drop-console.js +3 -5
- package/dist/transforms/drop-console.js.map +1 -1
- package/dist/transforms/expand-binary-assignment.d.ts.map +1 -1
- package/dist/transforms/expand-binary-assignment.js +0 -5
- package/dist/transforms/expand-binary-assignment.js.map +1 -1
- package/dist/transforms/expand-logical-assignment.d.ts.map +1 -1
- package/dist/transforms/expand-logical-assignment.js +0 -5
- package/dist/transforms/expand-logical-assignment.js.map +1 -1
- package/dist/transforms/extract-object-properties.js +5 -12
- package/dist/transforms/extract-object-properties.js.map +1 -1
- package/dist/transforms/fold-builtin-methods.d.ts.map +1 -1
- package/dist/transforms/fold-builtin-methods.js +44 -14
- package/dist/transforms/fold-builtin-methods.js.map +1 -1
- package/dist/transforms/fold-constants.js +5 -2
- package/dist/transforms/fold-constants.js.map +1 -1
- package/dist/transforms/function-declaration-to-expression.d.ts +5 -6
- package/dist/transforms/function-declaration-to-expression.d.ts.map +1 -1
- package/dist/transforms/function-declaration-to-expression.js +5 -6
- package/dist/transforms/function-declaration-to-expression.js.map +1 -1
- package/dist/transforms/hoist-variables.d.ts +29 -0
- package/dist/transforms/hoist-variables.d.ts.map +1 -0
- package/dist/transforms/hoist-variables.js +215 -0
- package/dist/transforms/hoist-variables.js.map +1 -0
- package/dist/transforms/inline-functions.js +11 -40
- package/dist/transforms/inline-functions.js.map +1 -1
- package/dist/transforms/logical-to-ternary.d.ts +1 -1
- package/dist/transforms/logical-to-ternary.js +5 -9
- package/dist/transforms/logical-to-ternary.js.map +1 -1
- package/dist/transforms/mangle-properties.d.ts +2 -5
- package/dist/transforms/mangle-properties.d.ts.map +1 -1
- package/dist/transforms/mangle-properties.js +9 -9
- package/dist/transforms/mangle-properties.js.map +1 -1
- package/dist/transforms/merge-variable-declarations.d.ts +17 -0
- package/dist/transforms/merge-variable-declarations.d.ts.map +1 -0
- package/dist/transforms/merge-variable-declarations.js +68 -0
- package/dist/transforms/merge-variable-declarations.js.map +1 -0
- package/dist/transforms/nullish-coalescing-to-ternary.d.ts +4 -5
- package/dist/transforms/nullish-coalescing-to-ternary.d.ts.map +1 -1
- package/dist/transforms/nullish-coalescing-to-ternary.js +7 -12
- package/dist/transforms/nullish-coalescing-to-ternary.js.map +1 -1
- package/dist/transforms/numbers-to-strings.d.ts.map +1 -1
- package/dist/transforms/numbers-to-strings.js +1 -8
- package/dist/transforms/numbers-to-strings.js.map +1 -1
- package/dist/transforms/object-method-to-property.d.ts +1 -1
- package/dist/transforms/object-method-to-property.js +1 -1
- package/dist/transforms/optional-chaining-to-ternary.d.ts +4 -3
- package/dist/transforms/optional-chaining-to-ternary.d.ts.map +1 -1
- package/dist/transforms/optional-chaining-to-ternary.js +9 -9
- package/dist/transforms/optional-chaining-to-ternary.js.map +1 -1
- package/dist/transforms/pack-declarations-into-parameters.d.ts.map +1 -1
- package/dist/transforms/pack-declarations-into-parameters.js +5 -21
- package/dist/transforms/pack-declarations-into-parameters.js.map +1 -1
- package/dist/transforms/pack.d.ts +4 -13
- package/dist/transforms/pack.d.ts.map +1 -1
- package/dist/transforms/pack.js +9 -29
- package/dist/transforms/pack.js.map +1 -1
- package/dist/transforms/remove-anonymous-function-names.d.ts +2 -4
- package/dist/transforms/remove-anonymous-function-names.d.ts.map +1 -1
- package/dist/transforms/remove-anonymous-function-names.js +2 -40
- package/dist/transforms/remove-anonymous-function-names.js.map +1 -1
- package/dist/transforms/remove-unreachable-code.js +2 -21
- package/dist/transforms/remove-unreachable-code.js.map +1 -1
- package/dist/transforms/remove-unused-code.d.ts.map +1 -1
- package/dist/transforms/remove-unused-code.js +12 -49
- package/dist/transforms/remove-unused-code.js.map +1 -1
- package/dist/transforms/rename-identifiers.d.ts +3 -3
- package/dist/transforms/rename-identifiers.d.ts.map +1 -1
- package/dist/transforms/rename-identifiers.js +31 -35
- package/dist/transforms/rename-identifiers.js.map +1 -1
- package/dist/transforms/reorder-function-declarations.d.ts +24 -0
- package/dist/transforms/reorder-function-declarations.d.ts.map +1 -0
- package/dist/transforms/reorder-function-declarations.js +62 -0
- package/dist/transforms/reorder-function-declarations.js.map +1 -0
- package/dist/transforms/specials-to-strings.d.ts.map +1 -1
- package/dist/transforms/specials-to-strings.js +2 -3
- package/dist/transforms/specials-to-strings.js.map +1 -1
- package/dist/transforms/switch-to-if.js +5 -15
- package/dist/transforms/switch-to-if.js.map +1 -1
- package/dist/transforms/ternary-to-if.d.ts.map +1 -1
- package/dist/transforms/ternary-to-if.js +5 -9
- package/dist/transforms/ternary-to-if.js.map +1 -1
- package/dist/transforms/update-to-assignment.d.ts.map +1 -1
- package/dist/transforms/update-to-assignment.js +6 -23
- package/dist/transforms/update-to-assignment.js.map +1 -1
- package/dist/transforms/yodify-conditions.d.ts +3 -4
- package/dist/transforms/yodify-conditions.d.ts.map +1 -1
- package/dist/transforms/yodify-conditions.js +3 -4
- package/dist/transforms/yodify-conditions.js.map +1 -1
- package/dist/utils/ast.d.ts +1 -3
- package/dist/utils/ast.d.ts.map +1 -1
- package/dist/utils/ast.js +4 -60
- package/dist/utils/ast.js.map +1 -1
- package/dist/utils/evaluation-order.js +1 -1
- package/dist/utils/evaluation-order.js.map +1 -1
- package/dist/utils/literal.d.ts.map +1 -1
- package/dist/utils/literal.js +74 -2
- package/dist/utils/literal.js.map +1 -1
- package/dist/utils/logical-lowering.d.ts.map +1 -1
- package/dist/utils/logical-lowering.js +7 -9
- package/dist/utils/logical-lowering.js.map +1 -1
- package/dist/utils/nullish.d.ts +4 -0
- package/dist/utils/nullish.d.ts.map +1 -0
- package/dist/utils/nullish.js +8 -0
- package/dist/utils/nullish.js.map +1 -0
- package/dist/utils/paths.d.ts +0 -2
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +0 -28
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/statement-lists.d.ts +9 -0
- package/dist/utils/statement-lists.d.ts.map +1 -0
- package/dist/utils/statement-lists.js +27 -0
- package/dist/utils/statement-lists.js.map +1 -0
- package/package.json +6 -2
- package/src/analysis/constant.ts +12 -33
- package/src/analysis/inlineability.ts +5 -13
- package/src/analysis/purity.ts +29 -92
- package/src/index.ts +1 -0
- package/src/obfuscator.ts +51 -14
- package/src/options.ts +21 -3
- package/src/preparation/expand-destructuring.ts +2 -10
- package/src/transforms/arguments-to-parameters.ts +5 -4
- package/src/transforms/arrow-to-function.ts +6 -10
- package/src/transforms/collapse-single-use-temps.ts +12 -23
- package/src/transforms/conceal-strings.ts +525 -0
- package/src/transforms/const-let-to-var.ts +9 -72
- package/src/transforms/const-to-let.ts +1 -8
- package/src/transforms/drop-console.ts +3 -5
- package/src/transforms/expand-binary-assignment.ts +0 -5
- package/src/transforms/expand-logical-assignment.ts +0 -5
- package/src/transforms/extract-object-properties.ts +5 -14
- package/src/transforms/fold-builtin-methods.ts +63 -17
- package/src/transforms/fold-constants.ts +5 -2
- package/src/transforms/function-declaration-to-expression.ts +5 -6
- package/src/transforms/hoist-variables.ts +262 -0
- package/src/transforms/inline-functions.ts +16 -47
- package/src/transforms/logical-to-ternary.ts +5 -10
- package/src/transforms/mangle-properties.ts +9 -12
- package/src/transforms/merge-variable-declarations.ts +91 -0
- package/src/transforms/nullish-coalescing-to-ternary.ts +7 -13
- package/src/transforms/numbers-to-strings.ts +2 -12
- package/src/transforms/object-method-to-property.ts +1 -1
- package/src/transforms/optional-chaining-to-ternary.ts +9 -9
- package/src/transforms/pack-declarations-into-parameters.ts +11 -21
- package/src/transforms/pack.ts +9 -30
- package/src/transforms/remove-anonymous-function-names.ts +3 -46
- package/src/transforms/remove-unreachable-code.ts +2 -22
- package/src/transforms/remove-unused-code.ts +14 -74
- package/src/transforms/rename-identifiers.ts +44 -35
- package/src/transforms/reorder-function-declarations.ts +78 -0
- package/src/transforms/specials-to-strings.ts +2 -3
- package/src/transforms/switch-to-if.ts +5 -22
- package/src/transforms/ternary-to-if.ts +5 -9
- package/src/transforms/update-to-assignment.ts +6 -24
- package/src/transforms/yodify-conditions.ts +3 -4
- package/src/utils/ast.ts +4 -69
- package/src/utils/evaluation-order.ts +1 -1
- package/src/utils/literal.ts +91 -2
- package/src/utils/logical-lowering.ts +7 -11
- package/src/utils/nullish.ts +23 -0
- package/src/utils/paths.ts +0 -32
- package/src/utils/statement-lists.ts +45 -0
|
@@ -6,10 +6,10 @@ import type { File } from '@babel/types'
|
|
|
6
6
|
import { analyzeInlineability } from '../analysis/inlineability'
|
|
7
7
|
import type { InlineCandidate } from '../analysis/inlineability'
|
|
8
8
|
import { isPure } from '../analysis/purity'
|
|
9
|
-
import {
|
|
9
|
+
import { walkOwnFunctionScope } from '../utils/ast'
|
|
10
10
|
import { reorderableToStatement } from '../utils/evaluation-order'
|
|
11
11
|
import { generateLoopLabel } from '../utils/loop-lowering'
|
|
12
|
-
import {
|
|
12
|
+
import { isInStrictContext } from '../utils/paths'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Replaces eligible calls with function bodies, working from inner calls out.
|
|
@@ -135,14 +135,6 @@ function isSafeAtCallSite(
|
|
|
135
135
|
callPath: NodePath<t.CallExpression>,
|
|
136
136
|
candidates: Map<string, InlineCandidate>,
|
|
137
137
|
): boolean {
|
|
138
|
-
// `with`, direct eval, and Annex B aliases can redirect free names outside
|
|
139
|
-
// Babel's scope table.
|
|
140
|
-
if (isInsideWith(callPath) || enclosingScopeHasDirectEval(callPath)) {
|
|
141
|
-
return false
|
|
142
|
-
}
|
|
143
|
-
if (annexBHoistShadowsFreeVar(callPath, freeVars)) {
|
|
144
|
-
return false
|
|
145
|
-
}
|
|
146
138
|
// Spliced code inherits call-site strictness, so it must match the callee.
|
|
147
139
|
if (isInStrictContext(candidate.fnPath) !== isInStrictContext(callPath)) {
|
|
148
140
|
return false
|
|
@@ -193,32 +185,6 @@ function isSafeAtCallSite(
|
|
|
193
185
|
return true
|
|
194
186
|
}
|
|
195
187
|
|
|
196
|
-
// ECMA-262 B.3.2.1 creates a sloppy block-function alias that Babel misses in
|
|
197
|
-
// the enclosing scope.
|
|
198
|
-
function annexBHoistShadowsFreeVar(
|
|
199
|
-
callPath: NodePath<t.CallExpression>,
|
|
200
|
-
freeVars: Set<string>,
|
|
201
|
-
): boolean {
|
|
202
|
-
if (freeVars.size === 0 || isInStrictContext(callPath)) {
|
|
203
|
-
return false
|
|
204
|
-
}
|
|
205
|
-
const owner = callPath.getFunctionParent() ?? callPath.scope.getProgramParent().path
|
|
206
|
-
let found = false
|
|
207
|
-
owner.traverse({
|
|
208
|
-
Function(path) {
|
|
209
|
-
path.skip()
|
|
210
|
-
},
|
|
211
|
-
FunctionDeclaration(path) {
|
|
212
|
-
const id = path.node.id
|
|
213
|
-
if (id && freeVars.has(id.name) && hasAnnexBFunctionAlias(path)) {
|
|
214
|
-
found = true
|
|
215
|
-
path.stop()
|
|
216
|
-
}
|
|
217
|
-
},
|
|
218
|
-
})
|
|
219
|
-
return found
|
|
220
|
-
}
|
|
221
|
-
|
|
222
188
|
// Only loops in the same function repeat the spliced body.
|
|
223
189
|
function callIsInsideLoop(callPath: NodePath): boolean {
|
|
224
190
|
for (let current: NodePath | null = callPath.parentPath; current; current = current.parentPath) {
|
|
@@ -581,7 +547,9 @@ function inlineCallSite(
|
|
|
581
547
|
const replacement: t.Statement[] = []
|
|
582
548
|
if (directTarget.kind === 'declarator') {
|
|
583
549
|
replacement.push(
|
|
584
|
-
t.variableDeclaration(
|
|
550
|
+
t.variableDeclaration(directTarget.declarationKind, [
|
|
551
|
+
t.variableDeclarator(t.identifier(directTarget.name)),
|
|
552
|
+
]),
|
|
585
553
|
)
|
|
586
554
|
}
|
|
587
555
|
if (needsLabel) {
|
|
@@ -621,7 +589,9 @@ function inlineCallSite(
|
|
|
621
589
|
return true
|
|
622
590
|
}
|
|
623
591
|
|
|
624
|
-
type DirectTarget =
|
|
592
|
+
type DirectTarget =
|
|
593
|
+
| { kind: 'declarator'; name: string; declarationKind: 'let' | 'var' }
|
|
594
|
+
| { kind: 'assign'; name: string }
|
|
625
595
|
|
|
626
596
|
function identifyDirectAssignmentTarget(
|
|
627
597
|
callPath: NodePath<t.CallExpression>,
|
|
@@ -642,9 +612,8 @@ function identifyDirectAssignmentTarget(
|
|
|
642
612
|
if (!declPath || !declPath.isVariableDeclaration() || declPath.node.declarations.length !== 1) {
|
|
643
613
|
return null
|
|
644
614
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
if (declPath.node.kind !== 'var') {
|
|
615
|
+
const declarationKind = declPath.node.kind
|
|
616
|
+
if (declarationKind !== 'var' && declarationKind !== 'let') {
|
|
648
617
|
return null
|
|
649
618
|
}
|
|
650
619
|
const owner = declPath.parentPath
|
|
@@ -667,7 +636,7 @@ function identifyDirectAssignmentTarget(
|
|
|
667
636
|
if (argsContainIdentName(args, name)) {
|
|
668
637
|
return null
|
|
669
638
|
}
|
|
670
|
-
return { kind: 'declarator', name }
|
|
639
|
+
return { kind: 'declarator', name, declarationKind }
|
|
671
640
|
}
|
|
672
641
|
|
|
673
642
|
if (
|
|
@@ -714,10 +683,10 @@ function argEligibleForElision(argPath: NodePath, scope: Scope): boolean {
|
|
|
714
683
|
return false
|
|
715
684
|
}
|
|
716
685
|
const binding = scope.getBinding(argPath.node.name)
|
|
717
|
-
if (!binding || binding.constantViolations.length > 0) {
|
|
686
|
+
if (!binding || (binding.kind !== 'const' && binding.constantViolations.length > 0)) {
|
|
718
687
|
return false
|
|
719
688
|
}
|
|
720
|
-
return isPure(argPath.node, scope
|
|
689
|
+
return isPure(argPath.node, scope)
|
|
721
690
|
}
|
|
722
691
|
|
|
723
692
|
// Catch parameters stay scoped to their copied handlers. Counting them here
|
|
@@ -931,8 +900,8 @@ function isNonReferenceSlot(parent: t.Node, key: string): boolean {
|
|
|
931
900
|
interface StatementWalkContext {
|
|
932
901
|
insideNestedLoop: boolean
|
|
933
902
|
insideNestedSwitch: boolean
|
|
934
|
-
// Tail position propagates through final blocks, branches, and
|
|
935
|
-
//
|
|
903
|
+
// Tail position propagates through final blocks, branches, labels, and `with`.
|
|
904
|
+
// Try, switch, and loops interrupt it because more code may run afterward.
|
|
936
905
|
tailPosition: boolean
|
|
937
906
|
}
|
|
938
907
|
|
|
@@ -1052,7 +1021,7 @@ function walkIntoCompound(
|
|
|
1052
1021
|
}
|
|
1053
1022
|
|
|
1054
1023
|
if (t.isWithStatement(node)) {
|
|
1055
|
-
node.body = walkSingleChild(node.body, hooks,
|
|
1024
|
+
node.body = walkSingleChild(node.body, hooks, ctx)
|
|
1056
1025
|
}
|
|
1057
1026
|
}
|
|
1058
1027
|
|
|
@@ -3,10 +3,10 @@ import * as t from '@babel/types'
|
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
5
|
import { isPure } from '../analysis/purity'
|
|
6
|
-
import { isInsideWith } from '../utils/ast'
|
|
7
6
|
import { traverseForChanges } from '../utils/change-tracking'
|
|
8
7
|
import type { ChangeState } from '../utils/change-tracking'
|
|
9
8
|
import { lowerLogicalWriteStatement } from '../utils/logical-lowering'
|
|
9
|
+
import { buildNonNullishCheck, buildNullishCheck } from '../utils/nullish'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Rewrites logical expressions as guarded assignments or ternaries. A
|
|
@@ -23,7 +23,7 @@ import { lowerLogicalWriteStatement } from '../utils/logical-lowering'
|
|
|
23
23
|
* if (!x) x = b;
|
|
24
24
|
* y = c;
|
|
25
25
|
* if (y) y = d;
|
|
26
|
-
* f((_t = get())
|
|
26
|
+
* f(((_t = get()) !== null ? _t !== void 0 : false) ? _t : fallback);
|
|
27
27
|
*/
|
|
28
28
|
export function logicalToTernary(ast: File): boolean {
|
|
29
29
|
return traverseForChanges(ast, visitor)
|
|
@@ -45,11 +45,6 @@ function lowerLogical(path: NodePath<t.LogicalExpression>): boolean {
|
|
|
45
45
|
if (op !== '&&' && op !== '||' && op !== '??') {
|
|
46
46
|
return false
|
|
47
47
|
}
|
|
48
|
-
// `with` can turn repeated names into getters and shadow a cache temp.
|
|
49
|
-
if (isInsideWith(path)) {
|
|
50
|
-
return false
|
|
51
|
-
}
|
|
52
|
-
|
|
53
48
|
if (lowerLogicalWriteStatement(path, (target) => buildFallbackTest(op, target))) {
|
|
54
49
|
return true
|
|
55
50
|
}
|
|
@@ -60,7 +55,7 @@ function lowerLogical(path: NodePath<t.LogicalExpression>): boolean {
|
|
|
60
55
|
let valueSrc: t.Expression
|
|
61
56
|
|
|
62
57
|
// Babel purity misses user coercion in unary and binary expressions.
|
|
63
|
-
if (isPure(leftPath.node, scope
|
|
58
|
+
if (isPure(leftPath.node, scope)) {
|
|
64
59
|
testSrc = node.left
|
|
65
60
|
valueSrc = t.cloneNode(node.left)
|
|
66
61
|
} else {
|
|
@@ -71,7 +66,7 @@ function lowerLogical(path: NodePath<t.LogicalExpression>): boolean {
|
|
|
71
66
|
}
|
|
72
67
|
|
|
73
68
|
const test: t.Expression =
|
|
74
|
-
op === '??' ?
|
|
69
|
+
op === '??' ? buildNonNullishCheck(testSrc, t.cloneNode(valueSrc)) : testSrc
|
|
75
70
|
|
|
76
71
|
path.replaceWith(
|
|
77
72
|
op === '&&'
|
|
@@ -88,5 +83,5 @@ function buildFallbackTest(op: '&&' | '||' | '??', target: t.Identifier): t.Expr
|
|
|
88
83
|
if (op === '&&') {
|
|
89
84
|
return target
|
|
90
85
|
}
|
|
91
|
-
return
|
|
86
|
+
return buildNullishCheck(target, t.cloneNode(target))
|
|
92
87
|
}
|
|
@@ -13,11 +13,8 @@ import { StringGenerator } from '../utils/string-generator'
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Renames statically known public properties through one program-wide mapping.
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* This pass runs before shape preparation, while Babel still distinguishes
|
|
20
|
-
* `obj.name` from `obj["name"]`.
|
|
16
|
+
* Options select or reserve names, and collision checks keep every unchanged
|
|
17
|
+
* property distinct from the generated names.
|
|
21
18
|
*
|
|
22
19
|
* @example
|
|
23
20
|
* // ◀️ before
|
|
@@ -507,7 +504,7 @@ function rewriteKeyedProperty(path: NodePath<KeyedProperty>, state: PropertyMang
|
|
|
507
504
|
if (mangled === name) {
|
|
508
505
|
return
|
|
509
506
|
}
|
|
510
|
-
node.key = t.
|
|
507
|
+
node.key = t.stringLiteral(mangled)
|
|
511
508
|
node.computed = false
|
|
512
509
|
if (t.isObjectProperty(node)) {
|
|
513
510
|
node.shorthand = false
|
|
@@ -532,7 +529,7 @@ function rewriteMember(path: NodePath<Member>, state: PropertyManglerState): voi
|
|
|
532
529
|
}
|
|
533
530
|
// Babel narrows members by `computed`, so both fields need widening.
|
|
534
531
|
const computed = node as Member & { computed: boolean; property: t.Expression }
|
|
535
|
-
computed.property = t.
|
|
532
|
+
computed.property = t.stringLiteral(mangled)
|
|
536
533
|
computed.computed = true
|
|
537
534
|
state.changed = true
|
|
538
535
|
}
|
|
@@ -586,7 +583,7 @@ function rewriteTerminalNames(
|
|
|
586
583
|
node.value = mangled
|
|
587
584
|
return node
|
|
588
585
|
}
|
|
589
|
-
return t.
|
|
586
|
+
return t.stringLiteral(mangled)
|
|
590
587
|
}
|
|
591
588
|
if (t.isSequenceExpression(node)) {
|
|
592
589
|
const last = node.expressions.length - 1
|
|
@@ -684,10 +681,10 @@ function isTransparentAnnotationParent(path: NodePath, child: t.Node): boolean {
|
|
|
684
681
|
|
|
685
682
|
function hasAnnotation(node: t.Node, annotation: string): boolean {
|
|
686
683
|
return (
|
|
687
|
-
node.leadingComments?.some(
|
|
688
|
-
(
|
|
689
|
-
|
|
690
|
-
) ?? false
|
|
684
|
+
node.leadingComments?.some((comment) => {
|
|
685
|
+
const value = comment.value.trim()
|
|
686
|
+
return value === `@${annotation}` || value === `#${annotation}`
|
|
687
|
+
}) ?? false
|
|
691
688
|
)
|
|
692
689
|
}
|
|
693
690
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as t from '@babel/types'
|
|
2
|
+
import type { File } from '@babel/types'
|
|
3
|
+
|
|
4
|
+
import { rewriteStatementLists } from '../utils/statement-lists'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Merges adjacent variable declarations when their kinds and export wrappers
|
|
8
|
+
* match. It runs in programs, blocks, switch cases, and static blocks, and
|
|
9
|
+
* removes unlabeled empty statements between compatible declarations.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // ◀️ before
|
|
13
|
+
* let a = 1;
|
|
14
|
+
* let b = 2;
|
|
15
|
+
*
|
|
16
|
+
* // ▶️ after
|
|
17
|
+
* let a = 1,
|
|
18
|
+
* b = 2;
|
|
19
|
+
*/
|
|
20
|
+
export function mergeVariableDeclarations(ast: File): boolean {
|
|
21
|
+
return rewriteStatementLists(ast, (statements) =>
|
|
22
|
+
mergeAdjacent(statements.map((path) => path.node)),
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type StatementLike = t.Program['body'][number]
|
|
27
|
+
|
|
28
|
+
interface MergeableDeclaration {
|
|
29
|
+
declaration: t.VariableDeclaration
|
|
30
|
+
exported: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function mergeAdjacent(list: readonly StatementLike[]): StatementLike[] | null {
|
|
34
|
+
const out: StatementLike[] = []
|
|
35
|
+
let pendingEmpty: t.EmptyStatement[] = []
|
|
36
|
+
let merged = false
|
|
37
|
+
|
|
38
|
+
for (const statement of list) {
|
|
39
|
+
if (t.isEmptyStatement(statement) && mergeableDeclaration(out.at(-1)) !== null) {
|
|
40
|
+
pendingEmpty.push(statement)
|
|
41
|
+
continue
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const previous = mergeableDeclaration(out.at(-1))
|
|
45
|
+
const current = mergeableDeclaration(statement)
|
|
46
|
+
if (previous && current && canMerge(previous, current)) {
|
|
47
|
+
out[out.length - 1] = mergePair(previous, current)
|
|
48
|
+
pendingEmpty = []
|
|
49
|
+
merged = true
|
|
50
|
+
continue
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
out.push(...pendingEmpty, statement)
|
|
54
|
+
pendingEmpty = []
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
out.push(...pendingEmpty)
|
|
58
|
+
return merged ? out : null
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function mergeableDeclaration(statement: StatementLike | undefined): MergeableDeclaration | null {
|
|
62
|
+
if (statement === undefined) {
|
|
63
|
+
return null
|
|
64
|
+
}
|
|
65
|
+
if (t.isVariableDeclaration(statement)) {
|
|
66
|
+
return { declaration: statement, exported: false }
|
|
67
|
+
}
|
|
68
|
+
if (t.isExportNamedDeclaration(statement) && t.isVariableDeclaration(statement.declaration)) {
|
|
69
|
+
return { declaration: statement.declaration, exported: true }
|
|
70
|
+
}
|
|
71
|
+
return null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function canMerge(previous: MergeableDeclaration, current: MergeableDeclaration): boolean {
|
|
75
|
+
return (
|
|
76
|
+
previous.exported === current.exported && previous.declaration.kind === current.declaration.kind
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function mergePair(previous: MergeableDeclaration, current: MergeableDeclaration): StatementLike {
|
|
81
|
+
const declaration = t.variableDeclaration(previous.declaration.kind, [
|
|
82
|
+
...previous.declaration.declarations,
|
|
83
|
+
...current.declaration.declarations,
|
|
84
|
+
])
|
|
85
|
+
|
|
86
|
+
if (!previous.exported) {
|
|
87
|
+
return declaration
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return t.exportNamedDeclaration(declaration)
|
|
91
|
+
}
|
|
@@ -2,15 +2,14 @@ import type { NodePath, Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import { isInsideWith } from '../utils/ast'
|
|
6
5
|
import { traverseForChanges } from '../utils/change-tracking'
|
|
7
6
|
import type { ChangeState } from '../utils/change-tracking'
|
|
8
7
|
import { lowerLogicalWriteStatement } from '../utils/logical-lowering'
|
|
8
|
+
import { buildNonNullishCheck, buildNullishCheck } from '../utils/nullish'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Rewrites `a ?? b` as a guarded assignment or
|
|
12
|
-
* side-effectful left side is cached.
|
|
13
|
-
* values in one comparison.
|
|
11
|
+
* Rewrites `a ?? b` as a guarded assignment or strict null and undefined
|
|
12
|
+
* checks. A side-effectful left side is cached.
|
|
14
13
|
*
|
|
15
14
|
* @example
|
|
16
15
|
* // ◀️ before
|
|
@@ -19,8 +18,8 @@ import { lowerLogicalWriteStatement } from '../utils/logical-lowering'
|
|
|
19
18
|
*
|
|
20
19
|
* // ▶️ after
|
|
21
20
|
* var x = a;
|
|
22
|
-
* if (x
|
|
23
|
-
* f((_t = get())
|
|
21
|
+
* if (x === null ? true : x === void 0) x = b;
|
|
22
|
+
* f(((_t = get()) !== null ? _t !== void 0 : false) ? _t : fallback);
|
|
24
23
|
*/
|
|
25
24
|
export function nullishCoalescingToTernary(ast: File): boolean {
|
|
26
25
|
return traverseForChanges(ast, visitor)
|
|
@@ -39,11 +38,6 @@ function lowerNullishCoalescing(path: NodePath<t.LogicalExpression>): boolean {
|
|
|
39
38
|
if (node.operator !== '??') {
|
|
40
39
|
return false
|
|
41
40
|
}
|
|
42
|
-
// `with` can turn a repeated name into a getter and shadow a cache temp.
|
|
43
|
-
if (isInsideWith(path)) {
|
|
44
|
-
return false
|
|
45
|
-
}
|
|
46
|
-
|
|
47
41
|
if (lowerLogicalWriteStatement(path, nullishFallbackTest)) {
|
|
48
42
|
return true
|
|
49
43
|
}
|
|
@@ -64,7 +58,7 @@ function lowerNullishCoalescing(path: NodePath<t.LogicalExpression>): boolean {
|
|
|
64
58
|
|
|
65
59
|
path.replaceWith(
|
|
66
60
|
t.conditionalExpression(
|
|
67
|
-
|
|
61
|
+
buildNonNullishCheck(test, t.cloneNode(consequent)),
|
|
68
62
|
consequent,
|
|
69
63
|
node.right,
|
|
70
64
|
),
|
|
@@ -73,5 +67,5 @@ function lowerNullishCoalescing(path: NodePath<t.LogicalExpression>): boolean {
|
|
|
73
67
|
}
|
|
74
68
|
|
|
75
69
|
function nullishFallbackTest(target: t.Identifier): t.Expression {
|
|
76
|
-
return
|
|
70
|
+
return buildNullishCheck(target, t.cloneNode(target))
|
|
77
71
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Visitor } from '@babel/traverse'
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
+
import { isNonComputedKey } from '../utils/ast'
|
|
5
6
|
import { traverseForChanges } from '../utils/change-tracking'
|
|
6
7
|
import type { ChangeState } from '../utils/change-tracking'
|
|
7
8
|
|
|
@@ -48,14 +49,3 @@ const visitor: Visitor<ChangeState> = {
|
|
|
48
49
|
state.changed = true
|
|
49
50
|
},
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
-
function isNonComputedKey(path: NodePath<t.NumericLiteral>): boolean {
|
|
53
|
-
const parentPath = path.parentPath
|
|
54
|
-
if (!parentPath) {
|
|
55
|
-
return false
|
|
56
|
-
}
|
|
57
|
-
const parent = parentPath.node
|
|
58
|
-
return (
|
|
59
|
-
'key' in parent && parent.key === path.node && 'computed' in parent && parent.computed === false
|
|
60
|
-
)
|
|
61
|
-
}
|
|
@@ -16,7 +16,7 @@ import type { ChangeState } from '../utils/change-tracking'
|
|
|
16
16
|
*
|
|
17
17
|
* Non-computed `__proto__` methods stay intact because the property form invokes
|
|
18
18
|
* ECMA-262 B.3.1 prototype-setting behavior. Computed keys create own properties
|
|
19
|
-
* and
|
|
19
|
+
* and can be rewritten.
|
|
20
20
|
*
|
|
21
21
|
* @example
|
|
22
22
|
* // ◀️ before
|
|
@@ -2,9 +2,9 @@ import type { NodePath, Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import { isInsideWith } from '../utils/ast'
|
|
6
5
|
import { traverseForChanges } from '../utils/change-tracking'
|
|
7
6
|
import type { ChangeState } from '../utils/change-tracking'
|
|
7
|
+
import { buildNullishCheck } from '../utils/nullish'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Rewrites optional chains as nested ternaries. Side-effectful receivers are
|
|
@@ -18,9 +18,10 @@ import type { ChangeState } from '../utils/change-tracking'
|
|
|
18
18
|
* a?.b?.c;
|
|
19
19
|
*
|
|
20
20
|
* // ▶️ after
|
|
21
|
-
* obj
|
|
22
|
-
* obj
|
|
23
|
-
* a
|
|
21
|
+
* (obj === null ? true : obj === void 0) ? void 0 : (_m = obj.m).call(obj, arg);
|
|
22
|
+
* (obj === null ? true : obj === void 0) ? true : delete obj.x;
|
|
23
|
+
* (a === null ? true : a === void 0) ? void 0 :
|
|
24
|
+
* ((_b = a.b) === null ? true : _b === void 0) ? void 0 : _b.c;
|
|
24
25
|
*/
|
|
25
26
|
export function optionalChainingToTernary(ast: File): boolean {
|
|
26
27
|
return traverseForChanges(ast, visitor)
|
|
@@ -40,10 +41,6 @@ const visitor: Visitor<ChangeState> = {
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
function lowerOptionalChain(path: OptionalPath): boolean {
|
|
43
|
-
// `with` can make a repeated receiver name invoke a getter twice.
|
|
44
|
-
if (isInsideWith(path)) {
|
|
45
|
-
return false
|
|
46
|
-
}
|
|
47
44
|
if (isInsideOptionalChain(path)) {
|
|
48
45
|
return false
|
|
49
46
|
}
|
|
@@ -173,16 +170,19 @@ function transformChain(path: OptionalPath): boolean {
|
|
|
173
170
|
}
|
|
174
171
|
|
|
175
172
|
let check: t.Expression
|
|
173
|
+
let repeatedCheck: t.Expression
|
|
176
174
|
|
|
177
175
|
if (path.scope.isStatic(chain)) {
|
|
178
176
|
// The receiver stays in the member expression, so the check needs its own
|
|
179
177
|
// node. One node under two parents is visited twice, and a later in-place
|
|
180
178
|
// rewrite such as renameIdentifiers then applies itself twice to it.
|
|
181
179
|
check = t.cloneNode(chain)
|
|
180
|
+
repeatedCheck = t.cloneNode(chain)
|
|
182
181
|
} else {
|
|
183
182
|
const tmp = path.scope.generateUidIdentifierBasedOnNode(chain)
|
|
184
183
|
path.scope.push({ id: t.cloneNode(tmp) })
|
|
185
184
|
check = t.assignmentExpression('=', t.cloneNode(tmp), chain)
|
|
185
|
+
repeatedCheck = t.cloneNode(tmp)
|
|
186
186
|
if (isCall) {
|
|
187
187
|
;(node as t.CallExpression).callee = t.cloneNode(tmp)
|
|
188
188
|
} else {
|
|
@@ -208,7 +208,7 @@ function transformChain(path: OptionalPath): boolean {
|
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
const condition =
|
|
211
|
+
const condition = buildNullishCheck(check, repeatedCheck)
|
|
212
212
|
|
|
213
213
|
let alternate = replacementPath.node as t.Expression
|
|
214
214
|
if (isDelete && i === optionals.length - 1) {
|
|
@@ -2,11 +2,10 @@ import type { Binding, NodePath, Visitor } from '@babel/traverse'
|
|
|
2
2
|
import * as t from '@babel/types'
|
|
3
3
|
import type { File } from '@babel/types'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { hasDuplicateParamNames } from '../utils/ast'
|
|
6
6
|
import { traverseForChanges } from '../utils/change-tracking'
|
|
7
7
|
import type { ChangeState } from '../utils/change-tracking'
|
|
8
8
|
import { isLiteralShaped } from '../utils/literal'
|
|
9
|
-
import { hasAnnexBFunctionAlias } from '../utils/paths'
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Moves leading literal-valued `var` declarations into trailing default
|
|
@@ -50,10 +49,6 @@ function packLeadingIntoParams(path: NodePath<t.Function>): boolean {
|
|
|
50
49
|
) {
|
|
51
50
|
return false
|
|
52
51
|
}
|
|
53
|
-
// An Annex B alias splits call sites across bindings Babel does not connect.
|
|
54
|
-
if (hasAnnexBFunctionAlias(path)) {
|
|
55
|
-
return false
|
|
56
|
-
}
|
|
57
52
|
const params = path.node.params
|
|
58
53
|
if (params.some((param) => t.isRestElement(param))) {
|
|
59
54
|
return false
|
|
@@ -75,10 +70,6 @@ function packLeadingIntoParams(path: NodePath<t.Function>): boolean {
|
|
|
75
70
|
if (referencesArguments(path)) {
|
|
76
71
|
return false
|
|
77
72
|
}
|
|
78
|
-
// Direct eval can inspect the newly unmapped `arguments` by name.
|
|
79
|
-
if (enclosingScopeHasDirectEval(path)) {
|
|
80
|
-
return false
|
|
81
|
-
}
|
|
82
73
|
// A caller with extra arguments could fill the new parameter slot.
|
|
83
74
|
if (!allCallSitesRespectArity(path, params.length)) {
|
|
84
75
|
return false
|
|
@@ -163,7 +154,11 @@ function methodComputedKey(path: NodePath<t.Function>): NodePath | null {
|
|
|
163
154
|
// arity and without spread.
|
|
164
155
|
function allCallSitesRespectArity(path: NodePath<t.Function>, arity: number): boolean {
|
|
165
156
|
const external = functionBinding(path)
|
|
166
|
-
if (
|
|
157
|
+
if (
|
|
158
|
+
!external ||
|
|
159
|
+
(external.kind !== 'const' && !external.constant) ||
|
|
160
|
+
!bindingCallsRespectArity(external, arity)
|
|
161
|
+
) {
|
|
167
162
|
return false
|
|
168
163
|
}
|
|
169
164
|
if (path.isFunctionExpression() && path.node.id) {
|
|
@@ -193,17 +188,12 @@ function bindingCallsRespectArity(binding: Binding, arity: number): boolean {
|
|
|
193
188
|
return true
|
|
194
189
|
}
|
|
195
190
|
|
|
196
|
-
// Annex B can hoist function names from nested blocks into this function scope.
|
|
197
191
|
function functionDeclarationNames(body: t.BlockStatement): Set<string> {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
return node !== body && t.isFunction(node) ? t.traverseFast.skip : undefined
|
|
205
|
-
})
|
|
206
|
-
return names
|
|
192
|
+
return new Set(
|
|
193
|
+
body.body.flatMap((statement) =>
|
|
194
|
+
t.isFunctionDeclaration(statement) && statement.id ? [statement.id.name] : [],
|
|
195
|
+
),
|
|
196
|
+
)
|
|
207
197
|
}
|
|
208
198
|
|
|
209
199
|
function functionBinding(path: NodePath<t.Function>): Binding | null {
|
package/src/transforms/pack.ts
CHANGED
|
@@ -5,7 +5,6 @@ import * as t from '@babel/types'
|
|
|
5
5
|
import type { File } from '@babel/types'
|
|
6
6
|
|
|
7
7
|
import type { TransformContext } from '../options'
|
|
8
|
-
import { isInsideWith } from '../utils/ast'
|
|
9
8
|
import { isCalleeOrTagOf, isInStrictContext, referencesOrWritesVariable } from '../utils/paths'
|
|
10
9
|
import { mulberry32 } from '../utils/random'
|
|
11
10
|
import { StringGenerator } from '../utils/string-generator'
|
|
@@ -108,19 +107,10 @@ const STANDARD_GLOBALS: readonly string[] = [
|
|
|
108
107
|
]
|
|
109
108
|
|
|
110
109
|
/**
|
|
111
|
-
* Serializes the whole program
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* none distinguishable from a global at build time, so free names are routed
|
|
116
|
-
* through a parameter object whose accessors run in the original top-level scope
|
|
117
|
-
* and resolve each name there. Import declarations return above the call. `eval`
|
|
118
|
-
* is left un-routed so a direct eval still reads the body scope. Names inside a
|
|
119
|
-
* `with` stay un-routed too, since they may resolve against the with object at
|
|
120
|
-
* runtime. Export statements cannot live inside a Function body, so pack throws
|
|
121
|
-
* on them. It packs everything else as written. Code that needs `import.meta`,
|
|
122
|
-
* top-level await, dynamic `import()`, or a top-level `arguments` will not run
|
|
123
|
-
* once moved into a Function body.
|
|
110
|
+
* Serializes the whole program and runs it through the `Function` constructor.
|
|
111
|
+
* Imports stay outside the generated function. Reads and writes to other free
|
|
112
|
+
* names go through accessors created in the original top-level scope. Export
|
|
113
|
+
* statements are rejected because they cannot appear in a `Function` body.
|
|
124
114
|
*
|
|
125
115
|
* @example
|
|
126
116
|
* // ◀️ before
|
|
@@ -230,15 +220,9 @@ function packProgram(programPath: NodePath<t.Program>, ctx: TransformContext): b
|
|
|
230
220
|
|
|
231
221
|
const isRoutable = (path: NodePath<t.Identifier>): boolean => {
|
|
232
222
|
const name = path.node.name
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
|
|
236
|
-
if (name === objectName || name === 'arguments' || name === 'eval') {
|
|
237
|
-
return false
|
|
238
|
-
}
|
|
239
|
-
// Inside `with`, a free name may resolve to a property of the with object at
|
|
240
|
-
// runtime, so routing it to the top-level accessor would change behavior.
|
|
241
|
-
if (isInsideWith(path)) {
|
|
223
|
+
// Keep the wrapper parameter and `arguments` bare. The latter must bind to
|
|
224
|
+
// the wrapper function's own arguments object.
|
|
225
|
+
if (name === objectName || name === 'arguments') {
|
|
242
226
|
return false
|
|
243
227
|
}
|
|
244
228
|
if (!referencesOrWritesVariable(path)) {
|
|
@@ -298,18 +282,13 @@ function packProgram(programPath: NodePath<t.Program>, ctx: TransformContext): b
|
|
|
298
282
|
}
|
|
299
283
|
programPath.traverse(routingVisitor)
|
|
300
284
|
|
|
301
|
-
// The script completion value is its trailing expression; returning it keeps
|
|
302
|
-
// `eval` of the packed output producing the same value.
|
|
303
285
|
const body = programNode.body
|
|
304
|
-
const lastStatement = body.at(-1)
|
|
305
|
-
if (lastStatement && t.isExpressionStatement(lastStatement)) {
|
|
306
|
-
body[body.length - 1] = t.returnStatement(lastStatement.expression)
|
|
307
|
-
}
|
|
308
|
-
|
|
309
286
|
const innerDirectives = bodyStrict ? [t.directive(t.directiveLiteral('use strict'))] : []
|
|
310
287
|
const innerCode = generate(t.program(body, innerDirectives, 'script'), {
|
|
311
288
|
minified: true,
|
|
312
289
|
comments: false,
|
|
290
|
+
// `comments: false` still allows @license and @preserve.
|
|
291
|
+
shouldPrintComment: () => false,
|
|
313
292
|
}).code
|
|
314
293
|
|
|
315
294
|
const objectExpression = buildAccessorObject({
|