webfuscator 1.1.0 → 1.2.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/dist/analysis/constant.js +3 -3
- package/dist/analysis/constant.js.map +1 -1
- package/dist/analysis/inlineability.js +2 -2
- package/dist/analysis/inlineability.js.map +1 -1
- package/dist/analysis/purity.js +1 -1
- package/dist/analysis/purity.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/obfuscator.d.ts.map +1 -1
- package/dist/obfuscator.js.map +1 -1
- package/dist/options.d.ts.map +1 -1
- package/dist/preparation/expand-destructuring.js +4 -3
- package/dist/preparation/expand-destructuring.js.map +1 -1
- package/dist/preparation/expand-template-literals.js +3 -2
- package/dist/preparation/expand-template-literals.js.map +1 -1
- package/dist/preparation/split-sequence-expressions.js +1 -1
- package/dist/preparation/split-sequence-expressions.js.map +1 -1
- package/dist/preparation/split-variable-declarations.js +1 -1
- package/dist/preparation/split-variable-declarations.js.map +1 -1
- package/dist/preparation/stringify-object-keys.js +1 -1
- package/dist/preparation/stringify-object-keys.js.map +1 -1
- package/dist/preparation/wrap-single-statements.js +2 -2
- package/dist/preparation/wrap-single-statements.js.map +1 -1
- package/dist/transforms/arguments-to-parameters.js +1 -1
- package/dist/transforms/arguments-to-parameters.js.map +1 -1
- package/dist/transforms/arrow-to-function.js.map +1 -1
- package/dist/transforms/collapse-single-use-temps.js +7 -7
- package/dist/transforms/collapse-single-use-temps.js.map +1 -1
- package/dist/transforms/const-let-to-var.js +3 -3
- package/dist/transforms/const-let-to-var.js.map +1 -1
- package/dist/transforms/const-to-let.js.map +1 -1
- package/dist/transforms/do-while-to-while.js +3 -3
- package/dist/transforms/do-while-to-while.js.map +1 -1
- package/dist/transforms/drop-console.js +4 -3
- package/dist/transforms/drop-console.js.map +1 -1
- package/dist/transforms/drop-debugger.js.map +1 -1
- package/dist/transforms/expand-binary-assignment.js +5 -3
- package/dist/transforms/expand-binary-assignment.js.map +1 -1
- package/dist/transforms/expand-logical-assignment.js +5 -3
- package/dist/transforms/expand-logical-assignment.js.map +1 -1
- package/dist/transforms/extract-object-properties.js +7 -7
- package/dist/transforms/extract-object-properties.js.map +1 -1
- package/dist/transforms/fold-builtin-methods.js +16 -15
- package/dist/transforms/fold-builtin-methods.js.map +1 -1
- package/dist/transforms/fold-constants.js +2 -2
- package/dist/transforms/fold-constants.js.map +1 -1
- package/dist/transforms/for-to-while.js +5 -5
- package/dist/transforms/for-to-while.js.map +1 -1
- package/dist/transforms/function-declaration-to-expression.js +3 -3
- package/dist/transforms/function-declaration-to-expression.js.map +1 -1
- package/dist/transforms/inline-functions.js +7 -7
- package/dist/transforms/inline-functions.js.map +1 -1
- package/dist/transforms/logical-to-ternary.js +2 -2
- package/dist/transforms/logical-to-ternary.js.map +1 -1
- package/dist/transforms/mangle-properties.d.ts.map +1 -1
- package/dist/transforms/mangle-properties.js +35 -86
- package/dist/transforms/mangle-properties.js.map +1 -1
- package/dist/transforms/nullish-coalescing-to-ternary.js +2 -2
- package/dist/transforms/nullish-coalescing-to-ternary.js.map +1 -1
- package/dist/transforms/numbers-to-strings.js +2 -2
- package/dist/transforms/numbers-to-strings.js.map +1 -1
- package/dist/transforms/object-method-to-property.js +1 -1
- package/dist/transforms/object-method-to-property.js.map +1 -1
- package/dist/transforms/optional-chaining-to-ternary.js +2 -2
- package/dist/transforms/optional-chaining-to-ternary.js.map +1 -1
- package/dist/transforms/pack-declarations-into-parameters.js +2 -2
- package/dist/transforms/pack-declarations-into-parameters.js.map +1 -1
- package/dist/transforms/pack.d.ts.map +1 -1
- package/dist/transforms/pack.js +10 -11
- package/dist/transforms/pack.js.map +1 -1
- package/dist/transforms/remove-anonymous-function-names.js +3 -3
- package/dist/transforms/remove-anonymous-function-names.js.map +1 -1
- package/dist/transforms/remove-unreachable-code.js +1 -1
- package/dist/transforms/remove-unreachable-code.js.map +1 -1
- package/dist/transforms/remove-unused-code.js +4 -4
- package/dist/transforms/remove-unused-code.js.map +1 -1
- package/dist/transforms/rename-identifiers.d.ts.map +1 -1
- package/dist/transforms/rename-identifiers.js +4 -3
- package/dist/transforms/rename-identifiers.js.map +1 -1
- package/dist/transforms/specials-to-strings.d.ts.map +1 -1
- package/dist/transforms/specials-to-strings.js +2 -2
- package/dist/transforms/specials-to-strings.js.map +1 -1
- package/dist/transforms/switch-to-if.js +7 -7
- package/dist/transforms/switch-to-if.js.map +1 -1
- package/dist/transforms/ternary-to-if.js +7 -4
- package/dist/transforms/ternary-to-if.js.map +1 -1
- package/dist/transforms/update-to-assignment.js +4 -2
- package/dist/transforms/update-to-assignment.js.map +1 -1
- package/dist/transforms/yodify-conditions.js +3 -3
- package/dist/transforms/yodify-conditions.js.map +1 -1
- package/dist/utils/ast.d.ts.map +1 -1
- package/dist/utils/ast.js +2 -1
- package/dist/utils/ast.js.map +1 -1
- package/dist/utils/evaluation-order.js.map +1 -1
- package/dist/utils/logical-lowering.js +2 -2
- package/dist/utils/logical-lowering.js.map +1 -1
- package/dist/utils/loop-lowering.js +1 -1
- package/dist/utils/loop-lowering.js.map +1 -1
- package/dist/utils/string-generator.js +1 -1
- package/dist/utils/string-generator.js.map +1 -1
- package/package.json +11 -10
- package/src/analysis/constant.ts +4 -4
- package/src/analysis/inlineability.ts +4 -4
- package/src/analysis/purity.ts +3 -3
- package/src/index.ts +4 -2
- package/src/obfuscator.ts +42 -42
- package/src/options.ts +1 -1
- package/src/preparation/expand-destructuring.ts +5 -4
- package/src/preparation/expand-template-literals.ts +4 -3
- package/src/preparation/split-sequence-expressions.ts +2 -2
- package/src/preparation/split-variable-declarations.ts +1 -1
- package/src/preparation/stringify-object-keys.ts +2 -2
- package/src/preparation/wrap-single-statements.ts +2 -2
- package/src/transforms/arguments-to-parameters.ts +5 -5
- package/src/transforms/arrow-to-function.ts +3 -3
- package/src/transforms/collapse-single-use-temps.ts +14 -14
- package/src/transforms/const-let-to-var.ts +6 -6
- package/src/transforms/const-to-let.ts +4 -4
- package/src/transforms/do-while-to-while.ts +6 -6
- package/src/transforms/drop-console.ts +8 -7
- package/src/transforms/drop-debugger.ts +2 -2
- package/src/transforms/expand-binary-assignment.ts +8 -6
- package/src/transforms/expand-logical-assignment.ts +8 -6
- package/src/transforms/extract-object-properties.ts +12 -12
- package/src/transforms/fold-builtin-methods.ts +20 -19
- package/src/transforms/fold-constants.ts +8 -8
- package/src/transforms/for-to-while.ts +8 -8
- package/src/transforms/function-declaration-to-expression.ts +5 -5
- package/src/transforms/inline-functions.ts +14 -14
- package/src/transforms/logical-to-ternary.ts +7 -7
- package/src/transforms/mangle-properties.ts +43 -97
- package/src/transforms/nullish-coalescing-to-ternary.ts +6 -6
- package/src/transforms/numbers-to-strings.ts +4 -4
- package/src/transforms/object-method-to-property.ts +4 -4
- package/src/transforms/optional-chaining-to-ternary.ts +5 -5
- package/src/transforms/pack-declarations-into-parameters.ts +7 -7
- package/src/transforms/pack.ts +20 -16
- package/src/transforms/remove-anonymous-function-names.ts +5 -5
- package/src/transforms/remove-unreachable-code.ts +3 -3
- package/src/transforms/remove-unused-code.ts +8 -8
- package/src/transforms/rename-identifiers.ts +9 -8
- package/src/transforms/specials-to-strings.ts +7 -7
- package/src/transforms/switch-to-if.ts +12 -12
- package/src/transforms/ternary-to-if.ts +12 -9
- package/src/transforms/update-to-assignment.ts +7 -5
- package/src/transforms/yodify-conditions.ts +6 -6
- package/src/utils/ast.ts +2 -1
- package/src/utils/evaluation-order.ts +1 -1
- package/src/utils/logical-lowering.ts +3 -3
- package/src/utils/loop-lowering.ts +1 -1
- package/src/utils/string-generator.ts +1 -1
|
@@ -2,11 +2,11 @@ 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 { isPure } from '
|
|
6
|
-
import { isInsideWith } from '
|
|
7
|
-
import { traverseForChanges } from '
|
|
8
|
-
import type { ChangeState } from '
|
|
9
|
-
import { lowerLogicalWriteStatement } from '
|
|
5
|
+
import { isPure } from '../analysis/purity'
|
|
6
|
+
import { isInsideWith } from '../utils/ast'
|
|
7
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
8
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
9
|
+
import { lowerLogicalWriteStatement } from '../utils/logical-lowering'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Rewrites logical expressions as guarded assignments or ternaries. A
|
|
@@ -40,7 +40,7 @@ const visitor: Visitor<ChangeState> = {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function lowerLogical(path: NodePath<t.LogicalExpression>): boolean {
|
|
43
|
-
const
|
|
43
|
+
const node = path.node
|
|
44
44
|
const op = node.operator
|
|
45
45
|
if (op !== '&&' && op !== '||' && op !== '??') {
|
|
46
46
|
return false
|
|
@@ -54,7 +54,7 @@ function lowerLogical(path: NodePath<t.LogicalExpression>): boolean {
|
|
|
54
54
|
return true
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
const
|
|
57
|
+
const scope = path.scope
|
|
58
58
|
const leftPath = path.get('left')
|
|
59
59
|
let testSrc: t.Expression
|
|
60
60
|
let valueSrc: t.Expression
|
|
@@ -3,13 +3,13 @@ import type { NodePath, Scope, Visitor } from '@babel/traverse'
|
|
|
3
3
|
import * as t from '@babel/types'
|
|
4
4
|
import type { File } from '@babel/types'
|
|
5
5
|
|
|
6
|
-
import { evaluateConstant, isOpaque } from '
|
|
7
|
-
import type { ManglePropertiesOptions, PropertyNameGenerator, TransformContext } from '
|
|
8
|
-
import { isProtoKey } from '
|
|
9
|
-
import type { ChangeState } from '
|
|
10
|
-
import { DOM_PROPERTIES } from '
|
|
11
|
-
import { mulberry32 } from '
|
|
12
|
-
import { StringGenerator } from '
|
|
6
|
+
import { evaluateConstant, isOpaque } from '../analysis/constant'
|
|
7
|
+
import type { ManglePropertiesOptions, PropertyNameGenerator, TransformContext } from '../options'
|
|
8
|
+
import { isProtoKey } from '../utils/ast'
|
|
9
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
10
|
+
import { DOM_PROPERTIES } from '../utils/dom-properties'
|
|
11
|
+
import { mulberry32 } from '../utils/random'
|
|
12
|
+
import { StringGenerator } from '../utils/string-generator'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Renames statically known public properties through one program-wide mapping.
|
|
@@ -49,6 +49,27 @@ const NUMERIC_PROPERTY_RE = /^-?[0-9]+(?:\.[0-9]+)?(?:e[+-][0-9]+)?$/u
|
|
|
49
49
|
const SYNTAX_SENSITIVE_GENERATED_NAMES = new Set(['__proto__', 'constructor', 'prototype'])
|
|
50
50
|
const MAX_GENERATOR_ATTEMPTS = 100_000
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Names a platform object may own wherever the output runs. That could be a
|
|
54
|
+
* browser, a Node process, or an embedded engine, and nothing here can tell
|
|
55
|
+
* which, so the table unions every host name Terser collected. Renaming a name
|
|
56
|
+
* the target owns breaks the program. Reserving one it does not own costs a
|
|
57
|
+
* single missed rename.
|
|
58
|
+
*
|
|
59
|
+
* `builtins: true` is the caller promising that none of these names reach a
|
|
60
|
+
* platform object in their target.
|
|
61
|
+
*/
|
|
62
|
+
const RESERVED_PROPERTIES: ReadonlySet<string> = new Set([
|
|
63
|
+
...DOM_PROPERTIES,
|
|
64
|
+
// V8 reads `Error.prepareStackTrace` back off the constructor, and it postdates the table.
|
|
65
|
+
'prepareStackTrace',
|
|
66
|
+
// Not host names. ES3 rejects a keyword after `.`, which some downstream
|
|
67
|
+
// tooling still enforces, so they stay out of the generated keys too.
|
|
68
|
+
'false',
|
|
69
|
+
'null',
|
|
70
|
+
'true',
|
|
71
|
+
])
|
|
72
|
+
|
|
52
73
|
type KeyedProperty =
|
|
53
74
|
| t.ClassAccessorProperty
|
|
54
75
|
| t.ClassMethod
|
|
@@ -92,7 +113,7 @@ class PropertyManglerState implements ChangeState {
|
|
|
92
113
|
this.regex = compileRegex(options.regex)
|
|
93
114
|
|
|
94
115
|
if (!options.builtins) {
|
|
95
|
-
for (const name of
|
|
116
|
+
for (const name of RESERVED_PROPERTIES) {
|
|
96
117
|
this.reserved.add(name)
|
|
97
118
|
}
|
|
98
119
|
}
|
|
@@ -292,7 +313,7 @@ const collectVisitor: Visitor<PropertyManglerState> = {
|
|
|
292
313
|
(t.isCallExpression(path.node) || t.isOptionalCallExpression(path.node)) &&
|
|
293
314
|
isObjectDefinePropertyCall(path as NodePath<Call>)
|
|
294
315
|
) {
|
|
295
|
-
const
|
|
316
|
+
const key = path.node.arguments[1]
|
|
296
317
|
if (key && t.isExpression(key)) {
|
|
297
318
|
collectTerminalNames(key, path.scope, path, state)
|
|
298
319
|
}
|
|
@@ -324,7 +345,7 @@ const rewriteVisitor: Visitor<PropertyManglerState> = {
|
|
|
324
345
|
(t.isCallExpression(path.node) || t.isOptionalCallExpression(path.node)) &&
|
|
325
346
|
isObjectDefinePropertyCall(path as NodePath<Call>)
|
|
326
347
|
) {
|
|
327
|
-
const
|
|
348
|
+
const key = path.node.arguments[1]
|
|
328
349
|
if (key && t.isExpression(key)) {
|
|
329
350
|
path.node.arguments[1] = rewriteTerminalNames(key, path.scope, path, state)
|
|
330
351
|
}
|
|
@@ -341,7 +362,7 @@ const rewriteVisitor: Visitor<PropertyManglerState> = {
|
|
|
341
362
|
}
|
|
342
363
|
|
|
343
364
|
function prepareKeyedProperty(path: NodePath<KeyedProperty>, state: PropertyManglerState): void {
|
|
344
|
-
const
|
|
365
|
+
const node = path.node
|
|
345
366
|
if (isSemanticKey(node)) {
|
|
346
367
|
const name = plainKeyName(node.key)
|
|
347
368
|
if (name !== null) {
|
|
@@ -360,7 +381,7 @@ function prepareKeyedProperty(path: NodePath<KeyedProperty>, state: PropertyMang
|
|
|
360
381
|
}
|
|
361
382
|
|
|
362
383
|
function prepareMember(path: NodePath<Member>, state: PropertyManglerState): void {
|
|
363
|
-
const
|
|
384
|
+
const node = path.node
|
|
364
385
|
if (state.keepQuoted && node.computed && t.isExpression(node.property)) {
|
|
365
386
|
protectTerminalNames(node.property, path.scope, path, state)
|
|
366
387
|
}
|
|
@@ -370,7 +391,7 @@ function prepareMember(path: NodePath<Member>, state: PropertyManglerState): voi
|
|
|
370
391
|
}
|
|
371
392
|
|
|
372
393
|
function protectQuotedKey(path: NodePath<KeyedProperty>, state: PropertyManglerState): void {
|
|
373
|
-
const
|
|
394
|
+
const node = path.node
|
|
374
395
|
if (node.computed) {
|
|
375
396
|
if (t.isExpression(node.key)) {
|
|
376
397
|
protectTerminalNames(node.key, path.scope, path, state)
|
|
@@ -398,7 +419,7 @@ function protectName(name: string, state: PropertyManglerState): void {
|
|
|
398
419
|
}
|
|
399
420
|
|
|
400
421
|
function addAnnotatedKey(path: NodePath<KeyedProperty>, state: PropertyManglerState): void {
|
|
401
|
-
const
|
|
422
|
+
const node = path.node
|
|
402
423
|
if (node.computed) {
|
|
403
424
|
if (t.isExpression(node.key)) {
|
|
404
425
|
forEachTerminalName(node.key, path.scope, path, (name) => state.annotated.add(name))
|
|
@@ -412,7 +433,7 @@ function addAnnotatedKey(path: NodePath<KeyedProperty>, state: PropertyManglerSt
|
|
|
412
433
|
}
|
|
413
434
|
|
|
414
435
|
function addAnnotatedMember(path: NodePath<Member>, state: PropertyManglerState): void {
|
|
415
|
-
const
|
|
436
|
+
const node = path.node
|
|
416
437
|
if (node.computed) {
|
|
417
438
|
if (t.isExpression(node.property)) {
|
|
418
439
|
forEachTerminalName(node.property, path.scope, path, (name) => state.annotated.add(name))
|
|
@@ -423,7 +444,7 @@ function addAnnotatedMember(path: NodePath<Member>, state: PropertyManglerState)
|
|
|
423
444
|
}
|
|
424
445
|
|
|
425
446
|
function collectKeyedProperty(path: NodePath<KeyedProperty>, state: PropertyManglerState): void {
|
|
426
|
-
const
|
|
447
|
+
const node = path.node
|
|
427
448
|
if (node.computed) {
|
|
428
449
|
if (!state.keepQuoted && t.isExpression(node.key)) {
|
|
429
450
|
collectTerminalNames(node.key, path.scope, path, state)
|
|
@@ -440,7 +461,7 @@ function collectKeyedProperty(path: NodePath<KeyedProperty>, state: PropertyMang
|
|
|
440
461
|
}
|
|
441
462
|
|
|
442
463
|
function collectMember(path: NodePath<Member>, state: PropertyManglerState): void {
|
|
443
|
-
const
|
|
464
|
+
const node = path.node
|
|
444
465
|
if (node.computed) {
|
|
445
466
|
if (!state.keepQuoted && t.isExpression(node.property)) {
|
|
446
467
|
collectTerminalNames(node.property, path.scope, path, state)
|
|
@@ -468,7 +489,7 @@ function collectTerminalNames(
|
|
|
468
489
|
}
|
|
469
490
|
|
|
470
491
|
function rewriteKeyedProperty(path: NodePath<KeyedProperty>, state: PropertyManglerState): void {
|
|
471
|
-
const
|
|
492
|
+
const node = path.node
|
|
472
493
|
if (node.computed) {
|
|
473
494
|
if (!state.keepQuoted && t.isExpression(node.key)) {
|
|
474
495
|
node.key = rewriteTerminalNames(node.key, path.scope, path, state)
|
|
@@ -495,7 +516,7 @@ function rewriteKeyedProperty(path: NodePath<KeyedProperty>, state: PropertyMang
|
|
|
495
516
|
}
|
|
496
517
|
|
|
497
518
|
function rewriteMember(path: NodePath<Member>, state: PropertyManglerState): void {
|
|
498
|
-
const
|
|
519
|
+
const node = path.node
|
|
499
520
|
if (node.computed) {
|
|
500
521
|
if (!state.keepQuoted && t.isExpression(node.property)) {
|
|
501
522
|
node.property = rewriteTerminalNames(node.property, path.scope, path, state)
|
|
@@ -650,7 +671,7 @@ function memberHasMangleAnnotation(path: NodePath<Member>): boolean {
|
|
|
650
671
|
}
|
|
651
672
|
|
|
652
673
|
function isTransparentAnnotationParent(path: NodePath, child: t.Node): boolean {
|
|
653
|
-
const
|
|
674
|
+
const node = path.node
|
|
654
675
|
return (
|
|
655
676
|
(t.isAssignmentExpression(node) && node.left === child) ||
|
|
656
677
|
(t.isCallExpression(node) && node.callee === child) ||
|
|
@@ -671,8 +692,8 @@ function hasAnnotation(node: t.Node, annotation: string): boolean {
|
|
|
671
692
|
}
|
|
672
693
|
|
|
673
694
|
function isObjectDefinePropertyCall(path: NodePath<Call>): boolean {
|
|
674
|
-
const
|
|
675
|
-
const
|
|
695
|
+
const node = path.node
|
|
696
|
+
const callee = node.callee
|
|
676
697
|
if (
|
|
677
698
|
(!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee)) ||
|
|
678
699
|
!t.isIdentifier(callee.object, { name: 'Object' })
|
|
@@ -742,78 +763,3 @@ function compileRegex(regex: ManglePropertiesOptions['regex']): RegExp | null {
|
|
|
742
763
|
}
|
|
743
764
|
return new RegExp(regex.source, regex.flags)
|
|
744
765
|
}
|
|
745
|
-
|
|
746
|
-
const BUILTIN_OBJECTS: readonly object[] = [
|
|
747
|
-
Object,
|
|
748
|
-
Array,
|
|
749
|
-
Function,
|
|
750
|
-
Number,
|
|
751
|
-
String,
|
|
752
|
-
Boolean,
|
|
753
|
-
BigInt,
|
|
754
|
-
Symbol,
|
|
755
|
-
Error,
|
|
756
|
-
AggregateError,
|
|
757
|
-
EvalError,
|
|
758
|
-
RangeError,
|
|
759
|
-
ReferenceError,
|
|
760
|
-
SyntaxError,
|
|
761
|
-
TypeError,
|
|
762
|
-
URIError,
|
|
763
|
-
Math,
|
|
764
|
-
Date,
|
|
765
|
-
RegExp,
|
|
766
|
-
JSON,
|
|
767
|
-
ArrayBuffer,
|
|
768
|
-
SharedArrayBuffer,
|
|
769
|
-
DataView,
|
|
770
|
-
Atomics,
|
|
771
|
-
Float32Array,
|
|
772
|
-
Float64Array,
|
|
773
|
-
Int8Array,
|
|
774
|
-
Int16Array,
|
|
775
|
-
Int32Array,
|
|
776
|
-
BigInt64Array,
|
|
777
|
-
Uint8Array,
|
|
778
|
-
Uint8ClampedArray,
|
|
779
|
-
Uint16Array,
|
|
780
|
-
Uint32Array,
|
|
781
|
-
BigUint64Array,
|
|
782
|
-
Map,
|
|
783
|
-
Set,
|
|
784
|
-
WeakMap,
|
|
785
|
-
WeakSet,
|
|
786
|
-
WeakRef,
|
|
787
|
-
FinalizationRegistry,
|
|
788
|
-
Promise,
|
|
789
|
-
Proxy,
|
|
790
|
-
Reflect,
|
|
791
|
-
Intl,
|
|
792
|
-
WebAssembly,
|
|
793
|
-
]
|
|
794
|
-
|
|
795
|
-
let cachedBuiltinProperties: ReadonlySet<string> | undefined
|
|
796
|
-
|
|
797
|
-
function builtinProperties(): ReadonlySet<string> {
|
|
798
|
-
cachedBuiltinProperties ??= collectBuiltinProperties()
|
|
799
|
-
return cachedBuiltinProperties
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
function collectBuiltinProperties(): ReadonlySet<string> {
|
|
803
|
-
const names = new Set(DOM_PROPERTIES)
|
|
804
|
-
for (const name of ['null', 'true', 'false', 'NaN', 'Infinity', '-Infinity', 'undefined']) {
|
|
805
|
-
names.add(name)
|
|
806
|
-
}
|
|
807
|
-
for (const object of BUILTIN_OBJECTS) {
|
|
808
|
-
for (const name of Object.getOwnPropertyNames(object)) {
|
|
809
|
-
names.add(name)
|
|
810
|
-
}
|
|
811
|
-
const prototype = 'prototype' in object ? object.prototype : null
|
|
812
|
-
if (prototype && (typeof prototype === 'object' || typeof prototype === 'function')) {
|
|
813
|
-
for (const name of Object.getOwnPropertyNames(prototype)) {
|
|
814
|
-
names.add(name)
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
return names
|
|
819
|
-
}
|
|
@@ -2,10 +2,10 @@ 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 '
|
|
6
|
-
import { traverseForChanges } from '
|
|
7
|
-
import type { ChangeState } from '
|
|
8
|
-
import { lowerLogicalWriteStatement } from '
|
|
5
|
+
import { isInsideWith } from '../utils/ast'
|
|
6
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
7
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
8
|
+
import { lowerLogicalWriteStatement } from '../utils/logical-lowering'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Rewrites `a ?? b` as a guarded assignment or `a != null ? a : b`. A
|
|
@@ -35,7 +35,7 @@ const visitor: Visitor<ChangeState> = {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
function lowerNullishCoalescing(path: NodePath<t.LogicalExpression>): boolean {
|
|
38
|
-
const
|
|
38
|
+
const node = path.node
|
|
39
39
|
if (node.operator !== '??') {
|
|
40
40
|
return false
|
|
41
41
|
}
|
|
@@ -48,7 +48,7 @@ function lowerNullishCoalescing(path: NodePath<t.LogicalExpression>): boolean {
|
|
|
48
48
|
return true
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
const
|
|
51
|
+
const scope = path.scope
|
|
52
52
|
let test: t.Expression
|
|
53
53
|
let consequent: t.Expression
|
|
54
54
|
|
|
@@ -2,8 +2,8 @@ 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 { traverseForChanges } from '
|
|
6
|
-
import type { ChangeState } from '
|
|
5
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
6
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Rewrites numeric literals as strings coerced with unary plus. Under `+`, `-`,
|
|
@@ -34,7 +34,7 @@ const visitor: Visitor<ChangeState> = {
|
|
|
34
34
|
return
|
|
35
35
|
}
|
|
36
36
|
const str = t.stringLiteral(String(path.node.value))
|
|
37
|
-
const
|
|
37
|
+
const parent = path.parent
|
|
38
38
|
if (
|
|
39
39
|
t.isUnaryExpression(parent) &&
|
|
40
40
|
parent.argument === path.node &&
|
|
@@ -50,7 +50,7 @@ const visitor: Visitor<ChangeState> = {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function isNonComputedKey(path: NodePath<t.NumericLiteral>): boolean {
|
|
53
|
-
const
|
|
53
|
+
const parentPath = path.parentPath
|
|
54
54
|
if (!parentPath) {
|
|
55
55
|
return false
|
|
56
56
|
}
|
|
@@ -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 { isProtoKey } from '
|
|
6
|
-
import { traverseForChanges } from '
|
|
7
|
-
import type { ChangeState } from '
|
|
5
|
+
import { isProtoKey } from '../utils/ast'
|
|
6
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
7
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Rewrites generator and async object methods as function-valued properties so
|
|
@@ -43,7 +43,7 @@ export function objectMethodToProperty(ast: File): boolean {
|
|
|
43
43
|
|
|
44
44
|
const visitor: Visitor<ChangeState> = {
|
|
45
45
|
ObjectMethod(path, state) {
|
|
46
|
-
const
|
|
46
|
+
const node = path.node
|
|
47
47
|
if (node.kind !== 'method' || (!node.generator && !node.async)) {
|
|
48
48
|
return
|
|
49
49
|
}
|
|
@@ -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 '
|
|
6
|
-
import { traverseForChanges } from '
|
|
7
|
-
import type { ChangeState } from '
|
|
5
|
+
import { isInsideWith } from '../utils/ast'
|
|
6
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
7
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Rewrites optional chains as nested ternaries. Side-effectful receivers are
|
|
@@ -129,7 +129,7 @@ function transformChain(path: OptionalPath): boolean {
|
|
|
129
129
|
|
|
130
130
|
let cur: NodePath = path
|
|
131
131
|
while (cur.isOptionalMemberExpression() || cur.isOptionalCallExpression()) {
|
|
132
|
-
const
|
|
132
|
+
const node = cur.node
|
|
133
133
|
if (node.optional) {
|
|
134
134
|
optionals.push(node as unknown as t.MemberExpression | t.CallExpression)
|
|
135
135
|
}
|
|
@@ -193,7 +193,7 @@ function transformChain(path: OptionalPath): boolean {
|
|
|
193
193
|
// A cached member call needs its original receiver as `this`.
|
|
194
194
|
if (isCall && t.isMemberExpression(chain)) {
|
|
195
195
|
const callNode = node as t.CallExpression
|
|
196
|
-
const
|
|
196
|
+
const object = chain.object
|
|
197
197
|
if (!t.isSuper(object)) {
|
|
198
198
|
let context: t.Expression
|
|
199
199
|
const memoized = path.scope.maybeGenerateMemoised(object)
|
|
@@ -2,11 +2,11 @@ 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 { enclosingScopeHasDirectEval, hasDuplicateParamNames } from '
|
|
6
|
-
import { traverseForChanges } from '
|
|
7
|
-
import type { ChangeState } from '
|
|
8
|
-
import { isLiteralShaped } from '
|
|
9
|
-
import { hasAnnexBFunctionAlias } from '
|
|
5
|
+
import { enclosingScopeHasDirectEval, hasDuplicateParamNames } from '../utils/ast'
|
|
6
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
7
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
8
|
+
import { isLiteralShaped } from '../utils/literal'
|
|
9
|
+
import { hasAnnexBFunctionAlias } from '../utils/paths'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Moves leading literal-valued `var` declarations into trailing default
|
|
@@ -54,7 +54,7 @@ function packLeadingIntoParams(path: NodePath<t.Function>): boolean {
|
|
|
54
54
|
if (hasAnnexBFunctionAlias(path)) {
|
|
55
55
|
return false
|
|
56
56
|
}
|
|
57
|
-
const
|
|
57
|
+
const params = path.node.params
|
|
58
58
|
if (params.some((param) => t.isRestElement(param))) {
|
|
59
59
|
return false
|
|
60
60
|
}
|
|
@@ -63,7 +63,7 @@ function packLeadingIntoParams(path: NodePath<t.Function>): boolean {
|
|
|
63
63
|
return false
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
const
|
|
66
|
+
const body = path.node.body
|
|
67
67
|
if (!t.isBlockStatement(body)) {
|
|
68
68
|
return false
|
|
69
69
|
}
|
package/src/transforms/pack.ts
CHANGED
|
@@ -4,11 +4,11 @@ import type { NodePath, Visitor } from '@babel/traverse'
|
|
|
4
4
|
import * as t from '@babel/types'
|
|
5
5
|
import type { File } from '@babel/types'
|
|
6
6
|
|
|
7
|
-
import type { TransformContext } from '
|
|
8
|
-
import { isInsideWith } from '
|
|
9
|
-
import { isCalleeOrTagOf, isInStrictContext, referencesOrWritesVariable } from '
|
|
10
|
-
import { mulberry32 } from '
|
|
11
|
-
import { StringGenerator } from '
|
|
7
|
+
import type { TransformContext } from '../options'
|
|
8
|
+
import { isInsideWith } from '../utils/ast'
|
|
9
|
+
import { isCalleeOrTagOf, isInStrictContext, referencesOrWritesVariable } from '../utils/paths'
|
|
10
|
+
import { mulberry32 } from '../utils/random'
|
|
11
|
+
import { StringGenerator } from '../utils/string-generator'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Serializes the whole program to a string and rebuilds it at runtime through
|
|
@@ -110,7 +110,7 @@ function packProgram(programPath: NodePath<t.Program>, ctx: TransformContext): b
|
|
|
110
110
|
t.memberExpression(t.identifier(objectName), t.stringLiteral(property), true)
|
|
111
111
|
|
|
112
112
|
const isRoutable = (path: NodePath<t.Identifier>): boolean => {
|
|
113
|
-
const
|
|
113
|
+
const name = path.node.name
|
|
114
114
|
// The wrapper parameter stays as written. `arguments` and `eval` are never
|
|
115
115
|
// routed: `arguments` binds to its own function's object, and leaving `eval`
|
|
116
116
|
// bare keeps a direct eval reading the body scope rather than the global one.
|
|
@@ -147,7 +147,7 @@ function packProgram(programPath: NodePath<t.Program>, ctx: TransformContext): b
|
|
|
147
147
|
if (isBareDeleteArgument(path) || !isRoutable(path)) {
|
|
148
148
|
return
|
|
149
149
|
}
|
|
150
|
-
const
|
|
150
|
+
const name = path.node.name
|
|
151
151
|
if (isWriteReference(path)) {
|
|
152
152
|
settable.add(name)
|
|
153
153
|
}
|
|
@@ -163,7 +163,7 @@ function packProgram(programPath: NodePath<t.Program>, ctx: TransformContext): b
|
|
|
163
163
|
|
|
164
164
|
// The script completion value is its trailing expression; returning it keeps
|
|
165
165
|
// `eval` of the packed output producing the same value.
|
|
166
|
-
const
|
|
166
|
+
const body = programNode.body
|
|
167
167
|
const lastStatement = body.at(-1)
|
|
168
168
|
if (lastStatement && t.isExpressionStatement(lastStatement)) {
|
|
169
169
|
body[body.length - 1] = t.returnStatement(lastStatement.expression)
|
|
@@ -252,7 +252,7 @@ function isWriteReference(path: NodePath<t.Identifier>): boolean {
|
|
|
252
252
|
if (!parent) {
|
|
253
253
|
return false
|
|
254
254
|
}
|
|
255
|
-
const
|
|
255
|
+
const node = path.node
|
|
256
256
|
if (parent.isAssignmentExpression() && parent.node.left === node) {
|
|
257
257
|
return true
|
|
258
258
|
}
|
|
@@ -295,9 +295,8 @@ interface AccessorObjectSpec {
|
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
function buildAccessorObject(spec: AccessorObjectSpec): t.ObjectExpression {
|
|
298
|
-
const { readProperties, setterParam, settable, strict, typeofProperties } = spec
|
|
299
298
|
const properties: t.ObjectMethod[] = []
|
|
300
|
-
for (const [name, property] of readProperties) {
|
|
299
|
+
for (const [name, property] of spec.readProperties) {
|
|
301
300
|
properties.push(
|
|
302
301
|
t.objectMethod(
|
|
303
302
|
'get',
|
|
@@ -306,23 +305,28 @@ function buildAccessorObject(spec: AccessorObjectSpec): t.ObjectExpression {
|
|
|
306
305
|
t.blockStatement([t.returnStatement(t.identifier(name))]),
|
|
307
306
|
),
|
|
308
307
|
)
|
|
309
|
-
if (settable.has(name)) {
|
|
308
|
+
if (spec.settable.has(name)) {
|
|
310
309
|
const setterBody = t.blockStatement([
|
|
311
310
|
t.expressionStatement(
|
|
312
|
-
t.assignmentExpression('=', t.identifier(name), t.identifier(setterParam)),
|
|
311
|
+
t.assignmentExpression('=', t.identifier(name), t.identifier(spec.setterParam)),
|
|
313
312
|
),
|
|
314
313
|
])
|
|
315
314
|
// A strict script becomes a sloppy output script, so the setter stays
|
|
316
315
|
// strict to keep an undeclared-global write throwing.
|
|
317
|
-
if (strict) {
|
|
316
|
+
if (spec.strict) {
|
|
318
317
|
setterBody.directives.push(t.directive(t.directiveLiteral('use strict')))
|
|
319
318
|
}
|
|
320
319
|
properties.push(
|
|
321
|
-
t.objectMethod(
|
|
320
|
+
t.objectMethod(
|
|
321
|
+
'set',
|
|
322
|
+
t.stringLiteral(property),
|
|
323
|
+
[t.identifier(spec.setterParam)],
|
|
324
|
+
setterBody,
|
|
325
|
+
),
|
|
322
326
|
)
|
|
323
327
|
}
|
|
324
328
|
}
|
|
325
|
-
for (const [name, property] of typeofProperties) {
|
|
329
|
+
for (const [name, property] of spec.typeofProperties) {
|
|
326
330
|
properties.push(
|
|
327
331
|
t.objectMethod(
|
|
328
332
|
'get',
|
|
@@ -2,8 +2,8 @@ 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 { traverseForChanges } from '
|
|
6
|
-
import type { ChangeState } from '
|
|
5
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
6
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Removes a function expression's name when the body does not use its binding
|
|
@@ -25,7 +25,7 @@ export function removeAnonymousFunctionNames(ast: File): boolean {
|
|
|
25
25
|
|
|
26
26
|
const visitor: Visitor<ChangeState> = {
|
|
27
27
|
FunctionExpression(path, state) {
|
|
28
|
-
const
|
|
28
|
+
const id = path.node.id
|
|
29
29
|
if (!id) {
|
|
30
30
|
return
|
|
31
31
|
}
|
|
@@ -48,8 +48,8 @@ const visitor: Visitor<ChangeState> = {
|
|
|
48
48
|
|
|
49
49
|
// No inferred name means `.name` would become empty.
|
|
50
50
|
function inferredName(path: NodePath<t.FunctionExpression>): string | null {
|
|
51
|
-
const
|
|
52
|
-
const
|
|
51
|
+
const node = path.node
|
|
52
|
+
const parentPath = path.parentPath
|
|
53
53
|
if (!parentPath) {
|
|
54
54
|
return null
|
|
55
55
|
}
|
|
@@ -2,8 +2,8 @@ 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 { traverseForChanges } from '
|
|
6
|
-
import type { ChangeState } from '
|
|
5
|
+
import { traverseForChanges } from '../utils/change-tracking'
|
|
6
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Removes statements after unconditional control flow in the same statement list.
|
|
@@ -72,7 +72,7 @@ function isCompletion(node: t.Node): boolean {
|
|
|
72
72
|
// Hoisted bindings and referenced lexical TDZ remain observable from reachable
|
|
73
73
|
// code. An unreferenced lexical declaration is inert.
|
|
74
74
|
function isSafeToRemoveAfterCompletion(path: NodePath<t.Statement>): boolean {
|
|
75
|
-
const
|
|
75
|
+
const node = path.node
|
|
76
76
|
if (t.isFunctionDeclaration(node) || (t.isVariableDeclaration(node) && node.kind === 'var')) {
|
|
77
77
|
return false
|
|
78
78
|
}
|
|
@@ -3,10 +3,10 @@ import type { NodePath, Scope, Visitor } from '@babel/traverse'
|
|
|
3
3
|
import * as t from '@babel/types'
|
|
4
4
|
import type { File } from '@babel/types'
|
|
5
5
|
|
|
6
|
-
import { isSideEffectFree } from '
|
|
7
|
-
import { isDirectEvalCall } from '
|
|
8
|
-
import type { ChangeState } from '
|
|
9
|
-
import { hasAnnexBFunctionAlias } from '
|
|
6
|
+
import { isSideEffectFree } from '../analysis/purity'
|
|
7
|
+
import { isDirectEvalCall } from '../utils/ast'
|
|
8
|
+
import type { ChangeState } from '../utils/change-tracking'
|
|
9
|
+
import { hasAnnexBFunctionAlias } from '../utils/paths'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Removes unused declarations and expression statements that have no effects.
|
|
@@ -150,12 +150,12 @@ function tryRemoveDeclarator(
|
|
|
150
150
|
return false
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
const
|
|
153
|
+
const id = path.node.id
|
|
154
154
|
if (!t.isIdentifier(id)) {
|
|
155
155
|
return false
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
const
|
|
158
|
+
const init = path.node.init
|
|
159
159
|
if (init && !isSideEffectFree(init, path.scope, path.get('init') as NodePath)) {
|
|
160
160
|
return false
|
|
161
161
|
}
|
|
@@ -196,7 +196,7 @@ function tryRemoveFunctionDecl(
|
|
|
196
196
|
if (hasAnnexBFunctionAlias(path)) {
|
|
197
197
|
return false
|
|
198
198
|
}
|
|
199
|
-
const
|
|
199
|
+
const id = path.node.id
|
|
200
200
|
if (!id) {
|
|
201
201
|
return false
|
|
202
202
|
}
|
|
@@ -228,7 +228,7 @@ function tryRemoveClassDecl(
|
|
|
228
228
|
if (isExported(path)) {
|
|
229
229
|
return false
|
|
230
230
|
}
|
|
231
|
-
const
|
|
231
|
+
const id = path.node.id
|
|
232
232
|
if (!id) {
|
|
233
233
|
return false
|
|
234
234
|
}
|