Socket
Socket
Sign inDemoInstall

terser

Package Overview
Dependencies
4
Maintainers
1
Versions
171
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.7.2 to 5.8.0

bin/terser.mjs

9

CHANGELOG.md
# Changelog
## v5.8.0
- Fixed shadowing variables while moving code in some cases (#1065)
- Stop mangling computed & quoted properties when keep_quoted is enabled.
- Fix for mangling private getter/setter and .#private access (#1060, #1068)
- Array.from has a new optimization when the unsafe option is set (#737)
- Mangle/propmangle let you generate your own identifiers through the nth_identifier option (#1061)
- More optimizations to switch statements (#1044)
## v5.7.2

@@ -4,0 +13,0 @@

2

lib/ast.js

@@ -1333,3 +1333,3 @@ /***********************************************************************

var AST_ClassPrivateProperty = DEFNODE("ClassProperty", "", {
var AST_ClassPrivateProperty = DEFNODE("ClassPrivateProperty", "", {
$documentation: "A class property for a private property",

@@ -1336,0 +1336,0 @@ }, AST_ClassProperty);

@@ -324,3 +324,5 @@ /***********************************************************************

&& !(node instanceof AST_SymbolDeclaration)
&& lhs.equivalent_to(node)) {
&& lhs.equivalent_to(node)
&& !shadows(node.scope, lvalues)
) {
if (stop_if_hit) {

@@ -373,3 +375,3 @@ abort = true;

|| node instanceof AST_SymbolRef
&& (lvalues.get(node.name) || side_effects && may_modify(node))
&& ((lvalues.has(node.name) && lvalues.get(node.name).modified) || side_effects && may_modify(node))
|| node instanceof AST_VarDef && node.value

@@ -447,4 +449,5 @@ && (lvalues.has(node.name.name) || side_effects && may_modify(node.name))

var lhs_local = is_lhs_local(lhs);
if (lhs instanceof AST_SymbolRef)
lvalues.set(lhs.name, false);
if (lhs instanceof AST_SymbolRef) {
lvalues.set(lhs.name, { def: lhs.definition(), modified: false });
}
var side_effects = value_has_side_effects(candidate);

@@ -515,4 +518,5 @@ var replace_all = replace_all_symbols();

while (cur_scope && cur_scope !== scope) {
if (cur_scope.variables.has(def.name))
if (cur_scope.variables.has(def.name)) {
return true;
}
cur_scope = cur_scope.parent_scope;

@@ -798,4 +802,10 @@ }

sym = sym.expression;
if (sym instanceof AST_SymbolRef || sym instanceof AST_This) {
lvalues.set(sym.name, lvalues.get(sym.name) || is_modified(compressor, tw, node, node, 0));
if (sym instanceof AST_SymbolRef) {
const prev = lvalues.get(sym.name);
if (!prev || !prev.modified) {
lvalues.set(sym.name, {
def: sym.definition(),
modified: is_modified(compressor, tw, node, node, 0)
});
}
}

@@ -912,2 +922,14 @@ });

}
function shadows(newScope, lvalues) {
for (const {def} of lvalues.values()) {
let current = newScope;
while (current && current !== def.scope) {
let nested_def = current.variables.get(def.name);
if (nested_def && nested_def !== def) return true;
current = current.parent_scope;
}
}
return false;
}
}

@@ -914,0 +936,0 @@

@@ -14,6 +14,6 @@ "use strict";

import { Compressor } from "./compress/index.js";
import { base54 } from "./scope.js";
import { SourceMap } from "./sourcemap.js";
import {
mangle_properties,
mangle_private_properties,
reserve_quoted_keys,

@@ -207,5 +207,5 @@ } from "./propmangle.js";

if (options.mangle) {
base54.reset();
toplevel.compute_char_frequency(options.mangle);
toplevel.mangle_names(options.mangle);
toplevel = mangle_private_properties(toplevel, options.mangle);
}

@@ -212,0 +212,0 @@ if (timings) timings.properties = Date.now();

@@ -62,2 +62,4 @@ /***********************************************************************

AST_PrivateMethod,
AST_PrivateGetter,
AST_PrivateSetter,
AST_Sequence,

@@ -144,2 +146,32 @@ AST_String,

function mangle_private_properties(ast, options) {
var cprivate = -1;
var private_cache = new Map();
var nth_identifier = options.nth_identifier || base54;
ast = ast.transform(new TreeTransformer(function(node) {
if (
node instanceof AST_ClassPrivateProperty
|| node instanceof AST_PrivateMethod
|| node instanceof AST_PrivateGetter
|| node instanceof AST_PrivateSetter
) {
node.key.name = mangle_private(node.key.name);
} else if (node instanceof AST_DotHash) {
node.property = mangle_private(node.property);
}
}));
return ast;
function mangle_private(name) {
let mangled = private_cache.get(name);
if (!mangled) {
mangled = nth_identifier.get(++cprivate);
private_cache.set(name, mangled);
}
return mangled;
}
}
function mangle_properties(ast, options) {

@@ -151,2 +183,3 @@ options = defaults(options, {

keep_quoted: false,
nth_identifier: base54,
only_cache: false,

@@ -158,2 +191,4 @@ regex: null,

var nth_identifier = options.nth_identifier;
var reserved_option = options.reserved;

@@ -165,6 +200,4 @@ if (!Array.isArray(reserved_option)) reserved_option = [reserved_option];

var cname = -1;
var cprivate = -1;
var cache;
var private_cache = new Map();
if (options.cache) {

@@ -192,5 +225,4 @@ cache = options.cache.props;

var unmangleable = new Set();
var private_properties = new Set();
var keep_quoted_strict = options.keep_quoted === "strict";
var keep_quoted = !!options.keep_quoted;

@@ -202,9 +234,9 @@ // step 1: find candidates to mangle

|| node instanceof AST_PrivateMethod
|| node instanceof AST_PrivateGetter
|| node instanceof AST_PrivateSetter
|| node instanceof AST_DotHash
) {
private_properties.add(node.key.name);
} else if (node instanceof AST_DotHash) {
private_properties.add(node.property);
// handled by mangle_private_properties
} else if (node instanceof AST_ObjectKeyVal) {
if (typeof node.key == "string" &&
(!keep_quoted_strict || !node.quote)) {
if (typeof node.key == "string" && (!keep_quoted || !node.quote)) {
add(node.key);

@@ -214,3 +246,3 @@ }

// setter or getter, since KeyVal is handled above
if (!keep_quoted_strict || !node.key.end.quote) {
if (!keep_quoted || !node.quote) {
add(node.key.name);

@@ -228,7 +260,7 @@ }

if (declared &&
(!keep_quoted_strict || !node.quote)) {
(!keep_quoted || !node.quote)) {
add(node.property);
}
} else if (node instanceof AST_Sub) {
if (!keep_quoted_strict) {
if (!keep_quoted) {
addStrings(node.property, add);

@@ -249,9 +281,9 @@ }

|| node instanceof AST_PrivateMethod
|| node instanceof AST_PrivateGetter
|| node instanceof AST_PrivateSetter
|| node instanceof AST_DotHash
) {
node.key.name = mangle_private(node.key.name);
} else if (node instanceof AST_DotHash) {
node.property = mangle_private(node.property);
// handled by mangle_private_properties
} else if (node instanceof AST_ObjectKeyVal) {
if (typeof node.key == "string" &&
(!keep_quoted_strict || !node.quote)) {
if (typeof node.key == "string" && (!keep_quoted || !node.quote)) {
node.key = mangle(node.key);

@@ -261,10 +293,10 @@ }

// setter, getter, method or class field
if (!keep_quoted_strict || !node.key.end.quote) {
if (!keep_quoted || !node.quote) {
node.key.name = mangle(node.key.name);
}
} else if (node instanceof AST_Dot) {
if (!keep_quoted_strict || !node.quote) {
if (!keep_quoted || !node.quote) {
node.property = mangle(node.property);
}
} else if (!options.keep_quoted && node instanceof AST_Sub) {
} else if (!keep_quoted && node instanceof AST_Sub) {
node.property = mangleStrings(node.property);

@@ -326,3 +358,3 @@ } else if (node instanceof AST_Call

do {
mangled = base54(++cname);
mangled = nth_identifier.get(++cname);
} while (!can_mangle(mangled));

@@ -336,12 +368,2 @@ }

function mangle_private(name) {
let mangled = private_cache.get(name);
if (!mangled) {
mangled = base54(++cprivate);
private_cache.set(name, mangled);
}
return mangled;
}
function mangleStrings(node) {

@@ -366,2 +388,3 @@ return node.transform(new TreeTransformer(function(node) {

mangle_properties,
mangle_private_properties,
};

@@ -670,4 +670,5 @@ /***********************************************************************

var ext = scope.enclosed;
var nth_identifier = options.nth_identifier;
out: while (true) {
var m = base54(++scope.cname);
var m = nth_identifier.get(++scope.cname);
if (ALL_RESERVED_WORDS.has(m)) continue; // skip over "do"

@@ -748,2 +749,3 @@

eval : false,
nth_identifier : base54,
ie8 : false,

@@ -770,2 +772,3 @@ keep_classnames: false,

options = this._default_mangler_options(options);
var nth_identifier = options.nth_identifier;

@@ -822,3 +825,3 @@ // We only need to mangle declaration nodes. Special logic wired

do {
name = base54(++lname);
name = nth_identifier.get(++lname);
} while (ALL_RESERVED_WORDS.has(name));

@@ -885,5 +888,8 @@ node.mangled_name = name;

AST_Toplevel.DEFMETHOD("expand_names", function(options) {
base54.reset();
base54.sort();
options = this._default_mangler_options(options);
var nth_identifier = options.nth_identifier;
if (nth_identifier.reset && nth_identifier.sort) {
nth_identifier.reset();
nth_identifier.sort();
}
var avoid = this.find_colliding_names(options);

@@ -900,3 +906,3 @@ var cname = 0;

do {
name = base54(cname++);
name = nth_identifier.get(cname++);
} while (avoid.has(name) || ALL_RESERVED_WORDS.has(name));

@@ -928,2 +934,9 @@ return name;

options = this._default_mangler_options(options);
var nth_identifier = options.nth_identifier;
if (!nth_identifier.reset || !nth_identifier.consider || !nth_identifier.sort) {
// If the identifier mangler is invariant, skip computing character frequency.
return;
}
nth_identifier.reset();
try {

@@ -933,8 +946,8 @@ AST_Node.prototype.print = function(stream, force_parens) {

if (this instanceof AST_Symbol && !this.unmangleable(options)) {
base54.consider(this.name, -1);
nth_identifier.consider(this.name, -1);
} else if (options.properties) {
if (this instanceof AST_DotHash) {
base54.consider("#" + this.property, -1);
nth_identifier.consider("#" + this.property, -1);
} else if (this instanceof AST_Dot) {
base54.consider(this.property, -1);
nth_identifier.consider(this.property, -1);
} else if (this instanceof AST_Sub) {

@@ -945,11 +958,11 @@ skip_string(this.property);

};
base54.consider(this.print_to_string(), 1);
nth_identifier.consider(this.print_to_string(), 1);
} finally {
AST_Node.prototype.print = AST_Node.prototype._print;
}
base54.sort();
nth_identifier.sort();
function skip_string(node) {
if (node instanceof AST_String) {
base54.consider(node.value, -1);
nth_identifier.consider(node.value, -1);
} else if (node instanceof AST_Conditional) {

@@ -978,15 +991,16 @@ skip_string(node.consequent);

}
base54.consider = function(str, delta) {
function consider(str, delta) {
for (var i = str.length; --i >= 0;) {
frequency.set(str[i], frequency.get(str[i]) + delta);
}
};
}
function compare(a, b) {
return frequency.get(b) - frequency.get(a);
}
base54.sort = function() {
function sort() {
chars = mergeSort(leading, compare).concat(mergeSort(digits, compare));
};
base54.reset = reset;
}
// Ensure this is in a usable initial state.
reset();
sort();
function base54(num) {

@@ -1003,3 +1017,9 @@ var ret = "", base = 54;

}
return base54;
return {
get: base54,
consider,
reset,
sort
};
})();

@@ -1006,0 +1026,0 @@

@@ -60,3 +60,2 @@ /***********************************************************************

AST_Do,
AST_Dot,
AST_Exit,

@@ -78,2 +77,3 @@ AST_Expansion,

AST_PrefixedTemplateString,
AST_PropAccess,
AST_Sequence,

@@ -233,3 +233,3 @@ AST_SimpleStatement,

def_transform(AST_Dot, function(self, tw) {
def_transform(AST_PropAccess, function(self, tw) {
self.expression = self.expression.transform(tw);

@@ -236,0 +236,0 @@ });

@@ -7,3 +7,3 @@ {

"license": "BSD-2-Clause",
"version": "5.7.2",
"version": "5.8.0",
"engines": {

@@ -49,15 +49,15 @@ "node": ">=10"

"source-map": "~0.7.2",
"source-map-support": "~0.5.19"
"source-map-support": "~0.5.20"
},
"devDependencies": {
"@ls-lint/ls-lint": "^1.9.2",
"acorn": "^8.0.5",
"astring": "^1.6.2",
"eslint": "^7.19.0",
"eslump": "^2.0.0",
"@ls-lint/ls-lint": "^1.10.0",
"acorn": "^8.5.0",
"astring": "^1.7.5",
"eslint": "^7.32.0",
"eslump": "^3.0.0",
"esm": "^3.2.25",
"mocha": "^8.2.1",
"mocha": "^9.1.1",
"pre-commit": "^1.2.2",
"rimraf": "^3.0.2",
"rollup": "2.38.4",
"rollup": "2.56.3",
"semver": "^7.3.4"

@@ -64,0 +64,0 @@ },

@@ -24,4 +24,4 @@ <h1><img src="https://terser.org/img/terser-banner-logo.png" alt="Terser" width="400"></h1>

[downloads-url]: https://npmjs.org/package/terser
[travis-image]: https://travis-ci.com/terser/terser.svg?branch=master
[travis-url]: https://travis-ci.com/terser/terser
[travis-image]: https://app.travis-ci.com/terser/terser.svg?branch=master
[travis-url]: https://app.travis-ci.com/github/terser/terser
[opencollective-contributors]: https://opencollective.com/terser/tiers/badge.svg

@@ -902,2 +902,8 @@ [opencollective-url]: https://opencollective.com/terser

- `nth_identifier` (default: an internal mangler that weights based on character
frequency analysis) -- Pass an object with a `get(n)` function that converts an
ordinal into the nth most favored (usually shortest) identifier.
Optionally also provide `reset()`, `sort()`, and `consider(chars, delta)` to
use character frequency analysis of the source code.
- `reserved` (default `[]`) -- Pass an array of identifiers that should be

@@ -949,2 +955,8 @@ excluded from mangling. Example: `["foo", "bar"]`.

- `nth_identifer` (default: an internal mangler that weights based on character
frequency analysis) -- Pass an object with a `get(n)` function that converts an
ordinal into the nth most favored (usually shortest) identifier.
Optionally also provide `reset()`, `sort()`, and `consider(chars, delta)` to
use character frequency analysis of the source code.
- `regex` (default: `null`) — Pass a [RegExp literal or pattern string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) to only mangle property matching the regular expression.

@@ -1084,2 +1096,3 @@

- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[ 1, 2, 3 ]`
- `Array.from([1, 2, 3])` → `[1, 2, 3]`
- `new Object()` → `{}`

@@ -1086,0 +1099,0 @@ - `String(exp)` or `exp.toString()` → `"" + exp`

@@ -83,2 +83,3 @@ /// <reference lib="es2015" />

module?: boolean;
nth_identifier?: SimpleIdentifierMangler | WeightedIdentifierMangler;
properties?: boolean | ManglePropertiesOptions;

@@ -90,2 +91,36 @@ reserved?: string[];

/**
* An identifier mangler for which the output is invariant with respect to the source code.
*/
export interface SimpleIdentifierMangler {
/**
* Obtains the nth most favored (usually shortest) identifier to rename a variable to.
* The mangler will increment n and retry until the return value is not in use in scope, and is not a reserved word.
* This function is expected to be stable; Evaluating get(n) === get(n) should always return true.
* @param n The ordinal of the identifier.
*/
get(n: number): string;
}
/**
* An identifier mangler that leverages character frequency analysis to determine identifier precedence.
*/
export interface WeightedIdentifierMangler extends SimpleIdentifierMangler {
/**
* Modifies the internal weighting of the input characters by the specified delta.
* Will be invoked on the entire printed AST, and then deduct mangleable identifiers.
* @param chars The characters to modify the weighting of.
* @param delta The numeric weight to add to the characters.
*/
consider(chars: string, delta: number): number;
/**
* Resets character weights.
*/
reset(): void;
/**
* Sorts identifiers by character frequency, in preparation for calls to get(n).
*/
sort(): void;
}
export interface ManglePropertiesOptions {

@@ -95,2 +130,3 @@ builtins?: boolean;

keep_quoted?: boolean | 'strict';
nth_identifier?: SimpleIdentifierMangler | WeightedIdentifierMangler;
regex?: RegExp | string;

@@ -97,0 +133,0 @@ reserved?: string[];

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc