chore: update deps
This commit is contained in:
3382
node_modules/terser/lib/ast.js
generated
vendored
Normal file
3382
node_modules/terser/lib/ast.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
482
node_modules/terser/lib/cli.js
generated
vendored
Normal file
482
node_modules/terser/lib/cli.js
generated
vendored
Normal file
@ -0,0 +1,482 @@
|
||||
import { minify, _default_options } from "../main.js";
|
||||
import { parse } from "./parse.js";
|
||||
import {
|
||||
AST_Assign,
|
||||
AST_Array,
|
||||
AST_Constant,
|
||||
AST_Node,
|
||||
AST_PropAccess,
|
||||
AST_RegExp,
|
||||
AST_Sequence,
|
||||
AST_Symbol,
|
||||
AST_Token,
|
||||
walk
|
||||
} from "./ast.js";
|
||||
import { OutputStream } from "./output.js";
|
||||
|
||||
export async function run_cli({ program, packageJson, fs, path }) {
|
||||
const skip_keys = new Set([ "cname", "parent_scope", "scope", "uses_eval", "uses_with" ]);
|
||||
var files = {};
|
||||
var options = {
|
||||
compress: false,
|
||||
mangle: false
|
||||
};
|
||||
const default_options = await _default_options();
|
||||
program.version(packageJson.name + " " + packageJson.version);
|
||||
program.parseArgv = program.parse;
|
||||
program.parse = undefined;
|
||||
|
||||
if (process.argv.includes("ast")) program.helpInformation = describe_ast;
|
||||
else if (process.argv.includes("options")) program.helpInformation = function() {
|
||||
var text = [];
|
||||
for (var option in default_options) {
|
||||
text.push("--" + (option === "sourceMap" ? "source-map" : option) + " options:");
|
||||
text.push(format_object(default_options[option]));
|
||||
text.push("");
|
||||
}
|
||||
return text.join("\n");
|
||||
};
|
||||
|
||||
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
|
||||
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js());
|
||||
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
|
||||
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
||||
program.option("-f, --format [options]", "Format options.", parse_js());
|
||||
program.option("-b, --beautify [options]", "Alias for --format.", parse_js());
|
||||
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
||||
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
||||
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
||||
program.option("-d, --define <expr>[=value]", "Global definitions.", parse_js("define"));
|
||||
program.option("--ecma <version>", "Specify ECMAScript release: 5, 2015, 2016 or 2017...");
|
||||
program.option("-e, --enclose [arg[,...][:value[,...]]]", "Embed output in a big function with configurable arguments and values.");
|
||||
program.option("--ie8", "Support non-standard Internet Explorer 8.");
|
||||
program.option("--keep-classnames", "Do not mangle/drop class names.");
|
||||
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
|
||||
program.option("--module", "Input is an ES6 module");
|
||||
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
||||
program.option("--rename", "Force symbol expansion.");
|
||||
program.option("--no-rename", "Disable symbol expansion.");
|
||||
program.option("--safari10", "Support non-standard Safari 10.");
|
||||
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_js());
|
||||
program.option("--timings", "Display operations run time on STDERR.");
|
||||
program.option("--toplevel", "Compress and/or mangle variables in toplevel scope.");
|
||||
program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
|
||||
program.arguments("[files...]").parseArgv(process.argv);
|
||||
if (program.configFile) {
|
||||
options = JSON.parse(read_file(program.configFile));
|
||||
}
|
||||
if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
||||
fatal("ERROR: cannot write source map to STDOUT");
|
||||
}
|
||||
|
||||
[
|
||||
"compress",
|
||||
"enclose",
|
||||
"ie8",
|
||||
"mangle",
|
||||
"module",
|
||||
"safari10",
|
||||
"sourceMap",
|
||||
"toplevel",
|
||||
"wrap"
|
||||
].forEach(function(name) {
|
||||
if (name in program) {
|
||||
options[name] = program[name];
|
||||
}
|
||||
});
|
||||
|
||||
if ("ecma" in program) {
|
||||
if (program.ecma != (program.ecma | 0)) fatal("ERROR: ecma must be an integer");
|
||||
const ecma = program.ecma | 0;
|
||||
if (ecma > 5 && ecma < 2015)
|
||||
options.ecma = ecma + 2009;
|
||||
else
|
||||
options.ecma = ecma;
|
||||
}
|
||||
if (program.format || program.beautify) {
|
||||
const chosenOption = program.format || program.beautify;
|
||||
options.format = typeof chosenOption === "object" ? chosenOption : {};
|
||||
}
|
||||
if (program.comments) {
|
||||
if (typeof options.format != "object") options.format = {};
|
||||
options.format.comments = typeof program.comments == "string" ? (program.comments == "false" ? false : program.comments) : "some";
|
||||
}
|
||||
if (program.define) {
|
||||
if (typeof options.compress != "object") options.compress = {};
|
||||
if (typeof options.compress.global_defs != "object") options.compress.global_defs = {};
|
||||
for (var expr in program.define) {
|
||||
options.compress.global_defs[expr] = program.define[expr];
|
||||
}
|
||||
}
|
||||
if (program.keepClassnames) {
|
||||
options.keep_classnames = true;
|
||||
}
|
||||
if (program.keepFnames) {
|
||||
options.keep_fnames = true;
|
||||
}
|
||||
if (program.mangleProps) {
|
||||
if (program.mangleProps.domprops) {
|
||||
delete program.mangleProps.domprops;
|
||||
} else {
|
||||
if (typeof program.mangleProps != "object") program.mangleProps = {};
|
||||
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
|
||||
}
|
||||
if (typeof options.mangle != "object") options.mangle = {};
|
||||
options.mangle.properties = program.mangleProps;
|
||||
}
|
||||
if (program.nameCache) {
|
||||
options.nameCache = JSON.parse(read_file(program.nameCache, "{}"));
|
||||
}
|
||||
if (program.output == "ast") {
|
||||
options.format = {
|
||||
ast: true,
|
||||
code: false
|
||||
};
|
||||
}
|
||||
if (program.parse) {
|
||||
if (!program.parse.acorn && !program.parse.spidermonkey) {
|
||||
options.parse = program.parse;
|
||||
} else if (program.sourceMap && program.sourceMap.content == "inline") {
|
||||
fatal("ERROR: inline source map only works with built-in parser");
|
||||
}
|
||||
}
|
||||
if (~program.rawArgs.indexOf("--rename")) {
|
||||
options.rename = true;
|
||||
} else if (!program.rename) {
|
||||
options.rename = false;
|
||||
}
|
||||
|
||||
let convert_path = name => name;
|
||||
if (typeof program.sourceMap == "object" && "base" in program.sourceMap) {
|
||||
convert_path = function() {
|
||||
var base = program.sourceMap.base;
|
||||
delete options.sourceMap.base;
|
||||
return function(name) {
|
||||
return path.relative(base, name);
|
||||
};
|
||||
}();
|
||||
}
|
||||
|
||||
let filesList;
|
||||
if (options.files && options.files.length) {
|
||||
filesList = options.files;
|
||||
|
||||
delete options.files;
|
||||
} else if (program.args.length) {
|
||||
filesList = program.args;
|
||||
}
|
||||
|
||||
if (filesList) {
|
||||
simple_glob(filesList).forEach(function(name) {
|
||||
files[convert_path(name)] = read_file(name);
|
||||
});
|
||||
} else {
|
||||
await new Promise((resolve) => {
|
||||
var chunks = [];
|
||||
process.stdin.setEncoding("utf8");
|
||||
process.stdin.on("data", function(chunk) {
|
||||
chunks.push(chunk);
|
||||
}).on("end", function() {
|
||||
files = [ chunks.join("") ];
|
||||
resolve();
|
||||
});
|
||||
process.stdin.resume();
|
||||
});
|
||||
}
|
||||
|
||||
await run_cli();
|
||||
|
||||
function convert_ast(fn) {
|
||||
return AST_Node.from_mozilla_ast(Object.keys(files).reduce(fn, null));
|
||||
}
|
||||
|
||||
async function run_cli() {
|
||||
var content = program.sourceMap && program.sourceMap.content;
|
||||
if (content && content !== "inline") {
|
||||
options.sourceMap.content = read_file(content, content);
|
||||
}
|
||||
if (program.timings) options.timings = true;
|
||||
|
||||
try {
|
||||
if (program.parse) {
|
||||
if (program.parse.acorn) {
|
||||
files = convert_ast(function(toplevel, name) {
|
||||
return require("acorn").parse(files[name], {
|
||||
ecmaVersion: 2018,
|
||||
locations: true,
|
||||
program: toplevel,
|
||||
sourceFile: name,
|
||||
sourceType: options.module || program.parse.module ? "module" : "script"
|
||||
});
|
||||
});
|
||||
} else if (program.parse.spidermonkey) {
|
||||
files = convert_ast(function(toplevel, name) {
|
||||
var obj = JSON.parse(files[name]);
|
||||
if (!toplevel) return obj;
|
||||
toplevel.body = toplevel.body.concat(obj.body);
|
||||
return toplevel;
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
fatal(ex);
|
||||
}
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await minify(files, options, fs);
|
||||
} catch (ex) {
|
||||
if (ex.name == "SyntaxError") {
|
||||
print_error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
|
||||
var col = ex.col;
|
||||
var lines = files[ex.filename].split(/\r?\n/);
|
||||
var line = lines[ex.line - 1];
|
||||
if (!line && !col) {
|
||||
line = lines[ex.line - 2];
|
||||
col = line.length;
|
||||
}
|
||||
if (line) {
|
||||
var limit = 70;
|
||||
if (col > limit) {
|
||||
line = line.slice(col - limit);
|
||||
col = limit;
|
||||
}
|
||||
print_error(line.slice(0, 80));
|
||||
print_error(line.slice(0, col).replace(/\S/g, " ") + "^");
|
||||
}
|
||||
}
|
||||
if (ex.defs) {
|
||||
print_error("Supported options:");
|
||||
print_error(format_object(ex.defs));
|
||||
}
|
||||
fatal(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (program.output == "ast") {
|
||||
if (!options.compress && !options.mangle) {
|
||||
result.ast.figure_out_scope({});
|
||||
}
|
||||
console.log(JSON.stringify(result.ast, function(key, value) {
|
||||
if (value) switch (key) {
|
||||
case "thedef":
|
||||
return symdef(value);
|
||||
case "enclosed":
|
||||
return value.length ? value.map(symdef) : undefined;
|
||||
case "variables":
|
||||
case "globals":
|
||||
return value.size ? collect_from_map(value, symdef) : undefined;
|
||||
}
|
||||
if (skip_keys.has(key)) return;
|
||||
if (value instanceof AST_Token) return;
|
||||
if (value instanceof Map) return;
|
||||
if (value instanceof AST_Node) {
|
||||
var result = {
|
||||
_class: "AST_" + value.TYPE
|
||||
};
|
||||
if (value.block_scope) {
|
||||
result.variables = value.block_scope.variables;
|
||||
result.enclosed = value.block_scope.enclosed;
|
||||
}
|
||||
value.CTOR.PROPS.forEach(function(prop) {
|
||||
if (prop !== "block_scope") {
|
||||
result[prop] = value[prop];
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
return value;
|
||||
}, 2));
|
||||
} else if (program.output == "spidermonkey") {
|
||||
try {
|
||||
const minified = await minify(
|
||||
result.code,
|
||||
{
|
||||
compress: false,
|
||||
mangle: false,
|
||||
format: {
|
||||
ast: true,
|
||||
code: false
|
||||
}
|
||||
},
|
||||
fs
|
||||
);
|
||||
console.log(JSON.stringify(minified.ast.to_mozilla_ast(), null, 2));
|
||||
} catch (ex) {
|
||||
fatal(ex);
|
||||
return;
|
||||
}
|
||||
} else if (program.output) {
|
||||
fs.mkdirSync(path.dirname(program.output), { recursive: true });
|
||||
fs.writeFileSync(program.output, result.code);
|
||||
if (options.sourceMap && options.sourceMap.url !== "inline" && result.map) {
|
||||
fs.writeFileSync(program.output + ".map", result.map);
|
||||
}
|
||||
} else {
|
||||
console.log(result.code);
|
||||
}
|
||||
if (program.nameCache) {
|
||||
fs.writeFileSync(program.nameCache, JSON.stringify(options.nameCache));
|
||||
}
|
||||
if (result.timings) for (var phase in result.timings) {
|
||||
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
||||
}
|
||||
}
|
||||
|
||||
function fatal(message) {
|
||||
if (message instanceof Error) message = message.stack.replace(/^\S*?Error:/, "ERROR:");
|
||||
print_error(message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// A file glob function that only supports "*" and "?" wildcards in the basename.
|
||||
// Example: "foo/bar/*baz??.*.js"
|
||||
// Argument `glob` may be a string or an array of strings.
|
||||
// Returns an array of strings. Garbage in, garbage out.
|
||||
function simple_glob(glob) {
|
||||
if (Array.isArray(glob)) {
|
||||
return [].concat.apply([], glob.map(simple_glob));
|
||||
}
|
||||
if (glob && glob.match(/[*?]/)) {
|
||||
var dir = path.dirname(glob);
|
||||
try {
|
||||
var entries = fs.readdirSync(dir);
|
||||
} catch (ex) {}
|
||||
if (entries) {
|
||||
var pattern = "^" + path.basename(glob)
|
||||
.replace(/[.+^$[\]\\(){}]/g, "\\$&")
|
||||
.replace(/\*/g, "[^/\\\\]*")
|
||||
.replace(/\?/g, "[^/\\\\]") + "$";
|
||||
var mod = process.platform === "win32" ? "i" : "";
|
||||
var rx = new RegExp(pattern, mod);
|
||||
var results = entries.filter(function(name) {
|
||||
return rx.test(name);
|
||||
}).map(function(name) {
|
||||
return path.join(dir, name);
|
||||
});
|
||||
if (results.length) return results;
|
||||
}
|
||||
}
|
||||
return [ glob ];
|
||||
}
|
||||
|
||||
function read_file(path, default_value) {
|
||||
try {
|
||||
return fs.readFileSync(path, "utf8");
|
||||
} catch (ex) {
|
||||
if ((ex.code == "ENOENT" || ex.code == "ENAMETOOLONG") && default_value != null) return default_value;
|
||||
fatal(ex);
|
||||
}
|
||||
}
|
||||
|
||||
function parse_js(flag) {
|
||||
return function(value, options) {
|
||||
options = options || {};
|
||||
try {
|
||||
walk(parse(value, { expression: true }), node => {
|
||||
if (node instanceof AST_Assign) {
|
||||
var name = node.left.print_to_string();
|
||||
var value = node.right;
|
||||
if (flag) {
|
||||
options[name] = value;
|
||||
} else if (value instanceof AST_Array) {
|
||||
options[name] = value.elements.map(to_string);
|
||||
} else if (value instanceof AST_RegExp) {
|
||||
value = value.value;
|
||||
options[name] = new RegExp(value.source, value.flags);
|
||||
} else {
|
||||
options[name] = to_string(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Symbol || node instanceof AST_PropAccess) {
|
||||
var name = node.print_to_string();
|
||||
options[name] = true;
|
||||
return true;
|
||||
}
|
||||
if (!(node instanceof AST_Sequence)) throw node;
|
||||
|
||||
function to_string(value) {
|
||||
return value instanceof AST_Constant ? value.getValue() : value.print_to_string({
|
||||
quote_keys: true
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch(ex) {
|
||||
if (flag) {
|
||||
fatal("Error parsing arguments for '" + flag + "': " + value);
|
||||
} else {
|
||||
options[value] = null;
|
||||
}
|
||||
}
|
||||
return options;
|
||||
};
|
||||
}
|
||||
|
||||
function symdef(def) {
|
||||
var ret = (1e6 + def.id) + " " + def.name;
|
||||
if (def.mangled_name) ret += " " + def.mangled_name;
|
||||
return ret;
|
||||
}
|
||||
|
||||
function collect_from_map(map, callback) {
|
||||
var result = [];
|
||||
map.forEach(function (def) {
|
||||
result.push(callback(def));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function format_object(obj) {
|
||||
var lines = [];
|
||||
var padding = "";
|
||||
Object.keys(obj).map(function(name) {
|
||||
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
|
||||
return [ name, JSON.stringify(obj[name]) ];
|
||||
}).forEach(function(tokens) {
|
||||
lines.push(" " + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
||||
});
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
function print_error(msg) {
|
||||
process.stderr.write(msg);
|
||||
process.stderr.write("\n");
|
||||
}
|
||||
|
||||
function describe_ast() {
|
||||
var out = OutputStream({ beautify: true });
|
||||
function doitem(ctor) {
|
||||
out.print("AST_" + ctor.TYPE);
|
||||
const props = ctor.SELF_PROPS.filter(prop => !/^\$/.test(prop));
|
||||
|
||||
if (props.length > 0) {
|
||||
out.space();
|
||||
out.with_parens(function() {
|
||||
props.forEach(function(prop, i) {
|
||||
if (i) out.space();
|
||||
out.print(prop);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (ctor.documentation) {
|
||||
out.space();
|
||||
out.print_string(ctor.documentation);
|
||||
}
|
||||
|
||||
if (ctor.SUBCLASSES.length > 0) {
|
||||
out.space();
|
||||
out.with_block(function() {
|
||||
ctor.SUBCLASSES.forEach(function(ctor) {
|
||||
out.indent();
|
||||
doitem(ctor);
|
||||
out.newline();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
doitem(AST_Node);
|
||||
return out + "\n";
|
||||
}
|
||||
}
|
373
node_modules/terser/lib/compress/common.js
generated
vendored
Normal file
373
node_modules/terser/lib/compress/common.js
generated
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
import {
|
||||
AST_Array,
|
||||
AST_Arrow,
|
||||
AST_BigInt,
|
||||
AST_BlockStatement,
|
||||
AST_Call,
|
||||
AST_Chain,
|
||||
AST_Class,
|
||||
AST_Const,
|
||||
AST_Constant,
|
||||
AST_DefClass,
|
||||
AST_Defun,
|
||||
AST_EmptyStatement,
|
||||
AST_Export,
|
||||
AST_False,
|
||||
AST_Function,
|
||||
AST_Import,
|
||||
AST_Infinity,
|
||||
AST_LabeledStatement,
|
||||
AST_Lambda,
|
||||
AST_Let,
|
||||
AST_LoopControl,
|
||||
AST_NaN,
|
||||
AST_Node,
|
||||
AST_Null,
|
||||
AST_Number,
|
||||
AST_Object,
|
||||
AST_ObjectKeyVal,
|
||||
AST_PropAccess,
|
||||
AST_RegExp,
|
||||
AST_Scope,
|
||||
AST_Sequence,
|
||||
AST_SimpleStatement,
|
||||
AST_Statement,
|
||||
AST_String,
|
||||
AST_SymbolRef,
|
||||
AST_True,
|
||||
AST_UnaryPrefix,
|
||||
AST_Undefined,
|
||||
|
||||
TreeWalker,
|
||||
walk,
|
||||
walk_abort,
|
||||
walk_parent,
|
||||
} from "../ast.js";
|
||||
import { make_node, regexp_source_fix, string_template, makePredicate } from "../utils/index.js";
|
||||
import { first_in_statement } from "../utils/first_in_statement.js";
|
||||
import { has_flag, TOP } from "./compressor-flags.js";
|
||||
|
||||
export function merge_sequence(array, node) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
array.push(...node.expressions);
|
||||
} else {
|
||||
array.push(node);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
export function make_sequence(orig, expressions) {
|
||||
if (expressions.length == 1) return expressions[0];
|
||||
if (expressions.length == 0) throw new Error("trying to create a sequence with length zero!");
|
||||
return make_node(AST_Sequence, orig, {
|
||||
expressions: expressions.reduce(merge_sequence, [])
|
||||
});
|
||||
}
|
||||
|
||||
export function make_empty_function(self) {
|
||||
return make_node(AST_Function, self, {
|
||||
uses_arguments: false,
|
||||
argnames: [],
|
||||
body: [],
|
||||
is_generator: false,
|
||||
async: false,
|
||||
variables: new Map(),
|
||||
uses_with: false,
|
||||
uses_eval: false,
|
||||
parent_scope: null,
|
||||
enclosed: [],
|
||||
cname: 0,
|
||||
block_scope: undefined,
|
||||
});
|
||||
}
|
||||
|
||||
export function make_node_from_constant(val, orig) {
|
||||
switch (typeof val) {
|
||||
case "string":
|
||||
return make_node(AST_String, orig, {
|
||||
value: val
|
||||
});
|
||||
case "number":
|
||||
if (isNaN(val)) return make_node(AST_NaN, orig);
|
||||
if (isFinite(val)) {
|
||||
return 1 / val < 0 ? make_node(AST_UnaryPrefix, orig, {
|
||||
operator: "-",
|
||||
expression: make_node(AST_Number, orig, { value: -val })
|
||||
}) : make_node(AST_Number, orig, { value: val });
|
||||
}
|
||||
return val < 0 ? make_node(AST_UnaryPrefix, orig, {
|
||||
operator: "-",
|
||||
expression: make_node(AST_Infinity, orig)
|
||||
}) : make_node(AST_Infinity, orig);
|
||||
case "bigint":
|
||||
return make_node(AST_BigInt, orig, { value: val.toString() });
|
||||
case "boolean":
|
||||
return make_node(val ? AST_True : AST_False, orig);
|
||||
case "undefined":
|
||||
return make_node(AST_Undefined, orig);
|
||||
default:
|
||||
if (val === null) {
|
||||
return make_node(AST_Null, orig, { value: null });
|
||||
}
|
||||
if (val instanceof RegExp) {
|
||||
return make_node(AST_RegExp, orig, {
|
||||
value: {
|
||||
source: regexp_source_fix(val.source),
|
||||
flags: val.flags
|
||||
}
|
||||
});
|
||||
}
|
||||
throw new Error(string_template("Can't handle constant of type: {type}", {
|
||||
type: typeof val
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
export function best_of_expression(ast1, ast2) {
|
||||
return ast1.size() > ast2.size() ? ast2 : ast1;
|
||||
}
|
||||
|
||||
export function best_of_statement(ast1, ast2) {
|
||||
return best_of_expression(
|
||||
make_node(AST_SimpleStatement, ast1, {
|
||||
body: ast1
|
||||
}),
|
||||
make_node(AST_SimpleStatement, ast2, {
|
||||
body: ast2
|
||||
})
|
||||
).body;
|
||||
}
|
||||
|
||||
/** Find which node is smaller, and return that */
|
||||
export function best_of(compressor, ast1, ast2) {
|
||||
if (first_in_statement(compressor)) {
|
||||
return best_of_statement(ast1, ast2);
|
||||
} else {
|
||||
return best_of_expression(ast1, ast2);
|
||||
}
|
||||
}
|
||||
|
||||
/** Simplify an object property's key, if possible */
|
||||
export function get_simple_key(key) {
|
||||
if (key instanceof AST_Constant) {
|
||||
return key.getValue();
|
||||
}
|
||||
if (key instanceof AST_UnaryPrefix
|
||||
&& key.operator == "void"
|
||||
&& key.expression instanceof AST_Constant) {
|
||||
return;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
export function read_property(obj, key) {
|
||||
key = get_simple_key(key);
|
||||
if (key instanceof AST_Node) return;
|
||||
|
||||
var value;
|
||||
if (obj instanceof AST_Array) {
|
||||
var elements = obj.elements;
|
||||
if (key == "length") return make_node_from_constant(elements.length, obj);
|
||||
if (typeof key == "number" && key in elements) value = elements[key];
|
||||
} else if (obj instanceof AST_Object) {
|
||||
key = "" + key;
|
||||
var props = obj.properties;
|
||||
for (var i = props.length; --i >= 0;) {
|
||||
var prop = props[i];
|
||||
if (!(prop instanceof AST_ObjectKeyVal)) return;
|
||||
if (!value && props[i].key === key) value = props[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
return value instanceof AST_SymbolRef && value.fixed_value() || value;
|
||||
}
|
||||
|
||||
export function has_break_or_continue(loop, parent) {
|
||||
var found = false;
|
||||
var tw = new TreeWalker(function(node) {
|
||||
if (found || node instanceof AST_Scope) return true;
|
||||
if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === loop) {
|
||||
return found = true;
|
||||
}
|
||||
});
|
||||
if (parent instanceof AST_LabeledStatement) tw.push(parent);
|
||||
tw.push(loop);
|
||||
loop.body.walk(tw);
|
||||
return found;
|
||||
}
|
||||
|
||||
// we shouldn't compress (1,func)(something) to
|
||||
// func(something) because that changes the meaning of
|
||||
// the func (becomes lexical instead of global).
|
||||
export function maintain_this_binding(parent, orig, val) {
|
||||
if (requires_sequence_to_maintain_binding(parent, orig, val)) {
|
||||
const zero = make_node(AST_Number, orig, { value: 0 });
|
||||
return make_sequence(orig, [ zero, val ]);
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
/** Detect (1, x.noThis)(), (0, eval)(), which need sequences */
|
||||
export function requires_sequence_to_maintain_binding(parent, orig, val) {
|
||||
return (
|
||||
parent instanceof AST_UnaryPrefix && parent.operator == "delete"
|
||||
|| parent instanceof AST_Call && parent.expression === orig
|
||||
&& (
|
||||
val instanceof AST_Chain
|
||||
|| val instanceof AST_PropAccess
|
||||
|| val instanceof AST_SymbolRef && val.name == "eval"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function is_func_expr(node) {
|
||||
return node instanceof AST_Arrow || node instanceof AST_Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine whether the node can benefit from negation.
|
||||
* Not the case with arrow functions (you need an extra set of parens). */
|
||||
export function is_iife_call(node) {
|
||||
if (node.TYPE != "Call") return false;
|
||||
return node.expression instanceof AST_Function || is_iife_call(node.expression);
|
||||
}
|
||||
|
||||
export function is_empty(thing) {
|
||||
if (thing === null) return true;
|
||||
if (thing instanceof AST_EmptyStatement) return true;
|
||||
if (thing instanceof AST_BlockStatement) return thing.body.length == 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
export const identifier_atom = makePredicate("Infinity NaN undefined");
|
||||
export function is_identifier_atom(node) {
|
||||
return node instanceof AST_Infinity
|
||||
|| node instanceof AST_NaN
|
||||
|| node instanceof AST_Undefined;
|
||||
}
|
||||
|
||||
/** Check if this is a SymbolRef node which has one def of a certain AST type */
|
||||
export function is_ref_of(ref, type) {
|
||||
if (!(ref instanceof AST_SymbolRef)) return false;
|
||||
var orig = ref.definition().orig;
|
||||
for (var i = orig.length; --i >= 0;) {
|
||||
if (orig[i] instanceof type) return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**Can we turn { block contents... } into just the block contents ?
|
||||
* Not if one of these is inside.
|
||||
**/
|
||||
export function can_be_evicted_from_block(node) {
|
||||
return !(
|
||||
node instanceof AST_DefClass ||
|
||||
node instanceof AST_Defun ||
|
||||
node instanceof AST_Let ||
|
||||
node instanceof AST_Const ||
|
||||
node instanceof AST_Export ||
|
||||
node instanceof AST_Import
|
||||
);
|
||||
}
|
||||
|
||||
export function as_statement_array(thing) {
|
||||
if (thing === null) return [];
|
||||
if (thing instanceof AST_BlockStatement) return thing.body;
|
||||
if (thing instanceof AST_EmptyStatement) return [];
|
||||
if (thing instanceof AST_Statement) return [ thing ];
|
||||
throw new Error("Can't convert thing to statement array");
|
||||
}
|
||||
|
||||
export function is_reachable(scope_node, defs) {
|
||||
const find_ref = node => {
|
||||
if (node instanceof AST_SymbolRef && defs.includes(node.definition())) {
|
||||
return walk_abort;
|
||||
}
|
||||
};
|
||||
|
||||
return walk_parent(scope_node, (node, info) => {
|
||||
if (node instanceof AST_Scope && node !== scope_node) {
|
||||
var parent = info.parent();
|
||||
|
||||
if (
|
||||
parent instanceof AST_Call
|
||||
&& parent.expression === node
|
||||
// Async/Generators aren't guaranteed to sync evaluate all of
|
||||
// their body steps, so it's possible they close over the variable.
|
||||
&& !(node.async || node.is_generator)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (walk(node, find_ref)) return walk_abort;
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Check if a ref refers to the name of a function/class it's defined within */
|
||||
export function is_recursive_ref(tw, def) {
|
||||
var node;
|
||||
for (var i = 0; node = tw.parent(i); i++) {
|
||||
if (node instanceof AST_Lambda || node instanceof AST_Class) {
|
||||
var name = node.name;
|
||||
if (name && name.definition() === def) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO this only works with AST_Defun, shouldn't it work for other ways of defining functions?
|
||||
export function retain_top_func(fn, compressor) {
|
||||
return compressor.top_retain
|
||||
&& fn instanceof AST_Defun
|
||||
&& has_flag(fn, TOP)
|
||||
&& fn.name
|
||||
&& compressor.top_retain(fn.name.definition());
|
||||
}
|
62
node_modules/terser/lib/compress/compressor-flags.js
generated
vendored
Normal file
62
node_modules/terser/lib/compress/compressor-flags.js
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
// bitfield flags to be stored in node.flags.
|
||||
// These are set and unset during compression, and store information in the node without requiring multiple fields.
|
||||
export const UNUSED = 0b00000001;
|
||||
export const TRUTHY = 0b00000010;
|
||||
export const FALSY = 0b00000100;
|
||||
export const UNDEFINED = 0b00001000;
|
||||
export const INLINED = 0b00010000;
|
||||
// Nodes to which values are ever written. Used when keep_assign is part of the unused option string.
|
||||
export const WRITE_ONLY = 0b00100000;
|
||||
|
||||
// information specific to a single compression pass
|
||||
export const SQUEEZED = 0b0000000100000000;
|
||||
export const OPTIMIZED = 0b0000001000000000;
|
||||
export const TOP = 0b0000010000000000;
|
||||
export const CLEAR_BETWEEN_PASSES = SQUEEZED | OPTIMIZED | TOP;
|
||||
|
||||
export const has_flag = (node, flag) => node.flags & flag;
|
||||
export const set_flag = (node, flag) => { node.flags |= flag; };
|
||||
export const clear_flag = (node, flag) => { node.flags &= ~flag; };
|
387
node_modules/terser/lib/compress/drop-side-effect-free.js
generated
vendored
Normal file
387
node_modules/terser/lib/compress/drop-side-effect-free.js
generated
vendored
Normal file
@ -0,0 +1,387 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
import {
|
||||
AST_Accessor,
|
||||
AST_Array,
|
||||
AST_Arrow,
|
||||
AST_Assign,
|
||||
AST_Binary,
|
||||
AST_Call,
|
||||
AST_Chain,
|
||||
AST_Class,
|
||||
AST_ClassPrivateProperty,
|
||||
AST_ClassProperty,
|
||||
AST_ClassStaticBlock,
|
||||
AST_ConciseMethod,
|
||||
AST_Conditional,
|
||||
AST_Constant,
|
||||
AST_DefClass,
|
||||
AST_Dot,
|
||||
AST_Expansion,
|
||||
AST_Function,
|
||||
AST_Node,
|
||||
AST_Number,
|
||||
AST_Object,
|
||||
AST_ObjectGetter,
|
||||
AST_ObjectKeyVal,
|
||||
AST_ObjectSetter,
|
||||
AST_PrivateGetter,
|
||||
AST_PrivateSetter,
|
||||
AST_PrivateMethod,
|
||||
AST_PropAccess,
|
||||
AST_Scope,
|
||||
AST_Sequence,
|
||||
AST_SimpleStatement,
|
||||
AST_Sub,
|
||||
AST_SymbolRef,
|
||||
AST_TemplateSegment,
|
||||
AST_TemplateString,
|
||||
AST_This,
|
||||
AST_Unary,
|
||||
} from "../ast.js";
|
||||
import { make_node, return_null, return_this } from "../utils/index.js";
|
||||
import { first_in_statement } from "../utils/first_in_statement.js";
|
||||
|
||||
import { pure_prop_access_globals } from "./native-objects.js";
|
||||
import { lazy_op, unary_side_effects, is_nullish_shortcircuited } from "./inference.js";
|
||||
import { WRITE_ONLY, set_flag, clear_flag } from "./compressor-flags.js";
|
||||
import { make_sequence, is_func_expr, is_iife_call } from "./common.js";
|
||||
|
||||
// AST_Node#drop_side_effect_free() gets called when we don't care about the value,
|
||||
// only about side effects. We'll be defining this method for each node type in this module
|
||||
//
|
||||
// Examples:
|
||||
// foo++ -> foo++
|
||||
// 1 + func() -> func()
|
||||
// 10 -> (nothing)
|
||||
// knownPureFunc(foo++) -> foo++
|
||||
|
||||
function def_drop_side_effect_free(node_or_nodes, func) {
|
||||
for (const node of [].concat(node_or_nodes)) {
|
||||
node.DEFMETHOD("drop_side_effect_free", func);
|
||||
}
|
||||
}
|
||||
|
||||
// Drop side-effect-free elements from an array of expressions.
|
||||
// Returns an array of expressions with side-effects or null
|
||||
// if all elements were dropped. Note: original array may be
|
||||
// returned if nothing changed.
|
||||
function trim(nodes, compressor, first_in_statement) {
|
||||
var len = nodes.length;
|
||||
if (!len) return null;
|
||||
|
||||
var ret = [], changed = false;
|
||||
for (var i = 0; i < len; i++) {
|
||||
var node = nodes[i].drop_side_effect_free(compressor, first_in_statement);
|
||||
changed |= node !== nodes[i];
|
||||
if (node) {
|
||||
ret.push(node);
|
||||
first_in_statement = false;
|
||||
}
|
||||
}
|
||||
return changed ? ret.length ? ret : null : nodes;
|
||||
}
|
||||
|
||||
def_drop_side_effect_free(AST_Node, return_this);
|
||||
def_drop_side_effect_free(AST_Constant, return_null);
|
||||
def_drop_side_effect_free(AST_This, return_null);
|
||||
|
||||
def_drop_side_effect_free(AST_Call, function (compressor, first_in_statement) {
|
||||
if (is_nullish_shortcircuited(this, compressor)) {
|
||||
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||
}
|
||||
|
||||
if (!this.is_callee_pure(compressor)) {
|
||||
if (this.expression.is_call_pure(compressor)) {
|
||||
var exprs = this.args.slice();
|
||||
exprs.unshift(this.expression.expression);
|
||||
exprs = trim(exprs, compressor, first_in_statement);
|
||||
return exprs && make_sequence(this, exprs);
|
||||
}
|
||||
if (is_func_expr(this.expression)
|
||||
&& (!this.expression.name || !this.expression.name.definition().references.length)) {
|
||||
var node = this.clone();
|
||||
node.expression.process_expression(false, compressor);
|
||||
return node;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
var args = trim(this.args, compressor, first_in_statement);
|
||||
return args && make_sequence(this, args);
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Accessor, return_null);
|
||||
|
||||
def_drop_side_effect_free(AST_Function, return_null);
|
||||
|
||||
def_drop_side_effect_free(AST_Arrow, return_null);
|
||||
|
||||
def_drop_side_effect_free(AST_Class, function (compressor) {
|
||||
const with_effects = [];
|
||||
|
||||
if (this.is_self_referential() && this.has_side_effects(compressor)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
const trimmed_extends = this.extends && this.extends.drop_side_effect_free(compressor);
|
||||
if (trimmed_extends) with_effects.push(trimmed_extends);
|
||||
|
||||
for (const prop of this.properties) {
|
||||
if (prop instanceof AST_ClassStaticBlock) {
|
||||
if (prop.has_side_effects(compressor)) {
|
||||
return this; // Be cautious about these
|
||||
}
|
||||
} else {
|
||||
const trimmed_prop = prop.drop_side_effect_free(compressor);
|
||||
if (trimmed_prop) with_effects.push(trimmed_prop);
|
||||
}
|
||||
}
|
||||
|
||||
if (!with_effects.length)
|
||||
return null;
|
||||
|
||||
const exprs = make_sequence(this, with_effects);
|
||||
if (this instanceof AST_DefClass) {
|
||||
// We want a statement
|
||||
return make_node(AST_SimpleStatement, this, { body: exprs });
|
||||
} else {
|
||||
return exprs;
|
||||
}
|
||||
});
|
||||
|
||||
def_drop_side_effect_free([
|
||||
AST_ClassProperty,
|
||||
AST_ClassPrivateProperty,
|
||||
], function (compressor) {
|
||||
const key = this.computed_key() && this.key.drop_side_effect_free(compressor);
|
||||
|
||||
const value = this.static && this.value
|
||||
&& this.value.drop_side_effect_free(compressor);
|
||||
|
||||
if (key && value)
|
||||
return make_sequence(this, [key, value]);
|
||||
return key || value || null;
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Binary, function (compressor, first_in_statement) {
|
||||
var right = this.right.drop_side_effect_free(compressor);
|
||||
if (!right)
|
||||
return this.left.drop_side_effect_free(compressor, first_in_statement);
|
||||
if (lazy_op.has(this.operator)) {
|
||||
if (right === this.right)
|
||||
return this;
|
||||
var node = this.clone();
|
||||
node.right = right;
|
||||
return node;
|
||||
} else {
|
||||
var left = this.left.drop_side_effect_free(compressor, first_in_statement);
|
||||
if (!left)
|
||||
return this.right.drop_side_effect_free(compressor, first_in_statement);
|
||||
return make_sequence(this, [left, right]);
|
||||
}
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Assign, function (compressor) {
|
||||
if (this.logical)
|
||||
return this;
|
||||
|
||||
var left = this.left;
|
||||
if (left.has_side_effects(compressor)
|
||||
|| compressor.has_directive("use strict")
|
||||
&& left instanceof AST_PropAccess
|
||||
&& left.expression.is_constant()) {
|
||||
return this;
|
||||
}
|
||||
set_flag(this, WRITE_ONLY);
|
||||
while (left instanceof AST_PropAccess) {
|
||||
left = left.expression;
|
||||
}
|
||||
if (left.is_constant_expression(compressor.find_parent(AST_Scope))) {
|
||||
return this.right.drop_side_effect_free(compressor);
|
||||
}
|
||||
return this;
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Conditional, function (compressor) {
|
||||
var consequent = this.consequent.drop_side_effect_free(compressor);
|
||||
var alternative = this.alternative.drop_side_effect_free(compressor);
|
||||
if (consequent === this.consequent && alternative === this.alternative)
|
||||
return this;
|
||||
if (!consequent)
|
||||
return alternative ? make_node(AST_Binary, this, {
|
||||
operator: "||",
|
||||
left: this.condition,
|
||||
right: alternative
|
||||
}) : this.condition.drop_side_effect_free(compressor);
|
||||
if (!alternative)
|
||||
return make_node(AST_Binary, this, {
|
||||
operator: "&&",
|
||||
left: this.condition,
|
||||
right: consequent
|
||||
});
|
||||
var node = this.clone();
|
||||
node.consequent = consequent;
|
||||
node.alternative = alternative;
|
||||
return node;
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Unary, function (compressor, first_in_statement) {
|
||||
if (unary_side_effects.has(this.operator)) {
|
||||
if (!this.expression.has_side_effects(compressor)) {
|
||||
set_flag(this, WRITE_ONLY);
|
||||
} else {
|
||||
clear_flag(this, WRITE_ONLY);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef)
|
||||
return null;
|
||||
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||
if (first_in_statement && expression && is_iife_call(expression)) {
|
||||
if (expression === this.expression && this.operator == "!")
|
||||
return this;
|
||||
return expression.negate(compressor, first_in_statement);
|
||||
}
|
||||
return expression;
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_SymbolRef, function (compressor) {
|
||||
const safe_access = this.is_declared(compressor)
|
||||
|| pure_prop_access_globals.has(this.name);
|
||||
return safe_access ? null : this;
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Object, function (compressor, first_in_statement) {
|
||||
var values = trim(this.properties, compressor, first_in_statement);
|
||||
return values && make_sequence(this, values);
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_ObjectKeyVal, function (compressor, first_in_statement) {
|
||||
const computed_key = this.key instanceof AST_Node;
|
||||
const key = computed_key && this.key.drop_side_effect_free(compressor, first_in_statement);
|
||||
const value = this.value.drop_side_effect_free(compressor, first_in_statement);
|
||||
if (key && value) {
|
||||
return make_sequence(this, [key, value]);
|
||||
}
|
||||
return key || value;
|
||||
});
|
||||
|
||||
def_drop_side_effect_free([
|
||||
AST_ConciseMethod,
|
||||
AST_ObjectGetter,
|
||||
AST_ObjectSetter,
|
||||
], function () {
|
||||
return this.computed_key() ? this.key : null;
|
||||
});
|
||||
|
||||
def_drop_side_effect_free([
|
||||
AST_PrivateMethod,
|
||||
AST_PrivateGetter,
|
||||
AST_PrivateSetter,
|
||||
], function () {
|
||||
return null;
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Array, function (compressor, first_in_statement) {
|
||||
var values = trim(this.elements, compressor, first_in_statement);
|
||||
return values && make_sequence(this, values);
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Dot, function (compressor, first_in_statement) {
|
||||
if (is_nullish_shortcircuited(this, compressor)) {
|
||||
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||
}
|
||||
if (!this.optional && this.expression.may_throw_on_access(compressor)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Sub, function (compressor, first_in_statement) {
|
||||
if (is_nullish_shortcircuited(this, compressor)) {
|
||||
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||
}
|
||||
if (!this.optional && this.expression.may_throw_on_access(compressor)) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var property = this.property.drop_side_effect_free(compressor);
|
||||
if (property && this.optional) return this;
|
||||
|
||||
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||
|
||||
if (expression && property) return make_sequence(this, [expression, property]);
|
||||
return expression || property;
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Chain, function (compressor, first_in_statement) {
|
||||
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Sequence, function (compressor) {
|
||||
var last = this.tail_node();
|
||||
var expr = last.drop_side_effect_free(compressor);
|
||||
if (expr === last)
|
||||
return this;
|
||||
var expressions = this.expressions.slice(0, -1);
|
||||
if (expr)
|
||||
expressions.push(expr);
|
||||
if (!expressions.length) {
|
||||
return make_node(AST_Number, this, { value: 0 });
|
||||
}
|
||||
return make_sequence(this, expressions);
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_Expansion, function (compressor, first_in_statement) {
|
||||
return this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||
});
|
||||
|
||||
def_drop_side_effect_free(AST_TemplateSegment, return_null);
|
||||
|
||||
def_drop_side_effect_free(AST_TemplateString, function (compressor) {
|
||||
var values = trim(this.segments, compressor, first_in_statement);
|
||||
return values && make_sequence(this, values);
|
||||
});
|
505
node_modules/terser/lib/compress/drop-unused.js
generated
vendored
Normal file
505
node_modules/terser/lib/compress/drop-unused.js
generated
vendored
Normal file
@ -0,0 +1,505 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
import {
|
||||
AST_Accessor,
|
||||
AST_Assign,
|
||||
AST_BlockStatement,
|
||||
AST_Call,
|
||||
AST_Class,
|
||||
AST_ClassExpression,
|
||||
AST_ClassStaticBlock,
|
||||
AST_DefaultAssign,
|
||||
AST_DefClass,
|
||||
AST_Definitions,
|
||||
AST_Defun,
|
||||
AST_Destructuring,
|
||||
AST_EmptyStatement,
|
||||
AST_Expansion,
|
||||
AST_Export,
|
||||
AST_For,
|
||||
AST_ForIn,
|
||||
AST_Function,
|
||||
AST_LabeledStatement,
|
||||
AST_Lambda,
|
||||
AST_Number,
|
||||
AST_Scope,
|
||||
AST_Sequence,
|
||||
AST_SimpleStatement,
|
||||
AST_SymbolBlockDeclaration,
|
||||
AST_SymbolCatch,
|
||||
AST_SymbolDeclaration,
|
||||
AST_SymbolFunarg,
|
||||
AST_SymbolRef,
|
||||
AST_SymbolVar,
|
||||
AST_Toplevel,
|
||||
AST_Unary,
|
||||
AST_Var,
|
||||
|
||||
TreeTransformer,
|
||||
TreeWalker,
|
||||
walk,
|
||||
} from "../ast.js";
|
||||
import {
|
||||
keep_name,
|
||||
make_node,
|
||||
map_add,
|
||||
MAP,
|
||||
remove,
|
||||
return_false,
|
||||
} from "../utils/index.js";
|
||||
import { SymbolDef } from "../scope.js";
|
||||
|
||||
import {
|
||||
WRITE_ONLY,
|
||||
UNUSED,
|
||||
|
||||
has_flag,
|
||||
set_flag,
|
||||
} from "./compressor-flags.js";
|
||||
import {
|
||||
make_sequence,
|
||||
maintain_this_binding,
|
||||
is_empty,
|
||||
is_ref_of,
|
||||
can_be_evicted_from_block,
|
||||
} from "./common.js";
|
||||
import { is_used_in_expression } from "./inference.js";
|
||||
|
||||
const r_keep_assign = /keep_assign/;
|
||||
|
||||
/** Drop unused variables from this scope */
|
||||
AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
||||
if (!compressor.option("unused")) return;
|
||||
if (compressor.has_directive("use asm")) return;
|
||||
if (!this.variables) return; // not really a scope (eg: AST_Class)
|
||||
|
||||
var self = this;
|
||||
if (self.pinned()) return;
|
||||
var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
|
||||
var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
|
||||
const assign_as_unused = r_keep_assign.test(compressor.option("unused")) ? return_false : function(node) {
|
||||
if (node instanceof AST_Assign
|
||||
&& !node.logical
|
||||
&& (has_flag(node, WRITE_ONLY) || node.operator == "=")
|
||||
) {
|
||||
return node.left;
|
||||
}
|
||||
if (node instanceof AST_Unary && has_flag(node, WRITE_ONLY)) {
|
||||
return node.expression;
|
||||
}
|
||||
};
|
||||
var in_use_ids = new Map();
|
||||
var fixed_ids = new Map();
|
||||
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
||||
self.variables.forEach(function(def) {
|
||||
if (compressor.top_retain(def)) {
|
||||
in_use_ids.set(def.id, def);
|
||||
}
|
||||
});
|
||||
}
|
||||
var var_defs_by_id = new Map();
|
||||
var initializations = new Map();
|
||||
|
||||
// pass 1: find out which symbols are directly used in
|
||||
// this scope (not in nested scopes).
|
||||
var scope = this;
|
||||
var tw = new TreeWalker(function(node, descend) {
|
||||
if (node instanceof AST_Lambda && node.uses_arguments && !tw.has_directive("use strict")) {
|
||||
node.argnames.forEach(function(argname) {
|
||||
if (!(argname instanceof AST_SymbolDeclaration)) return;
|
||||
var def = argname.definition();
|
||||
in_use_ids.set(def.id, def);
|
||||
});
|
||||
}
|
||||
if (node === self) return;
|
||||
if (node instanceof AST_Class && node.has_side_effects(compressor)) {
|
||||
if (node.is_self_referential()) {
|
||||
descend();
|
||||
} else {
|
||||
node.visit_nondeferred_class_parts(tw);
|
||||
}
|
||||
}
|
||||
if (node instanceof AST_Defun || node instanceof AST_DefClass) {
|
||||
var node_def = node.name.definition();
|
||||
const in_export = tw.parent() instanceof AST_Export;
|
||||
if (in_export || !drop_funcs && scope === self) {
|
||||
if (node_def.global) {
|
||||
in_use_ids.set(node_def.id, node_def);
|
||||
}
|
||||
}
|
||||
|
||||
map_add(initializations, node_def.id, node);
|
||||
return true; // don't go in nested scopes
|
||||
}
|
||||
// In the root scope, we drop things. In inner scopes, we just check for uses.
|
||||
const in_root_scope = scope === self;
|
||||
if (node instanceof AST_SymbolFunarg && in_root_scope) {
|
||||
map_add(var_defs_by_id, node.definition().id, node);
|
||||
}
|
||||
if (node instanceof AST_Definitions && in_root_scope) {
|
||||
const in_export = tw.parent() instanceof AST_Export;
|
||||
node.definitions.forEach(function(def) {
|
||||
if (def.name instanceof AST_SymbolVar) {
|
||||
map_add(var_defs_by_id, def.name.definition().id, def);
|
||||
}
|
||||
if (in_export || !drop_vars) {
|
||||
walk(def.name, node => {
|
||||
if (node instanceof AST_SymbolDeclaration) {
|
||||
const def = node.definition();
|
||||
if (def.global) {
|
||||
in_use_ids.set(def.id, def);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (def.name instanceof AST_Destructuring) {
|
||||
def.walk(tw);
|
||||
}
|
||||
if (def.name instanceof AST_SymbolDeclaration && def.value) {
|
||||
var node_def = def.name.definition();
|
||||
map_add(initializations, node_def.id, def.value);
|
||||
if (!node_def.chained && def.name.fixed_value() === def.value) {
|
||||
fixed_ids.set(node_def.id, def);
|
||||
}
|
||||
if (def.value.has_side_effects(compressor)) {
|
||||
def.value.walk(tw);
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return scan_ref_scoped(node, descend);
|
||||
});
|
||||
self.walk(tw);
|
||||
// pass 2: for every used symbol we need to walk its
|
||||
// initialization code to figure out if it uses other
|
||||
// symbols (that may not be in_use).
|
||||
tw = new TreeWalker(scan_ref_scoped);
|
||||
in_use_ids.forEach(function (def) {
|
||||
var init = initializations.get(def.id);
|
||||
if (init) init.forEach(function(init) {
|
||||
init.walk(tw);
|
||||
});
|
||||
});
|
||||
// pass 3: we should drop declarations not in_use
|
||||
var tt = new TreeTransformer(
|
||||
function before(node, descend, in_list) {
|
||||
var parent = tt.parent();
|
||||
if (drop_vars) {
|
||||
const sym = assign_as_unused(node);
|
||||
if (sym instanceof AST_SymbolRef) {
|
||||
var def = sym.definition();
|
||||
var in_use = in_use_ids.has(def.id);
|
||||
if (node instanceof AST_Assign) {
|
||||
if (!in_use || fixed_ids.has(def.id) && fixed_ids.get(def.id) !== node) {
|
||||
const assignee = node.right.transform(tt);
|
||||
if (!in_use && !assignee.has_side_effects(compressor) && !is_used_in_expression(tt)) {
|
||||
return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 });
|
||||
}
|
||||
return maintain_this_binding(parent, node, assignee);
|
||||
}
|
||||
} else if (!in_use) {
|
||||
return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 });
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scope !== self) return;
|
||||
var def;
|
||||
if (node.name
|
||||
&& (node instanceof AST_ClassExpression
|
||||
&& !keep_name(compressor.option("keep_classnames"), (def = node.name.definition()).name)
|
||||
|| node instanceof AST_Function
|
||||
&& !keep_name(compressor.option("keep_fnames"), (def = node.name.definition()).name))) {
|
||||
// any declarations with same name will overshadow
|
||||
// name of this anonymous function and can therefore
|
||||
// never be used anywhere
|
||||
if (!in_use_ids.has(def.id) || def.orig.length > 1) node.name = null;
|
||||
}
|
||||
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
|
||||
var trim =
|
||||
!compressor.option("keep_fargs")
|
||||
// Is this an IIFE that won't refer to its name?
|
||||
|| parent instanceof AST_Call
|
||||
&& parent.expression === node
|
||||
&& !node.pinned()
|
||||
&& (!node.name || node.name.unreferenced());
|
||||
for (var a = node.argnames, i = a.length; --i >= 0;) {
|
||||
var sym = a[i];
|
||||
if (sym instanceof AST_Expansion) {
|
||||
sym = sym.expression;
|
||||
}
|
||||
if (sym instanceof AST_DefaultAssign) {
|
||||
sym = sym.left;
|
||||
}
|
||||
// Do not drop destructuring arguments.
|
||||
// They constitute a type assertion of sorts
|
||||
if (
|
||||
!(sym instanceof AST_Destructuring)
|
||||
&& !in_use_ids.has(sym.definition().id)
|
||||
) {
|
||||
set_flag(sym, UNUSED);
|
||||
if (trim) {
|
||||
a.pop();
|
||||
}
|
||||
} else {
|
||||
trim = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node instanceof AST_DefClass && node !== self) {
|
||||
const def = node.name.definition();
|
||||
descend(node, this);
|
||||
const keep_class = def.global && !drop_funcs || in_use_ids.has(def.id);
|
||||
if (!keep_class) {
|
||||
const kept = node.drop_side_effect_free(compressor);
|
||||
if (kept == null) {
|
||||
def.eliminated++;
|
||||
return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
|
||||
}
|
||||
return kept;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_Defun && node !== self) {
|
||||
const def = node.name.definition();
|
||||
const keep = def.global && !drop_funcs || in_use_ids.has(def.id);
|
||||
if (!keep) {
|
||||
def.eliminated++;
|
||||
return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
|
||||
}
|
||||
}
|
||||
if (node instanceof AST_Definitions && !(parent instanceof AST_ForIn && parent.init === node)) {
|
||||
var drop_block = !(parent instanceof AST_Toplevel) && !(node instanceof AST_Var);
|
||||
// place uninitialized names at the start
|
||||
var body = [], head = [], tail = [];
|
||||
// for unused names whose initialization has
|
||||
// side effects, we can cascade the init. code
|
||||
// into the next one, or next statement.
|
||||
var side_effects = [];
|
||||
node.definitions.forEach(function(def) {
|
||||
if (def.value) def.value = def.value.transform(tt);
|
||||
var is_destructure = def.name instanceof AST_Destructuring;
|
||||
var sym = is_destructure
|
||||
? new SymbolDef(null, { name: "<destructure>" }) /* fake SymbolDef */
|
||||
: def.name.definition();
|
||||
if (drop_block && sym.global) return tail.push(def);
|
||||
if (!(drop_vars || drop_block)
|
||||
|| is_destructure
|
||||
&& (def.name.names.length
|
||||
|| def.name.is_array
|
||||
|| compressor.option("pure_getters") != true)
|
||||
|| in_use_ids.has(sym.id)
|
||||
) {
|
||||
if (def.value && fixed_ids.has(sym.id) && fixed_ids.get(sym.id) !== def) {
|
||||
def.value = def.value.drop_side_effect_free(compressor);
|
||||
}
|
||||
if (def.name instanceof AST_SymbolVar) {
|
||||
var var_defs = var_defs_by_id.get(sym.id);
|
||||
if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) {
|
||||
if (def.value) {
|
||||
var ref = make_node(AST_SymbolRef, def.name, def.name);
|
||||
sym.references.push(ref);
|
||||
var assign = make_node(AST_Assign, def, {
|
||||
operator: "=",
|
||||
logical: false,
|
||||
left: ref,
|
||||
right: def.value
|
||||
});
|
||||
if (fixed_ids.get(sym.id) === def) {
|
||||
fixed_ids.set(sym.id, assign);
|
||||
}
|
||||
side_effects.push(assign.transform(tt));
|
||||
}
|
||||
remove(var_defs, def);
|
||||
sym.eliminated++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (def.value) {
|
||||
if (side_effects.length > 0) {
|
||||
if (tail.length > 0) {
|
||||
side_effects.push(def.value);
|
||||
def.value = make_sequence(def.value, side_effects);
|
||||
} else {
|
||||
body.push(make_node(AST_SimpleStatement, node, {
|
||||
body: make_sequence(node, side_effects)
|
||||
}));
|
||||
}
|
||||
side_effects = [];
|
||||
}
|
||||
tail.push(def);
|
||||
} else {
|
||||
head.push(def);
|
||||
}
|
||||
} else if (sym.orig[0] instanceof AST_SymbolCatch) {
|
||||
var value = def.value && def.value.drop_side_effect_free(compressor);
|
||||
if (value) side_effects.push(value);
|
||||
def.value = null;
|
||||
head.push(def);
|
||||
} else {
|
||||
var value = def.value && def.value.drop_side_effect_free(compressor);
|
||||
if (value) {
|
||||
side_effects.push(value);
|
||||
}
|
||||
sym.eliminated++;
|
||||
}
|
||||
});
|
||||
if (head.length > 0 || tail.length > 0) {
|
||||
node.definitions = head.concat(tail);
|
||||
body.push(node);
|
||||
}
|
||||
if (side_effects.length > 0) {
|
||||
body.push(make_node(AST_SimpleStatement, node, {
|
||||
body: make_sequence(node, side_effects)
|
||||
}));
|
||||
}
|
||||
switch (body.length) {
|
||||
case 0:
|
||||
return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
|
||||
case 1:
|
||||
return body[0];
|
||||
default:
|
||||
return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { body });
|
||||
}
|
||||
}
|
||||
// certain combination of unused name + side effect leads to:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/44
|
||||
// https://github.com/mishoo/UglifyJS2/issues/1830
|
||||
// https://github.com/mishoo/UglifyJS2/issues/1838
|
||||
// that's an invalid AST.
|
||||
// We fix it at this stage by moving the `var` outside the `for`.
|
||||
if (node instanceof AST_For) {
|
||||
descend(node, this);
|
||||
var block;
|
||||
if (node.init instanceof AST_BlockStatement) {
|
||||
block = node.init;
|
||||
node.init = block.body.pop();
|
||||
block.body.push(node);
|
||||
}
|
||||
if (node.init instanceof AST_SimpleStatement) {
|
||||
node.init = node.init.body;
|
||||
} else if (is_empty(node.init)) {
|
||||
node.init = null;
|
||||
}
|
||||
return !block ? node : in_list ? MAP.splice(block.body) : block;
|
||||
}
|
||||
if (node instanceof AST_LabeledStatement
|
||||
&& node.body instanceof AST_For
|
||||
) {
|
||||
descend(node, this);
|
||||
if (node.body instanceof AST_BlockStatement) {
|
||||
var block = node.body;
|
||||
node.body = block.body.pop();
|
||||
block.body.push(node);
|
||||
return in_list ? MAP.splice(block.body) : block;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_BlockStatement) {
|
||||
descend(node, this);
|
||||
if (in_list && node.body.every(can_be_evicted_from_block)) {
|
||||
return MAP.splice(node.body);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
if (node instanceof AST_Scope && !(node instanceof AST_ClassStaticBlock)) {
|
||||
const save_scope = scope;
|
||||
scope = node;
|
||||
descend(node, this);
|
||||
scope = save_scope;
|
||||
return node;
|
||||
}
|
||||
},
|
||||
function after(node, in_list) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
switch (node.expressions.length) {
|
||||
case 0: return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 });
|
||||
case 1: return node.expressions[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
self.transform(tt);
|
||||
|
||||
function scan_ref_scoped(node, descend) {
|
||||
var node_def;
|
||||
const sym = assign_as_unused(node);
|
||||
if (sym instanceof AST_SymbolRef
|
||||
&& !is_ref_of(node.left, AST_SymbolBlockDeclaration)
|
||||
&& self.variables.get(sym.name) === (node_def = sym.definition())
|
||||
) {
|
||||
if (node instanceof AST_Assign) {
|
||||
node.right.walk(tw);
|
||||
if (!node_def.chained && node.left.fixed_value() === node.right) {
|
||||
fixed_ids.set(node_def.id, node);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
node_def = node.definition();
|
||||
if (!in_use_ids.has(node_def.id)) {
|
||||
in_use_ids.set(node_def.id, node_def);
|
||||
if (node_def.orig[0] instanceof AST_SymbolCatch) {
|
||||
const redef = node_def.scope.is_block_scope()
|
||||
&& node_def.scope.get_defun_scope().variables.get(node_def.name);
|
||||
if (redef) in_use_ids.set(redef.id, redef);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Class) {
|
||||
descend();
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope && !(node instanceof AST_ClassStaticBlock)) {
|
||||
var save_scope = scope;
|
||||
scope = node;
|
||||
descend();
|
||||
scope = save_scope;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
521
node_modules/terser/lib/compress/evaluate.js
generated
vendored
Normal file
521
node_modules/terser/lib/compress/evaluate.js
generated
vendored
Normal file
@ -0,0 +1,521 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
import {
|
||||
HOP,
|
||||
makePredicate,
|
||||
return_this,
|
||||
string_template,
|
||||
regexp_source_fix,
|
||||
regexp_is_safe,
|
||||
} from "../utils/index.js";
|
||||
import {
|
||||
AST_Array,
|
||||
AST_BigInt,
|
||||
AST_Binary,
|
||||
AST_Call,
|
||||
AST_Chain,
|
||||
AST_Class,
|
||||
AST_Conditional,
|
||||
AST_Constant,
|
||||
AST_Dot,
|
||||
AST_Expansion,
|
||||
AST_Function,
|
||||
AST_Lambda,
|
||||
AST_New,
|
||||
AST_Node,
|
||||
AST_Object,
|
||||
AST_PropAccess,
|
||||
AST_RegExp,
|
||||
AST_Statement,
|
||||
AST_Symbol,
|
||||
AST_SymbolRef,
|
||||
AST_TemplateString,
|
||||
AST_UnaryPrefix,
|
||||
AST_With,
|
||||
} from "../ast.js";
|
||||
import { is_undeclared_ref} from "./inference.js";
|
||||
import { is_pure_native_value, is_pure_native_fn, is_pure_native_method } from "./native-objects.js";
|
||||
|
||||
// methods to evaluate a constant expression
|
||||
|
||||
function def_eval(node, func) {
|
||||
node.DEFMETHOD("_eval", func);
|
||||
}
|
||||
|
||||
// Used to propagate a nullish short-circuit signal upwards through the chain.
|
||||
export const nullish = Symbol("This AST_Chain is nullish");
|
||||
|
||||
// If the node has been successfully reduced to a constant,
|
||||
// then its value is returned; otherwise the element itself
|
||||
// is returned.
|
||||
// They can be distinguished as constant value is never a
|
||||
// descendant of AST_Node.
|
||||
AST_Node.DEFMETHOD("evaluate", function (compressor) {
|
||||
if (!compressor.option("evaluate"))
|
||||
return this;
|
||||
var val = this._eval(compressor, 1);
|
||||
if (!val || val instanceof RegExp)
|
||||
return val;
|
||||
if (typeof val == "function" || typeof val == "object" || val == nullish)
|
||||
return this;
|
||||
|
||||
// Evaluated strings can be larger than the original expression
|
||||
if (typeof val === "string") {
|
||||
const unevaluated_size = this.size(compressor);
|
||||
if (val.length + 2 > unevaluated_size) return this;
|
||||
}
|
||||
|
||||
return val;
|
||||
});
|
||||
|
||||
var unaryPrefix = makePredicate("! ~ - + void");
|
||||
AST_Node.DEFMETHOD("is_constant", function () {
|
||||
// Accomodate when compress option evaluate=false
|
||||
// as well as the common constant expressions !0 and -1
|
||||
if (this instanceof AST_Constant) {
|
||||
return !(this instanceof AST_RegExp);
|
||||
} else {
|
||||
return this instanceof AST_UnaryPrefix
|
||||
&& unaryPrefix.has(this.operator)
|
||||
&& (
|
||||
// `this.expression` may be an `AST_RegExp`,
|
||||
// so not only `.is_constant()`.
|
||||
this.expression instanceof AST_Constant
|
||||
|| this.expression.is_constant()
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
def_eval(AST_Statement, function () {
|
||||
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
||||
});
|
||||
|
||||
def_eval(AST_Lambda, return_this);
|
||||
def_eval(AST_Class, return_this);
|
||||
def_eval(AST_Node, return_this);
|
||||
def_eval(AST_Constant, function () {
|
||||
return this.getValue();
|
||||
});
|
||||
|
||||
const supports_bigint = typeof BigInt === "function";
|
||||
def_eval(AST_BigInt, function () {
|
||||
if (supports_bigint) {
|
||||
return BigInt(this.value);
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
def_eval(AST_RegExp, function (compressor) {
|
||||
let evaluated = compressor.evaluated_regexps.get(this.value);
|
||||
if (evaluated === undefined && regexp_is_safe(this.value.source)) {
|
||||
try {
|
||||
const { source, flags } = this.value;
|
||||
evaluated = new RegExp(source, flags);
|
||||
} catch (e) {
|
||||
evaluated = null;
|
||||
}
|
||||
compressor.evaluated_regexps.set(this.value, evaluated);
|
||||
}
|
||||
return evaluated || this;
|
||||
});
|
||||
|
||||
def_eval(AST_TemplateString, function () {
|
||||
if (this.segments.length !== 1) return this;
|
||||
return this.segments[0].value;
|
||||
});
|
||||
|
||||
def_eval(AST_Function, function (compressor) {
|
||||
if (compressor.option("unsafe")) {
|
||||
var fn = function () { };
|
||||
fn.node = this;
|
||||
fn.toString = () => this.print_to_string();
|
||||
return fn;
|
||||
}
|
||||
return this;
|
||||
});
|
||||
|
||||
def_eval(AST_Array, function (compressor, depth) {
|
||||
if (compressor.option("unsafe")) {
|
||||
var elements = [];
|
||||
for (var i = 0, len = this.elements.length; i < len; i++) {
|
||||
var element = this.elements[i];
|
||||
var value = element._eval(compressor, depth);
|
||||
if (element === value)
|
||||
return this;
|
||||
elements.push(value);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
return this;
|
||||
});
|
||||
|
||||
def_eval(AST_Object, function (compressor, depth) {
|
||||
if (compressor.option("unsafe")) {
|
||||
var val = {};
|
||||
for (var i = 0, len = this.properties.length; i < len; i++) {
|
||||
var prop = this.properties[i];
|
||||
if (prop instanceof AST_Expansion)
|
||||
return this;
|
||||
var key = prop.key;
|
||||
if (key instanceof AST_Symbol) {
|
||||
key = key.name;
|
||||
} else if (key instanceof AST_Node) {
|
||||
key = key._eval(compressor, depth);
|
||||
if (key === prop.key)
|
||||
return this;
|
||||
}
|
||||
if (typeof Object.prototype[key] === "function") {
|
||||
return this;
|
||||
}
|
||||
if (prop.value instanceof AST_Function)
|
||||
continue;
|
||||
val[key] = prop.value._eval(compressor, depth);
|
||||
if (val[key] === prop.value)
|
||||
return this;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
return this;
|
||||
});
|
||||
|
||||
var non_converting_unary = makePredicate("! typeof void");
|
||||
def_eval(AST_UnaryPrefix, function (compressor, depth) {
|
||||
var e = this.expression;
|
||||
if (compressor.option("typeofs")
|
||||
&& this.operator == "typeof") {
|
||||
// Function would be evaluated to an array and so typeof would
|
||||
// incorrectly return 'object'. Hence making is a special case.
|
||||
if (e instanceof AST_Lambda
|
||||
|| e instanceof AST_SymbolRef
|
||||
&& e.fixed_value() instanceof AST_Lambda) {
|
||||
return typeof function () { };
|
||||
}
|
||||
if (
|
||||
(e instanceof AST_Object
|
||||
|| e instanceof AST_Array
|
||||
|| (e instanceof AST_SymbolRef
|
||||
&& (e.fixed_value() instanceof AST_Object
|
||||
|| e.fixed_value() instanceof AST_Array)))
|
||||
&& !e.has_side_effects(compressor)
|
||||
) {
|
||||
return typeof {};
|
||||
}
|
||||
}
|
||||
if (!non_converting_unary.has(this.operator))
|
||||
depth++;
|
||||
e = e._eval(compressor, depth);
|
||||
if (e === this.expression)
|
||||
return this;
|
||||
switch (this.operator) {
|
||||
case "!": return !e;
|
||||
case "typeof":
|
||||
// typeof <RegExp> returns "object" or "function" on different platforms
|
||||
// so cannot evaluate reliably
|
||||
if (e instanceof RegExp)
|
||||
return this;
|
||||
return typeof e;
|
||||
case "void": return void e;
|
||||
case "~": return ~e;
|
||||
case "-": return -e;
|
||||
case "+": return +e;
|
||||
}
|
||||
return this;
|
||||
});
|
||||
|
||||
var non_converting_binary = makePredicate("&& || ?? === !==");
|
||||
const identity_comparison = makePredicate("== != === !==");
|
||||
const has_identity = value => typeof value === "object"
|
||||
|| typeof value === "function"
|
||||
|| typeof value === "symbol";
|
||||
|
||||
def_eval(AST_Binary, function (compressor, depth) {
|
||||
if (!non_converting_binary.has(this.operator))
|
||||
depth++;
|
||||
|
||||
var left = this.left._eval(compressor, depth);
|
||||
if (left === this.left)
|
||||
return this;
|
||||
var right = this.right._eval(compressor, depth);
|
||||
if (right === this.right)
|
||||
return this;
|
||||
|
||||
if (left != null
|
||||
&& right != null
|
||||
&& identity_comparison.has(this.operator)
|
||||
&& has_identity(left)
|
||||
&& has_identity(right)
|
||||
&& typeof left === typeof right) {
|
||||
// Do not compare by reference
|
||||
return this;
|
||||
}
|
||||
|
||||
// Do not mix BigInt and Number; Don't use `>>>` on BigInt or `/ 0n`
|
||||
if (
|
||||
(typeof left === "bigint") !== (typeof right === "bigint")
|
||||
|| typeof left === "bigint"
|
||||
&& (this.operator === ">>>"
|
||||
|| this.operator === "/" && Number(right) === 0)
|
||||
) {
|
||||
return this;
|
||||
}
|
||||
|
||||
var result;
|
||||
switch (this.operator) {
|
||||
case "&&": result = left && right; break;
|
||||
case "||": result = left || right; break;
|
||||
case "??": result = left != null ? left : right; break;
|
||||
case "|": result = left | right; break;
|
||||
case "&": result = left & right; break;
|
||||
case "^": result = left ^ right; break;
|
||||
case "+": result = left + right; break;
|
||||
case "*": result = left * right; break;
|
||||
case "**": result = left ** right; break;
|
||||
case "/": result = left / right; break;
|
||||
case "%": result = left % right; break;
|
||||
case "-": result = left - right; break;
|
||||
case "<<": result = left << right; break;
|
||||
case ">>": result = left >> right; break;
|
||||
case ">>>": result = left >>> right; break;
|
||||
case "==": result = left == right; break;
|
||||
case "===": result = left === right; break;
|
||||
case "!=": result = left != right; break;
|
||||
case "!==": result = left !== right; break;
|
||||
case "<": result = left < right; break;
|
||||
case "<=": result = left <= right; break;
|
||||
case ">": result = left > right; break;
|
||||
case ">=": result = left >= right; break;
|
||||
default:
|
||||
return this;
|
||||
}
|
||||
if (typeof result === "number" && isNaN(result) && compressor.find_parent(AST_With)) {
|
||||
// leave original expression as is
|
||||
return this;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
|
||||
def_eval(AST_Conditional, function (compressor, depth) {
|
||||
var condition = this.condition._eval(compressor, depth);
|
||||
if (condition === this.condition)
|
||||
return this;
|
||||
var node = condition ? this.consequent : this.alternative;
|
||||
var value = node._eval(compressor, depth);
|
||||
return value === node ? this : value;
|
||||
});
|
||||
|
||||
// Set of AST_SymbolRef which are currently being evaluated.
|
||||
// Avoids infinite recursion of ._eval()
|
||||
const reentrant_ref_eval = new Set();
|
||||
def_eval(AST_SymbolRef, function (compressor, depth) {
|
||||
if (reentrant_ref_eval.has(this))
|
||||
return this;
|
||||
|
||||
var fixed = this.fixed_value();
|
||||
if (!fixed)
|
||||
return this;
|
||||
|
||||
reentrant_ref_eval.add(this);
|
||||
const value = fixed._eval(compressor, depth);
|
||||
reentrant_ref_eval.delete(this);
|
||||
|
||||
if (value === fixed)
|
||||
return this;
|
||||
|
||||
if (value && typeof value == "object") {
|
||||
var escaped = this.definition().escaped;
|
||||
if (escaped && depth > escaped)
|
||||
return this;
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
const global_objs = { Array, Math, Number, Object, String };
|
||||
|
||||
const regexp_flags = new Set([
|
||||
"dotAll",
|
||||
"global",
|
||||
"ignoreCase",
|
||||
"multiline",
|
||||
"sticky",
|
||||
"unicode",
|
||||
]);
|
||||
|
||||
def_eval(AST_PropAccess, function (compressor, depth) {
|
||||
let obj = this.expression._eval(compressor, depth + 1);
|
||||
if (obj === nullish || (this.optional && obj == null)) return nullish;
|
||||
|
||||
// `.length` of strings and arrays is always safe
|
||||
if (this.property === "length") {
|
||||
if (typeof obj === "string") {
|
||||
return obj.length;
|
||||
}
|
||||
|
||||
const is_spreadless_array =
|
||||
obj instanceof AST_Array
|
||||
&& obj.elements.every(el => !(el instanceof AST_Expansion));
|
||||
|
||||
if (
|
||||
is_spreadless_array
|
||||
&& obj.elements.every(el => !el.has_side_effects(compressor))
|
||||
) {
|
||||
return obj.elements.length;
|
||||
}
|
||||
}
|
||||
|
||||
if (compressor.option("unsafe")) {
|
||||
var key = this.property;
|
||||
if (key instanceof AST_Node) {
|
||||
key = key._eval(compressor, depth);
|
||||
if (key === this.property)
|
||||
return this;
|
||||
}
|
||||
|
||||
var exp = this.expression;
|
||||
if (is_undeclared_ref(exp)) {
|
||||
var aa;
|
||||
var first_arg = exp.name === "hasOwnProperty"
|
||||
&& key === "call"
|
||||
&& (aa = compressor.parent() && compressor.parent().args)
|
||||
&& (aa && aa[0]
|
||||
&& aa[0].evaluate(compressor));
|
||||
|
||||
first_arg = first_arg instanceof AST_Dot ? first_arg.expression : first_arg;
|
||||
|
||||
if (first_arg == null || first_arg.thedef && first_arg.thedef.undeclared) {
|
||||
return this.clone();
|
||||
}
|
||||
if (!is_pure_native_value(exp.name, key))
|
||||
return this;
|
||||
obj = global_objs[exp.name];
|
||||
} else {
|
||||
if (obj instanceof RegExp) {
|
||||
if (key == "source") {
|
||||
return regexp_source_fix(obj.source);
|
||||
} else if (key == "flags" || regexp_flags.has(key)) {
|
||||
return obj[key];
|
||||
}
|
||||
}
|
||||
if (!obj || obj === exp || !HOP(obj, key))
|
||||
return this;
|
||||
|
||||
if (typeof obj == "function")
|
||||
switch (key) {
|
||||
case "name":
|
||||
return obj.node.name ? obj.node.name.name : "";
|
||||
case "length":
|
||||
return obj.node.length_property();
|
||||
default:
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return obj[key];
|
||||
}
|
||||
return this;
|
||||
});
|
||||
|
||||
def_eval(AST_Chain, function (compressor, depth) {
|
||||
const evaluated = this.expression._eval(compressor, depth);
|
||||
return evaluated === nullish
|
||||
? undefined
|
||||
: evaluated === this.expression
|
||||
? this
|
||||
: evaluated;
|
||||
});
|
||||
|
||||
def_eval(AST_Call, function (compressor, depth) {
|
||||
var exp = this.expression;
|
||||
|
||||
const callee = exp._eval(compressor, depth);
|
||||
if (callee === nullish || (this.optional && callee == null)) return nullish;
|
||||
|
||||
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
||||
var key = exp.property;
|
||||
if (key instanceof AST_Node) {
|
||||
key = key._eval(compressor, depth);
|
||||
if (key === exp.property)
|
||||
return this;
|
||||
}
|
||||
var val;
|
||||
var e = exp.expression;
|
||||
if (is_undeclared_ref(e)) {
|
||||
var first_arg = e.name === "hasOwnProperty" &&
|
||||
key === "call" &&
|
||||
(this.args[0] && this.args[0].evaluate(compressor));
|
||||
|
||||
first_arg = first_arg instanceof AST_Dot ? first_arg.expression : first_arg;
|
||||
|
||||
if ((first_arg == null || first_arg.thedef && first_arg.thedef.undeclared)) {
|
||||
return this.clone();
|
||||
}
|
||||
if (!is_pure_native_fn(e.name, key)) return this;
|
||||
val = global_objs[e.name];
|
||||
} else {
|
||||
val = e._eval(compressor, depth + 1);
|
||||
if (val === e || !val)
|
||||
return this;
|
||||
if (!is_pure_native_method(val.constructor.name, key))
|
||||
return this;
|
||||
}
|
||||
var args = [];
|
||||
for (var i = 0, len = this.args.length; i < len; i++) {
|
||||
var arg = this.args[i];
|
||||
var value = arg._eval(compressor, depth);
|
||||
if (arg === value)
|
||||
return this;
|
||||
if (arg instanceof AST_Lambda)
|
||||
return this;
|
||||
args.push(value);
|
||||
}
|
||||
try {
|
||||
return val[key].apply(val, args);
|
||||
} catch (ex) {
|
||||
// We don't really care
|
||||
}
|
||||
}
|
||||
return this;
|
||||
});
|
||||
|
||||
// Also a subclass of AST_Call
|
||||
def_eval(AST_New, return_this);
|
92
node_modules/terser/lib/compress/global-defs.js
generated
vendored
Normal file
92
node_modules/terser/lib/compress/global-defs.js
generated
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
import {
|
||||
AST_Array,
|
||||
AST_Chain,
|
||||
AST_Constant,
|
||||
AST_Dot,
|
||||
AST_ImportMeta,
|
||||
AST_Node,
|
||||
AST_Object,
|
||||
AST_ObjectKeyVal,
|
||||
AST_PropAccess,
|
||||
AST_SymbolDeclaration,
|
||||
AST_SymbolRef,
|
||||
AST_Toplevel,
|
||||
TreeTransformer,
|
||||
} from "../ast.js";
|
||||
import { make_node, noop, HOP } from "../utils/index.js";
|
||||
import { make_node_from_constant } from "./common.js";
|
||||
import { is_lhs } from "./inference.js";
|
||||
|
||||
(function(def_find_defs) {
|
||||
function to_node(value, orig) {
|
||||
if (value instanceof AST_Node) {
|
||||
if (!(value instanceof AST_Constant)) {
|
||||
// Value may be a function, an array including functions and even a complex assign / block expression,
|
||||
// so it should never be shared in different places.
|
||||
// Otherwise wrong information may be used in the compression phase
|
||||
value = value.clone(true);
|
||||
}
|
||||
return make_node(value.CTOR, orig, value);
|
||||
}
|
||||
if (Array.isArray(value)) return make_node(AST_Array, orig, {
|
||||
elements: value.map(function(value) {
|
||||
return to_node(value, orig);
|
||||
})
|
||||
});
|
||||
if (value && typeof value == "object") {
|
||||
var props = [];
|
||||
for (var key in value) if (HOP(value, key)) {
|
||||
props.push(make_node(AST_ObjectKeyVal, orig, {
|
||||
key: key,
|
||||
value: to_node(value[key], orig)
|
||||
}));
|
||||
}
|
||||
return make_node(AST_Object, orig, {
|
||||
properties: props
|
||||
});
|
||||
}
|
||||
return make_node_from_constant(value, orig);
|
||||
}
|
||||
|
||||
AST_Toplevel.DEFMETHOD("resolve_defines", function(compressor) {
|
||||
if (!compressor.option("global_defs")) return this;
|
||||
this.figure_out_scope({ ie8: compressor.option("ie8") });
|
||||
return this.transform(new TreeTransformer(function(node) {
|
||||
var def = node._find_defs(compressor, "");
|
||||
if (!def) return;
|
||||
var level = 0, child = node, parent;
|
||||
while (parent = this.parent(level++)) {
|
||||
if (!(parent instanceof AST_PropAccess)) break;
|
||||
if (parent.expression !== child) break;
|
||||
child = parent;
|
||||
}
|
||||
if (is_lhs(child, parent)) {
|
||||
return;
|
||||
}
|
||||
return def;
|
||||
}));
|
||||
});
|
||||
def_find_defs(AST_Node, noop);
|
||||
def_find_defs(AST_Chain, function(compressor, suffix) {
|
||||
return this.expression._find_defs(compressor, suffix);
|
||||
});
|
||||
def_find_defs(AST_Dot, function(compressor, suffix) {
|
||||
return this.expression._find_defs(compressor, "." + this.property + suffix);
|
||||
});
|
||||
def_find_defs(AST_SymbolDeclaration, function() {
|
||||
if (!this.global()) return;
|
||||
});
|
||||
def_find_defs(AST_SymbolRef, function(compressor, suffix) {
|
||||
if (!this.global()) return;
|
||||
var defines = compressor.option("global_defs");
|
||||
var name = this.name + suffix;
|
||||
if (HOP(defines, name)) return to_node(defines[name], this);
|
||||
});
|
||||
def_find_defs(AST_ImportMeta, function(compressor, suffix) {
|
||||
var defines = compressor.option("global_defs");
|
||||
var name = "import.meta" + suffix;
|
||||
if (HOP(defines, name)) return to_node(defines[name], this);
|
||||
});
|
||||
})(function(node, func) {
|
||||
node.DEFMETHOD("_find_defs", func);
|
||||
});
|
4109
node_modules/terser/lib/compress/index.js
generated
vendored
Normal file
4109
node_modules/terser/lib/compress/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1052
node_modules/terser/lib/compress/inference.js
generated
vendored
Normal file
1052
node_modules/terser/lib/compress/inference.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
669
node_modules/terser/lib/compress/inline.js
generated
vendored
Normal file
669
node_modules/terser/lib/compress/inline.js
generated
vendored
Normal file
@ -0,0 +1,669 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
import {
|
||||
AST_Array,
|
||||
AST_Assign,
|
||||
AST_Block,
|
||||
AST_Call,
|
||||
AST_Catch,
|
||||
AST_Class,
|
||||
AST_ClassExpression,
|
||||
AST_DefaultAssign,
|
||||
AST_DefClass,
|
||||
AST_Defun,
|
||||
AST_Destructuring,
|
||||
AST_EmptyStatement,
|
||||
AST_Expansion,
|
||||
AST_Export,
|
||||
AST_Function,
|
||||
AST_IterationStatement,
|
||||
AST_Lambda,
|
||||
AST_Node,
|
||||
AST_Number,
|
||||
AST_Object,
|
||||
AST_ObjectKeyVal,
|
||||
AST_PropAccess,
|
||||
AST_Return,
|
||||
AST_Scope,
|
||||
AST_SimpleStatement,
|
||||
AST_Statement,
|
||||
AST_SymbolDefun,
|
||||
AST_SymbolFunarg,
|
||||
AST_SymbolLambda,
|
||||
AST_SymbolRef,
|
||||
AST_SymbolVar,
|
||||
AST_This,
|
||||
AST_Toplevel,
|
||||
AST_UnaryPrefix,
|
||||
AST_Undefined,
|
||||
AST_Var,
|
||||
AST_VarDef,
|
||||
|
||||
walk,
|
||||
|
||||
_INLINE,
|
||||
_NOINLINE,
|
||||
_PURE,
|
||||
} from "../ast.js";
|
||||
import { make_node, has_annotation } from "../utils/index.js";
|
||||
import "../size.js";
|
||||
|
||||
import "./evaluate.js";
|
||||
import "./drop-side-effect-free.js";
|
||||
import "./reduce-vars.js";
|
||||
import {
|
||||
SQUEEZED,
|
||||
INLINED,
|
||||
UNUSED,
|
||||
|
||||
has_flag,
|
||||
set_flag,
|
||||
} from "./compressor-flags.js";
|
||||
import {
|
||||
make_sequence,
|
||||
best_of,
|
||||
make_node_from_constant,
|
||||
identifier_atom,
|
||||
is_empty,
|
||||
is_func_expr,
|
||||
is_iife_call,
|
||||
is_reachable,
|
||||
is_recursive_ref,
|
||||
retain_top_func,
|
||||
} from "./common.js";
|
||||
|
||||
/**
|
||||
* Module that contains the inlining logic.
|
||||
*
|
||||
* @module
|
||||
*
|
||||
* The stars of the show are `inline_into_symbolref` and `inline_into_call`.
|
||||
*/
|
||||
|
||||
function within_array_or_object_literal(compressor) {
|
||||
var node, level = 0;
|
||||
while (node = compressor.parent(level++)) {
|
||||
if (node instanceof AST_Statement) return false;
|
||||
if (node instanceof AST_Array
|
||||
|| node instanceof AST_ObjectKeyVal
|
||||
|| node instanceof AST_Object) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function scope_encloses_variables_in_this_scope(scope, pulled_scope) {
|
||||
for (const enclosed of pulled_scope.enclosed) {
|
||||
if (pulled_scope.variables.has(enclosed.name)) {
|
||||
continue;
|
||||
}
|
||||
const looked_up = scope.find_variable(enclosed.name);
|
||||
if (looked_up) {
|
||||
if (looked_up === enclosed) continue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An extra check function for `top_retain` option, compare the length of const identifier
|
||||
* and init value length and return true if init value is longer than identifier. for example:
|
||||
* ```
|
||||
* // top_retain: ["example"]
|
||||
* const example = 100
|
||||
* ```
|
||||
* it will return false because length of "100" is short than identifier "example".
|
||||
*/
|
||||
function is_const_symbol_short_than_init_value(def, fixed_value) {
|
||||
if (def.orig.length === 1 && fixed_value) {
|
||||
const init_value_length = fixed_value.size();
|
||||
const identifer_length = def.name.length;
|
||||
return init_value_length > identifer_length;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function inline_into_symbolref(self, compressor) {
|
||||
if (compressor.in_computed_key()) return self;
|
||||
|
||||
const parent = compressor.parent();
|
||||
const def = self.definition();
|
||||
const nearest_scope = compressor.find_scope();
|
||||
let fixed = self.fixed_value();
|
||||
if (
|
||||
compressor.top_retain &&
|
||||
def.global &&
|
||||
compressor.top_retain(def) &&
|
||||
// when identifier is in top_retain option dose not mean we can always inline it.
|
||||
// if identifier name is longer then init value, we can replace it.
|
||||
is_const_symbol_short_than_init_value(def, fixed)
|
||||
) {
|
||||
// keep it
|
||||
def.fixed = false;
|
||||
def.single_use = false;
|
||||
return self;
|
||||
}
|
||||
|
||||
let single_use = def.single_use
|
||||
&& !(parent instanceof AST_Call
|
||||
&& (parent.is_callee_pure(compressor))
|
||||
|| has_annotation(parent, _NOINLINE))
|
||||
&& !(parent instanceof AST_Export
|
||||
&& fixed instanceof AST_Lambda
|
||||
&& fixed.name);
|
||||
|
||||
if (single_use && fixed instanceof AST_Node) {
|
||||
single_use =
|
||||
!fixed.has_side_effects(compressor)
|
||||
&& !fixed.may_throw(compressor);
|
||||
}
|
||||
|
||||
if (fixed instanceof AST_Class && def.scope !== self.scope) {
|
||||
return self;
|
||||
}
|
||||
|
||||
if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
|
||||
if (retain_top_func(fixed, compressor)) {
|
||||
single_use = false;
|
||||
} else if (def.scope !== self.scope
|
||||
&& (def.escaped == 1
|
||||
|| has_flag(fixed, INLINED)
|
||||
|| within_array_or_object_literal(compressor)
|
||||
|| !compressor.option("reduce_funcs"))) {
|
||||
single_use = false;
|
||||
} else if (is_recursive_ref(compressor, def)) {
|
||||
single_use = false;
|
||||
} else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
|
||||
single_use = fixed.is_constant_expression(self.scope);
|
||||
if (single_use == "f") {
|
||||
var scope = self.scope;
|
||||
do {
|
||||
if (scope instanceof AST_Defun || is_func_expr(scope)) {
|
||||
set_flag(scope, INLINED);
|
||||
}
|
||||
} while (scope = scope.parent_scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
|
||||
single_use =
|
||||
def.scope === self.scope
|
||||
&& !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
|
||||
|| parent instanceof AST_Call
|
||||
&& parent.expression === self
|
||||
&& !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
|
||||
&& !(fixed.name && fixed.name.definition().recursive_refs > 0);
|
||||
}
|
||||
|
||||
if (single_use && fixed) {
|
||||
if (fixed instanceof AST_DefClass) {
|
||||
set_flag(fixed, SQUEEZED);
|
||||
fixed = make_node(AST_ClassExpression, fixed, fixed);
|
||||
}
|
||||
if (fixed instanceof AST_Defun) {
|
||||
set_flag(fixed, SQUEEZED);
|
||||
fixed = make_node(AST_Function, fixed, fixed);
|
||||
}
|
||||
if (def.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) {
|
||||
const defun_def = fixed.name.definition();
|
||||
let lambda_def = fixed.variables.get(fixed.name.name);
|
||||
let name = lambda_def && lambda_def.orig[0];
|
||||
if (!(name instanceof AST_SymbolLambda)) {
|
||||
name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
|
||||
name.scope = fixed;
|
||||
fixed.name = name;
|
||||
lambda_def = fixed.def_function(name);
|
||||
}
|
||||
walk(fixed, node => {
|
||||
if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
|
||||
node.thedef = lambda_def;
|
||||
lambda_def.references.push(node);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (
|
||||
(fixed instanceof AST_Lambda || fixed instanceof AST_Class)
|
||||
&& fixed.parent_scope !== nearest_scope
|
||||
) {
|
||||
fixed = fixed.clone(true, compressor.get_toplevel());
|
||||
|
||||
nearest_scope.add_child_scope(fixed);
|
||||
}
|
||||
return fixed.optimize(compressor);
|
||||
}
|
||||
|
||||
// multiple uses
|
||||
if (fixed) {
|
||||
let replace;
|
||||
|
||||
if (fixed instanceof AST_This) {
|
||||
if (!(def.orig[0] instanceof AST_SymbolFunarg)
|
||||
&& def.references.every((ref) =>
|
||||
def.scope === ref.scope
|
||||
)) {
|
||||
replace = fixed;
|
||||
}
|
||||
} else {
|
||||
var ev = fixed.evaluate(compressor);
|
||||
if (
|
||||
ev !== fixed
|
||||
&& (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))
|
||||
) {
|
||||
replace = make_node_from_constant(ev, fixed);
|
||||
}
|
||||
}
|
||||
|
||||
if (replace) {
|
||||
const name_length = self.size(compressor);
|
||||
const replace_size = replace.size(compressor);
|
||||
|
||||
let overhead = 0;
|
||||
if (compressor.option("unused") && !compressor.exposed(def)) {
|
||||
overhead =
|
||||
(name_length + 2 + fixed.size(compressor)) /
|
||||
(def.references.length - def.assignments);
|
||||
}
|
||||
|
||||
if (replace_size <= name_length + overhead) {
|
||||
return replace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
export function inline_into_call(self, compressor) {
|
||||
if (compressor.in_computed_key()) return self;
|
||||
|
||||
var exp = self.expression;
|
||||
var fn = exp;
|
||||
var simple_args = self.args.every((arg) => !(arg instanceof AST_Expansion));
|
||||
|
||||
if (compressor.option("reduce_vars")
|
||||
&& fn instanceof AST_SymbolRef
|
||||
&& !has_annotation(self, _NOINLINE)
|
||||
) {
|
||||
const fixed = fn.fixed_value();
|
||||
|
||||
if (
|
||||
retain_top_func(fixed, compressor)
|
||||
|| !compressor.toplevel.funcs && exp.definition().global
|
||||
) {
|
||||
return self;
|
||||
}
|
||||
|
||||
fn = fixed;
|
||||
}
|
||||
|
||||
var is_func = fn instanceof AST_Lambda;
|
||||
|
||||
var stat = is_func && fn.body[0];
|
||||
var is_regular_func = is_func && !fn.is_generator && !fn.async;
|
||||
var can_inline = is_regular_func && compressor.option("inline") && !self.is_callee_pure(compressor);
|
||||
if (can_inline && stat instanceof AST_Return) {
|
||||
let returned = stat.value;
|
||||
if (!returned || returned.is_constant_expression()) {
|
||||
if (returned) {
|
||||
returned = returned.clone(true);
|
||||
} else {
|
||||
returned = make_node(AST_Undefined, self);
|
||||
}
|
||||
const args = self.args.concat(returned);
|
||||
return make_sequence(self, args).optimize(compressor);
|
||||
}
|
||||
|
||||
// optimize identity function
|
||||
if (
|
||||
fn.argnames.length === 1
|
||||
&& (fn.argnames[0] instanceof AST_SymbolFunarg)
|
||||
&& self.args.length < 2
|
||||
&& !(self.args[0] instanceof AST_Expansion)
|
||||
&& returned instanceof AST_SymbolRef
|
||||
&& returned.name === fn.argnames[0].name
|
||||
) {
|
||||
const replacement =
|
||||
(self.args[0] || make_node(AST_Undefined)).optimize(compressor);
|
||||
|
||||
let parent;
|
||||
if (
|
||||
replacement instanceof AST_PropAccess
|
||||
&& (parent = compressor.parent()) instanceof AST_Call
|
||||
&& parent.expression === self
|
||||
) {
|
||||
// identity function was being used to remove `this`, like in
|
||||
//
|
||||
// id(bag.no_this)(...)
|
||||
//
|
||||
// Replace with a larger but more effish (0, bag.no_this) wrapper.
|
||||
|
||||
return make_sequence(self, [
|
||||
make_node(AST_Number, self, { value: 0 }),
|
||||
replacement
|
||||
]);
|
||||
}
|
||||
// replace call with first argument or undefined if none passed
|
||||
return replacement;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_inline) {
|
||||
var scope, in_loop, level = -1;
|
||||
let def;
|
||||
let returned_value;
|
||||
let nearest_scope;
|
||||
if (simple_args
|
||||
&& !fn.uses_arguments
|
||||
&& !(compressor.parent() instanceof AST_Class)
|
||||
&& !(fn.name && fn instanceof AST_Function)
|
||||
&& (returned_value = can_flatten_body(stat))
|
||||
&& (exp === fn
|
||||
|| has_annotation(self, _INLINE)
|
||||
|| compressor.option("unused")
|
||||
&& (def = exp.definition()).references.length == 1
|
||||
&& !is_recursive_ref(compressor, def)
|
||||
&& fn.is_constant_expression(exp.scope))
|
||||
&& !has_annotation(self, _PURE | _NOINLINE)
|
||||
&& !fn.contains_this()
|
||||
&& can_inject_symbols()
|
||||
&& (nearest_scope = compressor.find_scope())
|
||||
&& !scope_encloses_variables_in_this_scope(nearest_scope, fn)
|
||||
&& !(function in_default_assign() {
|
||||
// Due to the fact function parameters have their own scope
|
||||
// which can't use `var something` in the function body within,
|
||||
// we simply don't inline into DefaultAssign.
|
||||
let i = 0;
|
||||
let p;
|
||||
while ((p = compressor.parent(i++))) {
|
||||
if (p instanceof AST_DefaultAssign) return true;
|
||||
if (p instanceof AST_Block) break;
|
||||
}
|
||||
return false;
|
||||
})()
|
||||
&& !(scope instanceof AST_Class)
|
||||
) {
|
||||
set_flag(fn, SQUEEZED);
|
||||
nearest_scope.add_child_scope(fn);
|
||||
return make_sequence(self, flatten_fn(returned_value)).optimize(compressor);
|
||||
}
|
||||
}
|
||||
|
||||
if (can_inline && has_annotation(self, _INLINE)) {
|
||||
set_flag(fn, SQUEEZED);
|
||||
fn = make_node(fn.CTOR === AST_Defun ? AST_Function : fn.CTOR, fn, fn);
|
||||
fn = fn.clone(true);
|
||||
fn.figure_out_scope({}, {
|
||||
parent_scope: compressor.find_scope(),
|
||||
toplevel: compressor.get_toplevel()
|
||||
});
|
||||
|
||||
return make_node(AST_Call, self, {
|
||||
expression: fn,
|
||||
args: self.args,
|
||||
}).optimize(compressor);
|
||||
}
|
||||
|
||||
const can_drop_this_call = is_regular_func && compressor.option("side_effects") && fn.body.every(is_empty);
|
||||
if (can_drop_this_call) {
|
||||
var args = self.args.concat(make_node(AST_Undefined, self));
|
||||
return make_sequence(self, args).optimize(compressor);
|
||||
}
|
||||
|
||||
if (compressor.option("negate_iife")
|
||||
&& compressor.parent() instanceof AST_SimpleStatement
|
||||
&& is_iife_call(self)) {
|
||||
return self.negate(compressor, true);
|
||||
}
|
||||
|
||||
var ev = self.evaluate(compressor);
|
||||
if (ev !== self) {
|
||||
ev = make_node_from_constant(ev, self).optimize(compressor);
|
||||
return best_of(compressor, ev, self);
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
function return_value(stat) {
|
||||
if (!stat) return make_node(AST_Undefined, self);
|
||||
if (stat instanceof AST_Return) {
|
||||
if (!stat.value) return make_node(AST_Undefined, self);
|
||||
return stat.value.clone(true);
|
||||
}
|
||||
if (stat instanceof AST_SimpleStatement) {
|
||||
return make_node(AST_UnaryPrefix, stat, {
|
||||
operator: "void",
|
||||
expression: stat.body.clone(true)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function can_flatten_body(stat) {
|
||||
var body = fn.body;
|
||||
var len = body.length;
|
||||
if (compressor.option("inline") < 3) {
|
||||
return len == 1 && return_value(stat);
|
||||
}
|
||||
stat = null;
|
||||
for (var i = 0; i < len; i++) {
|
||||
var line = body[i];
|
||||
if (line instanceof AST_Var) {
|
||||
if (stat && !line.definitions.every((var_def) =>
|
||||
!var_def.value
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
} else if (stat) {
|
||||
return false;
|
||||
} else if (!(line instanceof AST_EmptyStatement)) {
|
||||
stat = line;
|
||||
}
|
||||
}
|
||||
return return_value(stat);
|
||||
}
|
||||
|
||||
function can_inject_args(block_scoped, safe_to_inject) {
|
||||
for (var i = 0, len = fn.argnames.length; i < len; i++) {
|
||||
var arg = fn.argnames[i];
|
||||
if (arg instanceof AST_DefaultAssign) {
|
||||
if (has_flag(arg.left, UNUSED)) continue;
|
||||
return false;
|
||||
}
|
||||
if (arg instanceof AST_Destructuring) return false;
|
||||
if (arg instanceof AST_Expansion) {
|
||||
if (has_flag(arg.expression, UNUSED)) continue;
|
||||
return false;
|
||||
}
|
||||
if (has_flag(arg, UNUSED)) continue;
|
||||
if (!safe_to_inject
|
||||
|| block_scoped.has(arg.name)
|
||||
|| identifier_atom.has(arg.name)
|
||||
|| scope.conflicting_def(arg.name)) {
|
||||
return false;
|
||||
}
|
||||
if (in_loop) in_loop.push(arg.definition());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function can_inject_vars(block_scoped, safe_to_inject) {
|
||||
var len = fn.body.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
var stat = fn.body[i];
|
||||
if (!(stat instanceof AST_Var)) continue;
|
||||
if (!safe_to_inject) return false;
|
||||
for (var j = stat.definitions.length; --j >= 0;) {
|
||||
var name = stat.definitions[j].name;
|
||||
if (name instanceof AST_Destructuring
|
||||
|| block_scoped.has(name.name)
|
||||
|| identifier_atom.has(name.name)
|
||||
|| scope.conflicting_def(name.name)) {
|
||||
return false;
|
||||
}
|
||||
if (in_loop) in_loop.push(name.definition());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function can_inject_symbols() {
|
||||
var block_scoped = new Set();
|
||||
do {
|
||||
scope = compressor.parent(++level);
|
||||
if (scope.is_block_scope() && scope.block_scope) {
|
||||
// TODO this is sometimes undefined during compression.
|
||||
// But it should always have a value!
|
||||
scope.block_scope.variables.forEach(function (variable) {
|
||||
block_scoped.add(variable.name);
|
||||
});
|
||||
}
|
||||
if (scope instanceof AST_Catch) {
|
||||
// TODO can we delete? AST_Catch is a block scope.
|
||||
if (scope.argname) {
|
||||
block_scoped.add(scope.argname.name);
|
||||
}
|
||||
} else if (scope instanceof AST_IterationStatement) {
|
||||
in_loop = [];
|
||||
} else if (scope instanceof AST_SymbolRef) {
|
||||
if (scope.fixed_value() instanceof AST_Scope) return false;
|
||||
}
|
||||
} while (!(scope instanceof AST_Scope));
|
||||
|
||||
var safe_to_inject = !(scope instanceof AST_Toplevel) || compressor.toplevel.vars;
|
||||
var inline = compressor.option("inline");
|
||||
if (!can_inject_vars(block_scoped, inline >= 3 && safe_to_inject)) return false;
|
||||
if (!can_inject_args(block_scoped, inline >= 2 && safe_to_inject)) return false;
|
||||
return !in_loop || in_loop.length == 0 || !is_reachable(fn, in_loop);
|
||||
}
|
||||
|
||||
function append_var(decls, expressions, name, value) {
|
||||
var def = name.definition();
|
||||
|
||||
// Name already exists, only when a function argument had the same name
|
||||
const already_appended = scope.variables.has(name.name);
|
||||
if (!already_appended) {
|
||||
scope.variables.set(name.name, def);
|
||||
scope.enclosed.push(def);
|
||||
decls.push(make_node(AST_VarDef, name, {
|
||||
name: name,
|
||||
value: null
|
||||
}));
|
||||
}
|
||||
|
||||
var sym = make_node(AST_SymbolRef, name, name);
|
||||
def.references.push(sym);
|
||||
if (value) expressions.push(make_node(AST_Assign, self, {
|
||||
operator: "=",
|
||||
logical: false,
|
||||
left: sym,
|
||||
right: value.clone()
|
||||
}));
|
||||
}
|
||||
|
||||
function flatten_args(decls, expressions) {
|
||||
var len = fn.argnames.length;
|
||||
for (var i = self.args.length; --i >= len;) {
|
||||
expressions.push(self.args[i]);
|
||||
}
|
||||
for (i = len; --i >= 0;) {
|
||||
var name = fn.argnames[i];
|
||||
var value = self.args[i];
|
||||
if (has_flag(name, UNUSED) || !name.name || scope.conflicting_def(name.name)) {
|
||||
if (value) expressions.push(value);
|
||||
} else {
|
||||
var symbol = make_node(AST_SymbolVar, name, name);
|
||||
name.definition().orig.push(symbol);
|
||||
if (!value && in_loop) value = make_node(AST_Undefined, self);
|
||||
append_var(decls, expressions, symbol, value);
|
||||
}
|
||||
}
|
||||
decls.reverse();
|
||||
expressions.reverse();
|
||||
}
|
||||
|
||||
function flatten_vars(decls, expressions) {
|
||||
var pos = expressions.length;
|
||||
for (var i = 0, lines = fn.body.length; i < lines; i++) {
|
||||
var stat = fn.body[i];
|
||||
if (!(stat instanceof AST_Var)) continue;
|
||||
for (var j = 0, defs = stat.definitions.length; j < defs; j++) {
|
||||
var var_def = stat.definitions[j];
|
||||
var name = var_def.name;
|
||||
append_var(decls, expressions, name, var_def.value);
|
||||
if (in_loop && fn.argnames.every((argname) =>
|
||||
argname.name != name.name
|
||||
)) {
|
||||
var def = fn.variables.get(name.name);
|
||||
var sym = make_node(AST_SymbolRef, name, name);
|
||||
def.references.push(sym);
|
||||
expressions.splice(pos++, 0, make_node(AST_Assign, var_def, {
|
||||
operator: "=",
|
||||
logical: false,
|
||||
left: sym,
|
||||
right: make_node(AST_Undefined, name)
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function flatten_fn(returned_value) {
|
||||
var decls = [];
|
||||
var expressions = [];
|
||||
flatten_args(decls, expressions);
|
||||
flatten_vars(decls, expressions);
|
||||
expressions.push(returned_value);
|
||||
|
||||
if (decls.length) {
|
||||
const i = scope.body.indexOf(compressor.parent(level - 1)) + 1;
|
||||
scope.body.splice(i, 0, make_node(AST_Var, fn, {
|
||||
definitions: decls
|
||||
}));
|
||||
}
|
||||
|
||||
return expressions.map(exp => exp.clone(true));
|
||||
}
|
||||
}
|
206
node_modules/terser/lib/compress/native-objects.js
generated
vendored
Normal file
206
node_modules/terser/lib/compress/native-objects.js
generated
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
import { makePredicate } from "../utils/index.js";
|
||||
|
||||
// Lists of native methods, useful for `unsafe` option which assumes they exist.
|
||||
// Note: Lots of methods and functions are missing here, in case they aren't pure
|
||||
// or not available in all JS environments.
|
||||
|
||||
function make_nested_lookup(obj) {
|
||||
const out = new Map();
|
||||
for (var key of Object.keys(obj)) {
|
||||
out.set(key, makePredicate(obj[key]));
|
||||
}
|
||||
|
||||
const does_have = (global_name, fname) => {
|
||||
const inner_map = out.get(global_name);
|
||||
return inner_map != null && inner_map.has(fname);
|
||||
};
|
||||
return does_have;
|
||||
}
|
||||
|
||||
// Objects which are safe to access without throwing or causing a side effect.
|
||||
// Usually we'd check the `unsafe` option first but these are way too common for that
|
||||
export const pure_prop_access_globals = new Set([
|
||||
"Number",
|
||||
"String",
|
||||
"Array",
|
||||
"Object",
|
||||
"Function",
|
||||
"Promise",
|
||||
]);
|
||||
|
||||
const object_methods = [
|
||||
"constructor",
|
||||
"toString",
|
||||
"valueOf",
|
||||
];
|
||||
|
||||
export const is_pure_native_method = make_nested_lookup({
|
||||
Array: [
|
||||
"at",
|
||||
"flat",
|
||||
"includes",
|
||||
"indexOf",
|
||||
"join",
|
||||
"lastIndexOf",
|
||||
"slice",
|
||||
...object_methods,
|
||||
],
|
||||
Boolean: object_methods,
|
||||
Function: object_methods,
|
||||
Number: [
|
||||
"toExponential",
|
||||
"toFixed",
|
||||
"toPrecision",
|
||||
...object_methods,
|
||||
],
|
||||
Object: object_methods,
|
||||
RegExp: [
|
||||
"test",
|
||||
...object_methods,
|
||||
],
|
||||
String: [
|
||||
"at",
|
||||
"charAt",
|
||||
"charCodeAt",
|
||||
"charPointAt",
|
||||
"concat",
|
||||
"endsWith",
|
||||
"fromCharCode",
|
||||
"fromCodePoint",
|
||||
"includes",
|
||||
"indexOf",
|
||||
"italics",
|
||||
"lastIndexOf",
|
||||
"localeCompare",
|
||||
"match",
|
||||
"matchAll",
|
||||
"normalize",
|
||||
"padStart",
|
||||
"padEnd",
|
||||
"repeat",
|
||||
"replace",
|
||||
"replaceAll",
|
||||
"search",
|
||||
"slice",
|
||||
"split",
|
||||
"startsWith",
|
||||
"substr",
|
||||
"substring",
|
||||
"repeat",
|
||||
"toLocaleLowerCase",
|
||||
"toLocaleUpperCase",
|
||||
"toLowerCase",
|
||||
"toUpperCase",
|
||||
"trim",
|
||||
"trimEnd",
|
||||
"trimStart",
|
||||
...object_methods,
|
||||
],
|
||||
});
|
||||
|
||||
export const is_pure_native_fn = make_nested_lookup({
|
||||
Array: [
|
||||
"isArray",
|
||||
],
|
||||
Math: [
|
||||
"abs",
|
||||
"acos",
|
||||
"asin",
|
||||
"atan",
|
||||
"ceil",
|
||||
"cos",
|
||||
"exp",
|
||||
"floor",
|
||||
"log",
|
||||
"round",
|
||||
"sin",
|
||||
"sqrt",
|
||||
"tan",
|
||||
"atan2",
|
||||
"pow",
|
||||
"max",
|
||||
"min",
|
||||
],
|
||||
Number: [
|
||||
"isFinite",
|
||||
"isNaN",
|
||||
],
|
||||
Object: [
|
||||
"create",
|
||||
"getOwnPropertyDescriptor",
|
||||
"getOwnPropertyNames",
|
||||
"getPrototypeOf",
|
||||
"isExtensible",
|
||||
"isFrozen",
|
||||
"isSealed",
|
||||
"hasOwn",
|
||||
"keys",
|
||||
],
|
||||
String: [
|
||||
"fromCharCode",
|
||||
],
|
||||
});
|
||||
|
||||
// Known numeric values which come with JS environments
|
||||
export const is_pure_native_value = make_nested_lookup({
|
||||
Math: [
|
||||
"E",
|
||||
"LN10",
|
||||
"LN2",
|
||||
"LOG2E",
|
||||
"LOG10E",
|
||||
"PI",
|
||||
"SQRT1_2",
|
||||
"SQRT2",
|
||||
],
|
||||
Number: [
|
||||
"MAX_VALUE",
|
||||
"MIN_VALUE",
|
||||
"NaN",
|
||||
"NEGATIVE_INFINITY",
|
||||
"POSITIVE_INFINITY",
|
||||
],
|
||||
});
|
859
node_modules/terser/lib/compress/reduce-vars.js
generated
vendored
Normal file
859
node_modules/terser/lib/compress/reduce-vars.js
generated
vendored
Normal file
@ -0,0 +1,859 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
import {
|
||||
AST_Accessor,
|
||||
AST_Array,
|
||||
AST_Assign,
|
||||
AST_Await,
|
||||
AST_Binary,
|
||||
AST_Block,
|
||||
AST_Call,
|
||||
AST_Case,
|
||||
AST_Chain,
|
||||
AST_Class,
|
||||
AST_ClassStaticBlock,
|
||||
AST_ClassExpression,
|
||||
AST_Conditional,
|
||||
AST_Default,
|
||||
AST_Defun,
|
||||
AST_Destructuring,
|
||||
AST_Do,
|
||||
AST_Exit,
|
||||
AST_Expansion,
|
||||
AST_For,
|
||||
AST_ForIn,
|
||||
AST_If,
|
||||
AST_LabeledStatement,
|
||||
AST_Lambda,
|
||||
AST_New,
|
||||
AST_Node,
|
||||
AST_Number,
|
||||
AST_ObjectKeyVal,
|
||||
AST_PropAccess,
|
||||
AST_Scope,
|
||||
AST_Sequence,
|
||||
AST_SimpleStatement,
|
||||
AST_Symbol,
|
||||
AST_SymbolCatch,
|
||||
AST_SymbolConst,
|
||||
AST_SymbolDeclaration,
|
||||
AST_SymbolDefun,
|
||||
AST_SymbolFunarg,
|
||||
AST_SymbolLambda,
|
||||
AST_SymbolRef,
|
||||
AST_This,
|
||||
AST_Toplevel,
|
||||
AST_Try,
|
||||
AST_Unary,
|
||||
AST_UnaryPrefix,
|
||||
AST_Undefined,
|
||||
AST_VarDef,
|
||||
AST_While,
|
||||
AST_Yield,
|
||||
|
||||
walk,
|
||||
walk_body,
|
||||
walk_parent,
|
||||
} from "../ast.js";
|
||||
import { HOP, make_node, noop } from "../utils/index.js";
|
||||
|
||||
import { lazy_op, is_modified, is_lhs } from "./inference.js";
|
||||
import { INLINED, clear_flag } from "./compressor-flags.js";
|
||||
import { read_property, has_break_or_continue, is_recursive_ref } from "./common.js";
|
||||
|
||||
/**
|
||||
* Define the method AST_Node#reduce_vars, which goes through the AST in
|
||||
* execution order to perform basic flow analysis
|
||||
*/
|
||||
function def_reduce_vars(node, func) {
|
||||
node.DEFMETHOD("reduce_vars", func);
|
||||
}
|
||||
|
||||
def_reduce_vars(AST_Node, noop);
|
||||
|
||||
/** Clear definition properties */
|
||||
function reset_def(compressor, def) {
|
||||
def.assignments = 0;
|
||||
def.chained = false;
|
||||
def.direct_access = false;
|
||||
def.escaped = 0;
|
||||
def.recursive_refs = 0;
|
||||
def.references = [];
|
||||
def.single_use = undefined;
|
||||
if (
|
||||
def.scope.pinned()
|
||||
|| (def.orig[0] instanceof AST_SymbolFunarg && def.scope.uses_arguments)
|
||||
) {
|
||||
def.fixed = false;
|
||||
} else if (def.orig[0] instanceof AST_SymbolConst || !compressor.exposed(def)) {
|
||||
def.fixed = def.init;
|
||||
} else {
|
||||
def.fixed = false;
|
||||
}
|
||||
}
|
||||
|
||||
function reset_variables(tw, compressor, node) {
|
||||
node.variables.forEach(function(def) {
|
||||
reset_def(compressor, def);
|
||||
if (def.fixed === null) {
|
||||
tw.defs_to_safe_ids.set(def.id, tw.safe_ids);
|
||||
mark(tw, def, true);
|
||||
} else if (def.fixed) {
|
||||
tw.loop_ids.set(def.id, tw.in_loop);
|
||||
mark(tw, def, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function reset_block_variables(compressor, node) {
|
||||
if (node.block_scope) node.block_scope.variables.forEach((def) => {
|
||||
reset_def(compressor, def);
|
||||
});
|
||||
}
|
||||
|
||||
function push(tw) {
|
||||
tw.safe_ids = Object.create(tw.safe_ids);
|
||||
}
|
||||
|
||||
function pop(tw) {
|
||||
tw.safe_ids = Object.getPrototypeOf(tw.safe_ids);
|
||||
}
|
||||
|
||||
function mark(tw, def, safe) {
|
||||
tw.safe_ids[def.id] = safe;
|
||||
}
|
||||
|
||||
function safe_to_read(tw, def) {
|
||||
if (def.single_use == "m") return false;
|
||||
if (tw.safe_ids[def.id]) {
|
||||
if (def.fixed == null) {
|
||||
var orig = def.orig[0];
|
||||
if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false;
|
||||
def.fixed = make_node(AST_Undefined, orig);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return def.fixed instanceof AST_Defun;
|
||||
}
|
||||
|
||||
function safe_to_assign(tw, def, scope, value) {
|
||||
if (def.fixed === undefined) return true;
|
||||
let def_safe_ids;
|
||||
if (def.fixed === null
|
||||
&& (def_safe_ids = tw.defs_to_safe_ids.get(def.id))
|
||||
) {
|
||||
def_safe_ids[def.id] = false;
|
||||
tw.defs_to_safe_ids.delete(def.id);
|
||||
return true;
|
||||
}
|
||||
if (!HOP(tw.safe_ids, def.id)) return false;
|
||||
if (!safe_to_read(tw, def)) return false;
|
||||
if (def.fixed === false) return false;
|
||||
if (def.fixed != null && (!value || def.references.length > def.assignments)) return false;
|
||||
if (def.fixed instanceof AST_Defun) {
|
||||
return value instanceof AST_Node && def.fixed.parent_scope === scope;
|
||||
}
|
||||
return def.orig.every((sym) => {
|
||||
return !(sym instanceof AST_SymbolConst
|
||||
|| sym instanceof AST_SymbolDefun
|
||||
|| sym instanceof AST_SymbolLambda);
|
||||
});
|
||||
}
|
||||
|
||||
function ref_once(tw, compressor, def) {
|
||||
return compressor.option("unused")
|
||||
&& !def.scope.pinned()
|
||||
&& def.references.length - def.recursive_refs == 1
|
||||
&& tw.loop_ids.get(def.id) === tw.in_loop;
|
||||
}
|
||||
|
||||
function is_immutable(value) {
|
||||
if (!value) return false;
|
||||
return value.is_constant()
|
||||
|| value instanceof AST_Lambda
|
||||
|| value instanceof AST_This;
|
||||
}
|
||||
|
||||
// A definition "escapes" when its value can leave the point of use.
|
||||
// Example: `a = b || c`
|
||||
// In this example, "b" and "c" are escaping, because they're going into "a"
|
||||
//
|
||||
// def.escaped is != 0 when it escapes.
|
||||
//
|
||||
// When greater than 1, it means that N chained properties will be read off
|
||||
// of that def before an escape occurs. This is useful for evaluating
|
||||
// property accesses, where you need to know when to stop.
|
||||
function mark_escaped(tw, d, scope, node, value, level = 0, depth = 1) {
|
||||
var parent = tw.parent(level);
|
||||
if (value) {
|
||||
if (value.is_constant()) return;
|
||||
if (value instanceof AST_ClassExpression) return;
|
||||
}
|
||||
|
||||
if (
|
||||
parent instanceof AST_Assign && (parent.operator === "=" || parent.logical) && node === parent.right
|
||||
|| parent instanceof AST_Call && (node !== parent.expression || parent instanceof AST_New)
|
||||
|| parent instanceof AST_Exit && node === parent.value && node.scope !== d.scope
|
||||
|| parent instanceof AST_VarDef && node === parent.value
|
||||
|| parent instanceof AST_Yield && node === parent.value && node.scope !== d.scope
|
||||
) {
|
||||
if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1;
|
||||
if (!d.escaped || d.escaped > depth) d.escaped = depth;
|
||||
return;
|
||||
} else if (
|
||||
parent instanceof AST_Array
|
||||
|| parent instanceof AST_Await
|
||||
|| parent instanceof AST_Binary && lazy_op.has(parent.operator)
|
||||
|| parent instanceof AST_Conditional && node !== parent.condition
|
||||
|| parent instanceof AST_Expansion
|
||||
|| parent instanceof AST_Sequence && node === parent.tail_node()
|
||||
) {
|
||||
mark_escaped(tw, d, scope, parent, parent, level + 1, depth);
|
||||
} else if (parent instanceof AST_ObjectKeyVal && node === parent.value) {
|
||||
var obj = tw.parent(level + 1);
|
||||
|
||||
mark_escaped(tw, d, scope, obj, obj, level + 2, depth);
|
||||
} else if (parent instanceof AST_PropAccess && node === parent.expression) {
|
||||
value = read_property(value, parent.property);
|
||||
|
||||
mark_escaped(tw, d, scope, parent, value, level + 1, depth + 1);
|
||||
if (value) return;
|
||||
}
|
||||
|
||||
if (level > 0) return;
|
||||
if (parent instanceof AST_Sequence && node !== parent.tail_node()) return;
|
||||
if (parent instanceof AST_SimpleStatement) return;
|
||||
|
||||
d.direct_access = true;
|
||||
}
|
||||
|
||||
const suppress = node => walk(node, node => {
|
||||
if (!(node instanceof AST_Symbol)) return;
|
||||
var d = node.definition();
|
||||
if (!d) return;
|
||||
if (node instanceof AST_SymbolRef) d.references.push(node);
|
||||
d.fixed = false;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Accessor, function(tw, descend, compressor) {
|
||||
push(tw);
|
||||
reset_variables(tw, compressor, this);
|
||||
descend();
|
||||
pop(tw);
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Assign, function(tw, descend, compressor) {
|
||||
var node = this;
|
||||
if (node.left instanceof AST_Destructuring) {
|
||||
suppress(node.left);
|
||||
return;
|
||||
}
|
||||
|
||||
const finish_walk = () => {
|
||||
if (node.logical) {
|
||||
node.left.walk(tw);
|
||||
|
||||
push(tw);
|
||||
node.right.walk(tw);
|
||||
pop(tw);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var sym = node.left;
|
||||
if (!(sym instanceof AST_SymbolRef)) return finish_walk();
|
||||
|
||||
var def = sym.definition();
|
||||
var safe = safe_to_assign(tw, def, sym.scope, node.right);
|
||||
def.assignments++;
|
||||
if (!safe) return finish_walk();
|
||||
|
||||
var fixed = def.fixed;
|
||||
if (!fixed && node.operator != "=" && !node.logical) return finish_walk();
|
||||
|
||||
var eq = node.operator == "=";
|
||||
var value = eq ? node.right : node;
|
||||
if (is_modified(compressor, tw, node, value, 0)) return finish_walk();
|
||||
|
||||
def.references.push(sym);
|
||||
|
||||
if (!node.logical) {
|
||||
if (!eq) def.chained = true;
|
||||
|
||||
def.fixed = eq ? function() {
|
||||
return node.right;
|
||||
} : function() {
|
||||
return make_node(AST_Binary, node, {
|
||||
operator: node.operator.slice(0, -1),
|
||||
left: fixed instanceof AST_Node ? fixed : fixed(),
|
||||
right: node.right
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (node.logical) {
|
||||
mark(tw, def, false);
|
||||
push(tw);
|
||||
node.right.walk(tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
}
|
||||
|
||||
mark(tw, def, false);
|
||||
node.right.walk(tw);
|
||||
mark(tw, def, true);
|
||||
|
||||
mark_escaped(tw, def, sym.scope, node, value, 0, 1);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Binary, function(tw) {
|
||||
if (!lazy_op.has(this.operator)) return;
|
||||
this.left.walk(tw);
|
||||
push(tw);
|
||||
this.right.walk(tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Block, function(tw, descend, compressor) {
|
||||
reset_block_variables(compressor, this);
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Case, function(tw) {
|
||||
push(tw);
|
||||
this.expression.walk(tw);
|
||||
pop(tw);
|
||||
push(tw);
|
||||
walk_body(this, tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Class, function(tw, descend) {
|
||||
clear_flag(this, INLINED);
|
||||
push(tw);
|
||||
descend();
|
||||
pop(tw);
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_ClassStaticBlock, function(tw, descend, compressor) {
|
||||
reset_block_variables(compressor, this);
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Conditional, function(tw) {
|
||||
this.condition.walk(tw);
|
||||
push(tw);
|
||||
this.consequent.walk(tw);
|
||||
pop(tw);
|
||||
push(tw);
|
||||
this.alternative.walk(tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Chain, function(tw, descend) {
|
||||
// Chains' conditions apply left-to-right, cumulatively.
|
||||
// If we walk normally we don't go in that order because we would pop before pushing again
|
||||
// Solution: AST_PropAccess and AST_Call push when they are optional, and never pop.
|
||||
// Then we pop everything when they are done being walked.
|
||||
const safe_ids = tw.safe_ids;
|
||||
|
||||
descend();
|
||||
|
||||
// Unroll back to start
|
||||
tw.safe_ids = safe_ids;
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Call, function (tw) {
|
||||
this.expression.walk(tw);
|
||||
|
||||
if (this.optional) {
|
||||
// Never pop -- it's popped at AST_Chain above
|
||||
push(tw);
|
||||
}
|
||||
|
||||
for (const arg of this.args) arg.walk(tw);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_PropAccess, function (tw) {
|
||||
if (!this.optional) return;
|
||||
|
||||
this.expression.walk(tw);
|
||||
|
||||
// Never pop -- it's popped at AST_Chain above
|
||||
push(tw);
|
||||
|
||||
if (this.property instanceof AST_Node) this.property.walk(tw);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Default, function(tw, descend) {
|
||||
push(tw);
|
||||
descend();
|
||||
pop(tw);
|
||||
return true;
|
||||
});
|
||||
|
||||
function mark_lambda(tw, descend, compressor) {
|
||||
clear_flag(this, INLINED);
|
||||
push(tw);
|
||||
reset_variables(tw, compressor, this);
|
||||
|
||||
var iife;
|
||||
if (!this.name
|
||||
&& !this.uses_arguments
|
||||
&& !this.pinned()
|
||||
&& (iife = tw.parent()) instanceof AST_Call
|
||||
&& iife.expression === this
|
||||
&& !iife.args.some(arg => arg instanceof AST_Expansion)
|
||||
&& this.argnames.every(arg_name => arg_name instanceof AST_Symbol)
|
||||
) {
|
||||
// Virtually turn IIFE parameters into variable definitions:
|
||||
// (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})()
|
||||
// So existing transformation rules can work on them.
|
||||
this.argnames.forEach((arg, i) => {
|
||||
if (!arg.definition) return;
|
||||
var d = arg.definition();
|
||||
// Avoid setting fixed when there's more than one origin for a variable value
|
||||
if (d.orig.length > 1) return;
|
||||
if (d.fixed === undefined && (!this.uses_arguments || tw.has_directive("use strict"))) {
|
||||
d.fixed = function() {
|
||||
return iife.args[i] || make_node(AST_Undefined, iife);
|
||||
};
|
||||
tw.loop_ids.set(d.id, tw.in_loop);
|
||||
mark(tw, d, true);
|
||||
} else {
|
||||
d.fixed = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
descend();
|
||||
pop(tw);
|
||||
|
||||
handle_defined_after_hoist(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's possible for a hoisted function to use something that's not defined yet. Example:
|
||||
*
|
||||
* hoisted();
|
||||
* var defined_after = true;
|
||||
* function hoisted() {
|
||||
* // use defined_after
|
||||
* }
|
||||
*
|
||||
* Or even indirectly:
|
||||
*
|
||||
* B();
|
||||
* var defined_after = true;
|
||||
* function A() {
|
||||
* // use defined_after
|
||||
* }
|
||||
* function B() {
|
||||
* A();
|
||||
* }
|
||||
*
|
||||
* Access a variable before declaration will either throw a ReferenceError
|
||||
* (if the variable is declared with `let` or `const`),
|
||||
* or get an `undefined` (if the variable is declared with `var`).
|
||||
*
|
||||
* If the variable is inlined into the function, the behavior will change.
|
||||
*
|
||||
* This function is called on the parent to disallow inlining of such variables,
|
||||
*/
|
||||
function handle_defined_after_hoist(parent) {
|
||||
const defuns = [];
|
||||
walk(parent, node => {
|
||||
if (node === parent) return;
|
||||
if (node instanceof AST_Defun) {
|
||||
defuns.push(node);
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
node instanceof AST_Scope
|
||||
|| node instanceof AST_SimpleStatement
|
||||
) return true;
|
||||
});
|
||||
|
||||
// `defun` id to array of `defun` it uses
|
||||
const defun_dependencies_map = new Map();
|
||||
// `defun` id to array of enclosing `def` that are used by the function
|
||||
const dependencies_map = new Map();
|
||||
// all symbol ids that will be tracked for read/write
|
||||
const symbols_of_interest = new Set();
|
||||
const defuns_of_interest = new Set();
|
||||
|
||||
for (const defun of defuns) {
|
||||
const fname_def = defun.name.definition();
|
||||
const enclosing_defs = [];
|
||||
|
||||
for (const def of defun.enclosed) {
|
||||
if (
|
||||
def.fixed === false
|
||||
|| def === fname_def
|
||||
|| def.scope.get_defun_scope() !== parent
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
symbols_of_interest.add(def.id);
|
||||
|
||||
// found a reference to another function
|
||||
if (
|
||||
def.assignments === 0
|
||||
&& def.orig.length === 1
|
||||
&& def.orig[0] instanceof AST_SymbolDefun
|
||||
) {
|
||||
defuns_of_interest.add(def.id);
|
||||
symbols_of_interest.add(def.id);
|
||||
|
||||
defuns_of_interest.add(fname_def.id);
|
||||
symbols_of_interest.add(fname_def.id);
|
||||
|
||||
if (!defun_dependencies_map.has(fname_def.id)) {
|
||||
defun_dependencies_map.set(fname_def.id, []);
|
||||
}
|
||||
defun_dependencies_map.get(fname_def.id).push(def.id);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
enclosing_defs.push(def);
|
||||
}
|
||||
|
||||
if (enclosing_defs.length) {
|
||||
dependencies_map.set(fname_def.id, enclosing_defs);
|
||||
defuns_of_interest.add(fname_def.id);
|
||||
symbols_of_interest.add(fname_def.id);
|
||||
}
|
||||
}
|
||||
|
||||
// No defuns use outside constants
|
||||
if (!dependencies_map.size) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Increment to count "symbols of interest" (defuns or defs) that we found.
|
||||
// These are tracked in AST order so we can check which is after which.
|
||||
let symbol_index = 1;
|
||||
// Map a defun ID to its first read (a `symbol_index`)
|
||||
const defun_first_read_map = new Map();
|
||||
// Map a symbol ID to its last write (a `symbol_index`)
|
||||
const symbol_last_write_map = new Map();
|
||||
|
||||
walk_parent(parent, (node, walk_info) => {
|
||||
if (node instanceof AST_Symbol && node.thedef) {
|
||||
const id = node.definition().id;
|
||||
|
||||
symbol_index++;
|
||||
|
||||
// Track last-writes to symbols
|
||||
if (symbols_of_interest.has(id)) {
|
||||
if (node instanceof AST_SymbolDeclaration || is_lhs(node, walk_info.parent())) {
|
||||
symbol_last_write_map.set(id, symbol_index);
|
||||
}
|
||||
}
|
||||
|
||||
// Track first-reads of defuns (refined later)
|
||||
if (defuns_of_interest.has(id)) {
|
||||
if (!defun_first_read_map.has(id) && !is_recursive_ref(walk_info, id)) {
|
||||
defun_first_read_map.set(id, symbol_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Refine `defun_first_read_map` to be as high as possible
|
||||
for (const [defun, defun_first_read] of defun_first_read_map) {
|
||||
// Update all depdencies of `defun`
|
||||
const queue = new Set(defun_dependencies_map.get(defun));
|
||||
for (const enclosed_defun of queue) {
|
||||
let enclosed_defun_first_read = defun_first_read_map.get(enclosed_defun);
|
||||
if (enclosed_defun_first_read != null && enclosed_defun_first_read < defun_first_read) {
|
||||
continue;
|
||||
}
|
||||
|
||||
defun_first_read_map.set(enclosed_defun, defun_first_read);
|
||||
|
||||
for (const enclosed_enclosed_defun of defun_dependencies_map.get(enclosed_defun) || []) {
|
||||
queue.add(enclosed_enclosed_defun);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure write-then-read order, otherwise clear `fixed`
|
||||
// This is safe because last-writes (found_symbol_writes) are assumed to be as late as possible, and first-reads (defun_first_read_map) are assumed to be as early as possible.
|
||||
for (const [defun, defs] of dependencies_map) {
|
||||
const defun_first_read = defun_first_read_map.get(defun);
|
||||
if (defun_first_read === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const def of defs) {
|
||||
if (def.fixed === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let def_last_write = symbol_last_write_map.get(def.id) || 0;
|
||||
|
||||
if (defun_first_read < def_last_write) {
|
||||
def.fixed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def_reduce_vars(AST_Lambda, mark_lambda);
|
||||
|
||||
def_reduce_vars(AST_Do, function(tw, descend, compressor) {
|
||||
reset_block_variables(compressor, this);
|
||||
const saved_loop = tw.in_loop;
|
||||
tw.in_loop = this;
|
||||
push(tw);
|
||||
this.body.walk(tw);
|
||||
if (has_break_or_continue(this)) {
|
||||
pop(tw);
|
||||
push(tw);
|
||||
}
|
||||
this.condition.walk(tw);
|
||||
pop(tw);
|
||||
tw.in_loop = saved_loop;
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_For, function(tw, descend, compressor) {
|
||||
reset_block_variables(compressor, this);
|
||||
if (this.init) this.init.walk(tw);
|
||||
const saved_loop = tw.in_loop;
|
||||
tw.in_loop = this;
|
||||
push(tw);
|
||||
if (this.condition) this.condition.walk(tw);
|
||||
this.body.walk(tw);
|
||||
if (this.step) {
|
||||
if (has_break_or_continue(this)) {
|
||||
pop(tw);
|
||||
push(tw);
|
||||
}
|
||||
this.step.walk(tw);
|
||||
}
|
||||
pop(tw);
|
||||
tw.in_loop = saved_loop;
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_ForIn, function(tw, descend, compressor) {
|
||||
reset_block_variables(compressor, this);
|
||||
suppress(this.init);
|
||||
this.object.walk(tw);
|
||||
const saved_loop = tw.in_loop;
|
||||
tw.in_loop = this;
|
||||
push(tw);
|
||||
this.body.walk(tw);
|
||||
pop(tw);
|
||||
tw.in_loop = saved_loop;
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_If, function(tw) {
|
||||
this.condition.walk(tw);
|
||||
push(tw);
|
||||
this.body.walk(tw);
|
||||
pop(tw);
|
||||
if (this.alternative) {
|
||||
push(tw);
|
||||
this.alternative.walk(tw);
|
||||
pop(tw);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_LabeledStatement, function(tw) {
|
||||
push(tw);
|
||||
this.body.walk(tw);
|
||||
pop(tw);
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_SymbolCatch, function() {
|
||||
this.definition().fixed = false;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_SymbolRef, function(tw, descend, compressor) {
|
||||
var d = this.definition();
|
||||
d.references.push(this);
|
||||
if (d.references.length == 1
|
||||
&& !d.fixed
|
||||
&& d.orig[0] instanceof AST_SymbolDefun) {
|
||||
tw.loop_ids.set(d.id, tw.in_loop);
|
||||
}
|
||||
var fixed_value;
|
||||
if (d.fixed === undefined || !safe_to_read(tw, d)) {
|
||||
d.fixed = false;
|
||||
} else if (d.fixed) {
|
||||
fixed_value = this.fixed_value();
|
||||
if (
|
||||
fixed_value instanceof AST_Lambda
|
||||
&& is_recursive_ref(tw, d)
|
||||
) {
|
||||
d.recursive_refs++;
|
||||
} else if (fixed_value
|
||||
&& !compressor.exposed(d)
|
||||
&& ref_once(tw, compressor, d)
|
||||
) {
|
||||
d.single_use =
|
||||
fixed_value instanceof AST_Lambda && !fixed_value.pinned()
|
||||
|| fixed_value instanceof AST_Class
|
||||
|| d.scope === this.scope && fixed_value.is_constant_expression();
|
||||
} else {
|
||||
d.single_use = false;
|
||||
}
|
||||
if (is_modified(compressor, tw, this, fixed_value, 0, is_immutable(fixed_value))) {
|
||||
if (d.single_use) {
|
||||
d.single_use = "m";
|
||||
} else {
|
||||
d.fixed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
mark_escaped(tw, d, this.scope, this, fixed_value, 0, 1);
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Toplevel, function(tw, descend, compressor) {
|
||||
this.globals.forEach(function(def) {
|
||||
reset_def(compressor, def);
|
||||
});
|
||||
reset_variables(tw, compressor, this);
|
||||
descend();
|
||||
handle_defined_after_hoist(this);
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Try, function(tw, descend, compressor) {
|
||||
reset_block_variables(compressor, this);
|
||||
push(tw);
|
||||
this.body.walk(tw);
|
||||
pop(tw);
|
||||
if (this.bcatch) {
|
||||
push(tw);
|
||||
this.bcatch.walk(tw);
|
||||
pop(tw);
|
||||
}
|
||||
if (this.bfinally) this.bfinally.walk(tw);
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_Unary, function(tw) {
|
||||
var node = this;
|
||||
if (node.operator !== "++" && node.operator !== "--") return;
|
||||
var exp = node.expression;
|
||||
if (!(exp instanceof AST_SymbolRef)) return;
|
||||
var def = exp.definition();
|
||||
var safe = safe_to_assign(tw, def, exp.scope, true);
|
||||
def.assignments++;
|
||||
if (!safe) return;
|
||||
var fixed = def.fixed;
|
||||
if (!fixed) return;
|
||||
def.references.push(exp);
|
||||
def.chained = true;
|
||||
def.fixed = function() {
|
||||
return make_node(AST_Binary, node, {
|
||||
operator: node.operator.slice(0, -1),
|
||||
left: make_node(AST_UnaryPrefix, node, {
|
||||
operator: "+",
|
||||
expression: fixed instanceof AST_Node ? fixed : fixed()
|
||||
}),
|
||||
right: make_node(AST_Number, node, {
|
||||
value: 1
|
||||
})
|
||||
});
|
||||
};
|
||||
mark(tw, def, true);
|
||||
return true;
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_VarDef, function(tw, descend) {
|
||||
var node = this;
|
||||
if (node.name instanceof AST_Destructuring) {
|
||||
suppress(node.name);
|
||||
return;
|
||||
}
|
||||
var d = node.name.definition();
|
||||
if (node.value) {
|
||||
if (safe_to_assign(tw, d, node.name.scope, node.value)) {
|
||||
d.fixed = function() {
|
||||
return node.value;
|
||||
};
|
||||
tw.loop_ids.set(d.id, tw.in_loop);
|
||||
mark(tw, d, false);
|
||||
descend();
|
||||
mark(tw, d, true);
|
||||
return true;
|
||||
} else {
|
||||
d.fixed = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
def_reduce_vars(AST_While, function(tw, descend, compressor) {
|
||||
reset_block_variables(compressor, this);
|
||||
const saved_loop = tw.in_loop;
|
||||
tw.in_loop = this;
|
||||
push(tw);
|
||||
descend();
|
||||
pop(tw);
|
||||
tw.in_loop = saved_loop;
|
||||
return true;
|
||||
});
|
1516
node_modules/terser/lib/compress/tighten-body.js
generated
vendored
Normal file
1516
node_modules/terser/lib/compress/tighten-body.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
300
node_modules/terser/lib/equivalent-to.js
generated
vendored
Normal file
300
node_modules/terser/lib/equivalent-to.js
generated
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
import {
|
||||
AST_Array,
|
||||
AST_Atom,
|
||||
AST_Await,
|
||||
AST_BigInt,
|
||||
AST_Binary,
|
||||
AST_Block,
|
||||
AST_Call,
|
||||
AST_Catch,
|
||||
AST_Chain,
|
||||
AST_Class,
|
||||
AST_ClassProperty,
|
||||
AST_ClassPrivateProperty,
|
||||
AST_ConciseMethod,
|
||||
AST_Conditional,
|
||||
AST_Debugger,
|
||||
AST_Definitions,
|
||||
AST_Destructuring,
|
||||
AST_Directive,
|
||||
AST_Do,
|
||||
AST_Dot,
|
||||
AST_DotHash,
|
||||
AST_EmptyStatement,
|
||||
AST_Expansion,
|
||||
AST_Export,
|
||||
AST_Finally,
|
||||
AST_For,
|
||||
AST_ForIn,
|
||||
AST_ForOf,
|
||||
AST_If,
|
||||
AST_Import,
|
||||
AST_ImportMeta,
|
||||
AST_Jump,
|
||||
AST_LabeledStatement,
|
||||
AST_Lambda,
|
||||
AST_LoopControl,
|
||||
AST_NameMapping,
|
||||
AST_NewTarget,
|
||||
AST_Node,
|
||||
AST_Number,
|
||||
AST_Object,
|
||||
AST_ObjectGetter,
|
||||
AST_ObjectKeyVal,
|
||||
AST_ObjectProperty,
|
||||
AST_ObjectSetter,
|
||||
AST_PrefixedTemplateString,
|
||||
AST_PrivateMethod,
|
||||
AST_PropAccess,
|
||||
AST_RegExp,
|
||||
AST_Sequence,
|
||||
AST_SimpleStatement,
|
||||
AST_String,
|
||||
AST_Super,
|
||||
AST_Switch,
|
||||
AST_SwitchBranch,
|
||||
AST_Symbol,
|
||||
AST_TemplateSegment,
|
||||
AST_TemplateString,
|
||||
AST_This,
|
||||
AST_Toplevel,
|
||||
AST_Try,
|
||||
AST_Unary,
|
||||
AST_VarDef,
|
||||
AST_While,
|
||||
AST_With,
|
||||
AST_Yield
|
||||
} from "./ast.js";
|
||||
|
||||
const shallow_cmp = (node1, node2) => {
|
||||
return (
|
||||
node1 === null && node2 === null
|
||||
|| node1.TYPE === node2.TYPE && node1.shallow_cmp(node2)
|
||||
);
|
||||
};
|
||||
|
||||
export const equivalent_to = (tree1, tree2) => {
|
||||
if (!shallow_cmp(tree1, tree2)) return false;
|
||||
const walk_1_state = [tree1];
|
||||
const walk_2_state = [tree2];
|
||||
|
||||
const walk_1_push = walk_1_state.push.bind(walk_1_state);
|
||||
const walk_2_push = walk_2_state.push.bind(walk_2_state);
|
||||
|
||||
while (walk_1_state.length && walk_2_state.length) {
|
||||
const node_1 = walk_1_state.pop();
|
||||
const node_2 = walk_2_state.pop();
|
||||
|
||||
if (!shallow_cmp(node_1, node_2)) return false;
|
||||
|
||||
node_1._children_backwards(walk_1_push);
|
||||
node_2._children_backwards(walk_2_push);
|
||||
|
||||
if (walk_1_state.length !== walk_2_state.length) {
|
||||
// Different number of children
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return walk_1_state.length == 0 && walk_2_state.length == 0;
|
||||
};
|
||||
|
||||
const pass_through = () => true;
|
||||
|
||||
AST_Node.prototype.shallow_cmp = function () {
|
||||
throw new Error("did not find a shallow_cmp function for " + this.constructor.name);
|
||||
};
|
||||
|
||||
AST_Debugger.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Directive.prototype.shallow_cmp = function(other) {
|
||||
return this.value === other.value;
|
||||
};
|
||||
|
||||
AST_SimpleStatement.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Block.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_EmptyStatement.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_LabeledStatement.prototype.shallow_cmp = function(other) {
|
||||
return this.label.name === other.label.name;
|
||||
};
|
||||
|
||||
AST_Do.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_While.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_For.prototype.shallow_cmp = function(other) {
|
||||
return (this.init == null ? other.init == null : this.init === other.init) && (this.condition == null ? other.condition == null : this.condition === other.condition) && (this.step == null ? other.step == null : this.step === other.step);
|
||||
};
|
||||
|
||||
AST_ForIn.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_ForOf.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_With.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Toplevel.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Expansion.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Lambda.prototype.shallow_cmp = function(other) {
|
||||
return this.is_generator === other.is_generator && this.async === other.async;
|
||||
};
|
||||
|
||||
AST_Destructuring.prototype.shallow_cmp = function(other) {
|
||||
return this.is_array === other.is_array;
|
||||
};
|
||||
|
||||
AST_PrefixedTemplateString.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_TemplateString.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_TemplateSegment.prototype.shallow_cmp = function(other) {
|
||||
return this.value === other.value;
|
||||
};
|
||||
|
||||
AST_Jump.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_LoopControl.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Await.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Yield.prototype.shallow_cmp = function(other) {
|
||||
return this.is_star === other.is_star;
|
||||
};
|
||||
|
||||
AST_If.prototype.shallow_cmp = function(other) {
|
||||
return this.alternative == null ? other.alternative == null : this.alternative === other.alternative;
|
||||
};
|
||||
|
||||
AST_Switch.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_SwitchBranch.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Try.prototype.shallow_cmp = function(other) {
|
||||
return (this.body === other.body) && (this.bcatch == null ? other.bcatch == null : this.bcatch === other.bcatch) && (this.bfinally == null ? other.bfinally == null : this.bfinally === other.bfinally);
|
||||
};
|
||||
|
||||
AST_Catch.prototype.shallow_cmp = function(other) {
|
||||
return this.argname == null ? other.argname == null : this.argname === other.argname;
|
||||
};
|
||||
|
||||
AST_Finally.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Definitions.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_VarDef.prototype.shallow_cmp = function(other) {
|
||||
return this.value == null ? other.value == null : this.value === other.value;
|
||||
};
|
||||
|
||||
AST_NameMapping.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Import.prototype.shallow_cmp = function(other) {
|
||||
return (this.imported_name == null ? other.imported_name == null : this.imported_name === other.imported_name) && (this.imported_names == null ? other.imported_names == null : this.imported_names === other.imported_names);
|
||||
};
|
||||
|
||||
AST_ImportMeta.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Export.prototype.shallow_cmp = function(other) {
|
||||
return (this.exported_definition == null ? other.exported_definition == null : this.exported_definition === other.exported_definition) && (this.exported_value == null ? other.exported_value == null : this.exported_value === other.exported_value) && (this.exported_names == null ? other.exported_names == null : this.exported_names === other.exported_names) && this.module_name === other.module_name && this.is_default === other.is_default;
|
||||
};
|
||||
|
||||
AST_Call.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Sequence.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_PropAccess.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Chain.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Dot.prototype.shallow_cmp = function(other) {
|
||||
return this.property === other.property;
|
||||
};
|
||||
|
||||
AST_DotHash.prototype.shallow_cmp = function(other) {
|
||||
return this.property === other.property;
|
||||
};
|
||||
|
||||
AST_Unary.prototype.shallow_cmp = function(other) {
|
||||
return this.operator === other.operator;
|
||||
};
|
||||
|
||||
AST_Binary.prototype.shallow_cmp = function(other) {
|
||||
return this.operator === other.operator;
|
||||
};
|
||||
|
||||
AST_Conditional.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Array.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Object.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_ObjectProperty.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_ObjectKeyVal.prototype.shallow_cmp = function(other) {
|
||||
return this.key === other.key;
|
||||
};
|
||||
|
||||
AST_ObjectSetter.prototype.shallow_cmp = function(other) {
|
||||
return this.static === other.static;
|
||||
};
|
||||
|
||||
AST_ObjectGetter.prototype.shallow_cmp = function(other) {
|
||||
return this.static === other.static;
|
||||
};
|
||||
|
||||
AST_ConciseMethod.prototype.shallow_cmp = function(other) {
|
||||
return this.static === other.static && this.is_generator === other.is_generator && this.async === other.async;
|
||||
};
|
||||
|
||||
AST_PrivateMethod.prototype.shallow_cmp = function(other) {
|
||||
return this.static === other.static && this.is_generator === other.is_generator && this.async === other.async;
|
||||
};
|
||||
|
||||
AST_Class.prototype.shallow_cmp = function(other) {
|
||||
return (this.name == null ? other.name == null : this.name === other.name) && (this.extends == null ? other.extends == null : this.extends === other.extends);
|
||||
};
|
||||
|
||||
AST_ClassProperty.prototype.shallow_cmp = function(other) {
|
||||
return this.static === other.static
|
||||
&& (typeof this.key === "string"
|
||||
? this.key === other.key
|
||||
: true /* AST_Node handled elsewhere */);
|
||||
};
|
||||
|
||||
AST_ClassPrivateProperty.prototype.shallow_cmp = function(other) {
|
||||
return this.static === other.static;
|
||||
};
|
||||
|
||||
AST_Symbol.prototype.shallow_cmp = function(other) {
|
||||
return this.name === other.name;
|
||||
};
|
||||
|
||||
AST_NewTarget.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_This.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_Super.prototype.shallow_cmp = pass_through;
|
||||
|
||||
AST_String.prototype.shallow_cmp = function(other) {
|
||||
return this.value === other.value;
|
||||
};
|
||||
|
||||
AST_Number.prototype.shallow_cmp = function(other) {
|
||||
return this.value === other.value;
|
||||
};
|
||||
|
||||
AST_BigInt.prototype.shallow_cmp = function(other) {
|
||||
return this.value === other.value;
|
||||
};
|
||||
|
||||
AST_RegExp.prototype.shallow_cmp = function (other) {
|
||||
return (
|
||||
this.value.flags === other.value.flags
|
||||
&& this.value.source === other.value.source
|
||||
);
|
||||
};
|
||||
|
||||
AST_Atom.prototype.shallow_cmp = pass_through;
|
412
node_modules/terser/lib/minify.js
generated
vendored
Normal file
412
node_modules/terser/lib/minify.js
generated
vendored
Normal file
@ -0,0 +1,412 @@
|
||||
"use strict";
|
||||
/* eslint-env browser, es6, node */
|
||||
|
||||
import {
|
||||
defaults,
|
||||
map_from_object,
|
||||
map_to_object,
|
||||
HOP,
|
||||
} from "./utils/index.js";
|
||||
import { AST_Toplevel, AST_Node, walk, AST_Scope } from "./ast.js";
|
||||
import { parse } from "./parse.js";
|
||||
import { OutputStream } from "./output.js";
|
||||
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,
|
||||
find_annotated_props,
|
||||
} from "./propmangle.js";
|
||||
|
||||
// to/from base64 functions
|
||||
// Prefer built-in Buffer, if available, then use hack
|
||||
// https://developer.mozilla.org/en-US/docs/Glossary/Base64#The_Unicode_Problem
|
||||
var to_ascii = typeof Buffer !== "undefined"
|
||||
? (b64) => Buffer.from(b64, "base64").toString()
|
||||
: (b64) => decodeURIComponent(escape(atob(b64)));
|
||||
var to_base64 = typeof Buffer !== "undefined"
|
||||
? (str) => Buffer.from(str).toString("base64")
|
||||
: (str) => btoa(unescape(encodeURIComponent(str)));
|
||||
|
||||
function read_source_map(code) {
|
||||
var match = /(?:^|[^.])\/\/# sourceMappingURL=data:application\/json(;[\w=-]*)?;base64,([+/0-9A-Za-z]*=*)\s*$/.exec(code);
|
||||
if (!match) {
|
||||
console.warn("inline source map not found");
|
||||
return null;
|
||||
}
|
||||
return to_ascii(match[2]);
|
||||
}
|
||||
|
||||
function set_shorthand(name, options, keys) {
|
||||
if (options[name]) {
|
||||
keys.forEach(function(key) {
|
||||
if (options[key]) {
|
||||
if (typeof options[key] != "object") options[key] = {};
|
||||
if (!(name in options[key])) options[key][name] = options[name];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function init_cache(cache) {
|
||||
if (!cache) return;
|
||||
if (!("props" in cache)) {
|
||||
cache.props = new Map();
|
||||
} else if (!(cache.props instanceof Map)) {
|
||||
cache.props = map_from_object(cache.props);
|
||||
}
|
||||
}
|
||||
|
||||
function cache_to_json(cache) {
|
||||
return {
|
||||
props: map_to_object(cache.props)
|
||||
};
|
||||
}
|
||||
|
||||
function log_input(files, options, fs, debug_folder) {
|
||||
if (!(fs && fs.writeFileSync && fs.mkdirSync)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
fs.mkdirSync(debug_folder);
|
||||
} catch (e) {
|
||||
if (e.code !== "EEXIST") throw e;
|
||||
}
|
||||
|
||||
const log_path = `${debug_folder}/terser-debug-${(Math.random() * 9999999) | 0}.log`;
|
||||
|
||||
options = options || {};
|
||||
|
||||
const options_str = JSON.stringify(options, (_key, thing) => {
|
||||
if (typeof thing === "function") return "[Function " + thing.toString() + "]";
|
||||
if (thing instanceof RegExp) return "[RegExp " + thing.toString() + "]";
|
||||
return thing;
|
||||
}, 4);
|
||||
|
||||
const files_str = (file) => {
|
||||
if (typeof file === "object" && options.parse && options.parse.spidermonkey) {
|
||||
return JSON.stringify(file, null, 2);
|
||||
} else if (typeof file === "object") {
|
||||
return Object.keys(file)
|
||||
.map((key) => key + ": " + files_str(file[key]))
|
||||
.join("\n\n");
|
||||
} else if (typeof file === "string") {
|
||||
return "```\n" + file + "\n```";
|
||||
} else {
|
||||
return file; // What do?
|
||||
}
|
||||
};
|
||||
|
||||
fs.writeFileSync(log_path, "Options: \n" + options_str + "\n\nInput files:\n\n" + files_str(files) + "\n");
|
||||
}
|
||||
|
||||
function* minify_sync_or_async(files, options, _fs_module) {
|
||||
if (
|
||||
_fs_module
|
||||
&& typeof process === "object"
|
||||
&& process.env
|
||||
&& typeof process.env.TERSER_DEBUG_DIR === "string"
|
||||
) {
|
||||
log_input(files, options, _fs_module, process.env.TERSER_DEBUG_DIR);
|
||||
}
|
||||
|
||||
options = defaults(options, {
|
||||
compress: {},
|
||||
ecma: undefined,
|
||||
enclose: false,
|
||||
ie8: false,
|
||||
keep_classnames: undefined,
|
||||
keep_fnames: false,
|
||||
mangle: {},
|
||||
module: false,
|
||||
nameCache: null,
|
||||
output: null,
|
||||
format: null,
|
||||
parse: {},
|
||||
rename: undefined,
|
||||
safari10: false,
|
||||
sourceMap: false,
|
||||
spidermonkey: false,
|
||||
timings: false,
|
||||
toplevel: false,
|
||||
warnings: false,
|
||||
wrap: false,
|
||||
}, true);
|
||||
|
||||
var timings = options.timings && {
|
||||
start: Date.now()
|
||||
};
|
||||
if (options.keep_classnames === undefined) {
|
||||
options.keep_classnames = options.keep_fnames;
|
||||
}
|
||||
if (options.rename === undefined) {
|
||||
options.rename = options.compress && options.mangle;
|
||||
}
|
||||
if (options.output && options.format) {
|
||||
throw new Error("Please only specify either output or format option, preferrably format.");
|
||||
}
|
||||
options.format = options.format || options.output || {};
|
||||
set_shorthand("ecma", options, [ "parse", "compress", "format" ]);
|
||||
set_shorthand("ie8", options, [ "compress", "mangle", "format" ]);
|
||||
set_shorthand("keep_classnames", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("module", options, [ "parse", "compress", "mangle" ]);
|
||||
set_shorthand("safari10", options, [ "mangle", "format" ]);
|
||||
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("warnings", options, [ "compress" ]); // legacy
|
||||
var quoted_props;
|
||||
if (options.mangle) {
|
||||
options.mangle = defaults(options.mangle, {
|
||||
cache: options.nameCache && (options.nameCache.vars || {}),
|
||||
eval: false,
|
||||
ie8: false,
|
||||
keep_classnames: false,
|
||||
keep_fnames: false,
|
||||
module: false,
|
||||
nth_identifier: base54,
|
||||
properties: false,
|
||||
reserved: [],
|
||||
safari10: false,
|
||||
toplevel: false,
|
||||
}, true);
|
||||
if (options.mangle.properties) {
|
||||
if (typeof options.mangle.properties != "object") {
|
||||
options.mangle.properties = {};
|
||||
}
|
||||
if (options.mangle.properties.keep_quoted) {
|
||||
quoted_props = options.mangle.properties.reserved;
|
||||
if (!Array.isArray(quoted_props)) quoted_props = [];
|
||||
options.mangle.properties.reserved = quoted_props;
|
||||
}
|
||||
if (options.nameCache && !("cache" in options.mangle.properties)) {
|
||||
options.mangle.properties.cache = options.nameCache.props || {};
|
||||
}
|
||||
}
|
||||
init_cache(options.mangle.cache);
|
||||
init_cache(options.mangle.properties.cache);
|
||||
}
|
||||
if (options.sourceMap) {
|
||||
options.sourceMap = defaults(options.sourceMap, {
|
||||
asObject: false,
|
||||
content: null,
|
||||
filename: null,
|
||||
includeSources: false,
|
||||
root: null,
|
||||
url: null,
|
||||
}, true);
|
||||
}
|
||||
|
||||
// -- Parse phase --
|
||||
if (timings) timings.parse = Date.now();
|
||||
var toplevel;
|
||||
if (files instanceof AST_Toplevel) {
|
||||
toplevel = files;
|
||||
} else {
|
||||
if (typeof files == "string" || (options.parse.spidermonkey && !Array.isArray(files))) {
|
||||
files = [ files ];
|
||||
}
|
||||
options.parse = options.parse || {};
|
||||
options.parse.toplevel = null;
|
||||
|
||||
if (options.parse.spidermonkey) {
|
||||
options.parse.toplevel = AST_Node.from_mozilla_ast(Object.keys(files).reduce(function(toplevel, name) {
|
||||
if (!toplevel) return files[name];
|
||||
toplevel.body = toplevel.body.concat(files[name].body);
|
||||
return toplevel;
|
||||
}, null));
|
||||
} else {
|
||||
delete options.parse.spidermonkey;
|
||||
|
||||
for (var name in files) if (HOP(files, name)) {
|
||||
options.parse.filename = name;
|
||||
options.parse.toplevel = parse(files[name], options.parse);
|
||||
if (options.sourceMap && options.sourceMap.content == "inline") {
|
||||
if (Object.keys(files).length > 1)
|
||||
throw new Error("inline source map only works with singular input");
|
||||
options.sourceMap.content = read_source_map(files[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.parse.toplevel === null) {
|
||||
throw new Error("no source file given");
|
||||
}
|
||||
|
||||
toplevel = options.parse.toplevel;
|
||||
}
|
||||
if (quoted_props && options.mangle.properties.keep_quoted !== "strict") {
|
||||
reserve_quoted_keys(toplevel, quoted_props);
|
||||
}
|
||||
var annotated_props;
|
||||
if (options.mangle && options.mangle.properties) {
|
||||
annotated_props = find_annotated_props(toplevel);
|
||||
}
|
||||
if (options.wrap) {
|
||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
if (options.enclose) {
|
||||
toplevel = toplevel.wrap_enclose(options.enclose);
|
||||
}
|
||||
if (timings) timings.rename = Date.now();
|
||||
// disable rename on harmony due to expand_names bug in for-of loops
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2794
|
||||
if (0 && options.rename) {
|
||||
toplevel.figure_out_scope(options.mangle);
|
||||
toplevel.expand_names(options.mangle);
|
||||
}
|
||||
|
||||
// -- Compress phase --
|
||||
if (timings) timings.compress = Date.now();
|
||||
if (options.compress) {
|
||||
toplevel = new Compressor(options.compress, {
|
||||
mangle_options: options.mangle
|
||||
}).compress(toplevel);
|
||||
}
|
||||
|
||||
// -- Mangle phase --
|
||||
if (timings) timings.scope = Date.now();
|
||||
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
||||
if (timings) timings.mangle = Date.now();
|
||||
if (options.mangle) {
|
||||
toplevel.compute_char_frequency(options.mangle);
|
||||
toplevel.mangle_names(options.mangle);
|
||||
toplevel = mangle_private_properties(toplevel, options.mangle);
|
||||
}
|
||||
if (timings) timings.properties = Date.now();
|
||||
if (options.mangle && options.mangle.properties) {
|
||||
toplevel = mangle_properties(toplevel, options.mangle.properties, annotated_props);
|
||||
}
|
||||
|
||||
// Format phase
|
||||
if (timings) timings.format = Date.now();
|
||||
var result = {};
|
||||
if (options.format.ast) {
|
||||
result.ast = toplevel;
|
||||
}
|
||||
if (options.format.spidermonkey) {
|
||||
result.ast = toplevel.to_mozilla_ast();
|
||||
}
|
||||
let format_options;
|
||||
if (!HOP(options.format, "code") || options.format.code) {
|
||||
// Make a shallow copy so that we can modify without mutating the user's input.
|
||||
format_options = {...options.format};
|
||||
if (!format_options.ast) {
|
||||
// Destroy stuff to save RAM. (unless the deprecated `ast` option is on)
|
||||
format_options._destroy_ast = true;
|
||||
|
||||
walk(toplevel, node => {
|
||||
if (node instanceof AST_Scope) {
|
||||
node.variables = undefined;
|
||||
node.enclosed = undefined;
|
||||
node.parent_scope = undefined;
|
||||
}
|
||||
if (node.block_scope) {
|
||||
node.block_scope.variables = undefined;
|
||||
node.block_scope.enclosed = undefined;
|
||||
node.block_scope.parent_scope = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (options.sourceMap) {
|
||||
if (options.sourceMap.includeSources && files instanceof AST_Toplevel) {
|
||||
throw new Error("original source content unavailable");
|
||||
}
|
||||
format_options.source_map = yield* SourceMap({
|
||||
file: options.sourceMap.filename,
|
||||
orig: options.sourceMap.content,
|
||||
root: options.sourceMap.root,
|
||||
files: options.sourceMap.includeSources ? files : null,
|
||||
});
|
||||
}
|
||||
delete format_options.ast;
|
||||
delete format_options.code;
|
||||
delete format_options.spidermonkey;
|
||||
var stream = OutputStream(format_options);
|
||||
toplevel.print(stream);
|
||||
result.code = stream.get();
|
||||
if (options.sourceMap) {
|
||||
Object.defineProperty(result, "map", {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get() {
|
||||
const map = format_options.source_map.getEncoded();
|
||||
return (result.map = options.sourceMap.asObject ? map : JSON.stringify(map));
|
||||
},
|
||||
set(value) {
|
||||
Object.defineProperty(result, "map", {
|
||||
value,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
result.decoded_map = format_options.source_map.getDecoded();
|
||||
if (options.sourceMap.url == "inline") {
|
||||
var sourceMap = typeof result.map === "object" ? JSON.stringify(result.map) : result.map;
|
||||
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(sourceMap);
|
||||
} else if (options.sourceMap.url) {
|
||||
result.code += "\n//# sourceMappingURL=" + options.sourceMap.url;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.nameCache && options.mangle) {
|
||||
if (options.mangle.cache) options.nameCache.vars = cache_to_json(options.mangle.cache);
|
||||
if (options.mangle.properties && options.mangle.properties.cache) {
|
||||
options.nameCache.props = cache_to_json(options.mangle.properties.cache);
|
||||
}
|
||||
}
|
||||
if (format_options && format_options.source_map) {
|
||||
format_options.source_map.destroy();
|
||||
}
|
||||
if (timings) {
|
||||
timings.end = Date.now();
|
||||
result.timings = {
|
||||
parse: 1e-3 * (timings.rename - timings.parse),
|
||||
rename: 1e-3 * (timings.compress - timings.rename),
|
||||
compress: 1e-3 * (timings.scope - timings.compress),
|
||||
scope: 1e-3 * (timings.mangle - timings.scope),
|
||||
mangle: 1e-3 * (timings.properties - timings.mangle),
|
||||
properties: 1e-3 * (timings.format - timings.properties),
|
||||
format: 1e-3 * (timings.end - timings.format),
|
||||
total: 1e-3 * (timings.end - timings.start)
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async function minify(files, options, _fs_module) {
|
||||
const gen = minify_sync_or_async(files, options, _fs_module);
|
||||
|
||||
let yielded;
|
||||
let val;
|
||||
do {
|
||||
val = gen.next(await yielded);
|
||||
yielded = val.value;
|
||||
} while (!val.done);
|
||||
|
||||
return val.value;
|
||||
}
|
||||
|
||||
function minify_sync(files, options, _fs_module) {
|
||||
const gen = minify_sync_or_async(files, options, _fs_module);
|
||||
|
||||
let yielded;
|
||||
let val;
|
||||
do {
|
||||
if (yielded && typeof yielded.then === "function") {
|
||||
throw new Error("minify_sync cannot be used with the legacy source-map module");
|
||||
}
|
||||
val = gen.next(yielded);
|
||||
yielded = val.value;
|
||||
} while (!val.done);
|
||||
|
||||
return val.value;
|
||||
}
|
||||
|
||||
export {
|
||||
minify,
|
||||
minify_sync,
|
||||
to_ascii,
|
||||
};
|
1916
node_modules/terser/lib/mozilla-ast.js
generated
vendored
Normal file
1916
node_modules/terser/lib/mozilla-ast.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2528
node_modules/terser/lib/output.js
generated
vendored
Normal file
2528
node_modules/terser/lib/output.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3498
node_modules/terser/lib/parse.js
generated
vendored
Normal file
3498
node_modules/terser/lib/parse.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
434
node_modules/terser/lib/propmangle.js
generated
vendored
Normal file
434
node_modules/terser/lib/propmangle.js
generated
vendored
Normal file
@ -0,0 +1,434 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
"use strict";
|
||||
/* global global, self */
|
||||
|
||||
import {
|
||||
defaults,
|
||||
push_uniq,
|
||||
has_annotation,
|
||||
clear_annotation,
|
||||
} from "./utils/index.js";
|
||||
import { base54 } from "./scope.js";
|
||||
import {
|
||||
AST_Binary,
|
||||
AST_Call,
|
||||
AST_ClassPrivateProperty,
|
||||
AST_Conditional,
|
||||
AST_Dot,
|
||||
AST_DotHash,
|
||||
AST_ObjectKeyVal,
|
||||
AST_ObjectProperty,
|
||||
AST_PrivateMethod,
|
||||
AST_PrivateGetter,
|
||||
AST_PrivateSetter,
|
||||
AST_PrivateIn,
|
||||
AST_Sequence,
|
||||
AST_String,
|
||||
AST_Sub,
|
||||
TreeTransformer,
|
||||
TreeWalker,
|
||||
_KEY,
|
||||
_MANGLEPROP,
|
||||
|
||||
walk,
|
||||
} from "./ast.js";
|
||||
import { domprops } from "../tools/domprops.js";
|
||||
|
||||
function find_builtins(reserved) {
|
||||
domprops.forEach(add);
|
||||
|
||||
// Compatibility fix for some standard defined globals not defined on every js environment
|
||||
var new_globals = ["Symbol", "Map", "Promise", "Proxy", "Reflect", "Set", "WeakMap", "WeakSet"];
|
||||
var objects = {};
|
||||
var global_ref = typeof global === "object" ? global : self;
|
||||
|
||||
new_globals.forEach(function (new_global) {
|
||||
objects[new_global] = global_ref[new_global] || function() {};
|
||||
});
|
||||
|
||||
[
|
||||
"null",
|
||||
"true",
|
||||
"false",
|
||||
"NaN",
|
||||
"Infinity",
|
||||
"-Infinity",
|
||||
"undefined",
|
||||
].forEach(add);
|
||||
[ Object, Array, Function, Number,
|
||||
String, Boolean, Error, Math,
|
||||
Date, RegExp, objects.Symbol, ArrayBuffer,
|
||||
DataView, decodeURI, decodeURIComponent,
|
||||
encodeURI, encodeURIComponent, eval, EvalError,
|
||||
Float32Array, Float64Array, Int8Array, Int16Array,
|
||||
Int32Array, isFinite, isNaN, JSON, objects.Map, parseFloat,
|
||||
parseInt, objects.Promise, objects.Proxy, RangeError, ReferenceError,
|
||||
objects.Reflect, objects.Set, SyntaxError, TypeError, Uint8Array,
|
||||
Uint8ClampedArray, Uint16Array, Uint32Array, URIError,
|
||||
objects.WeakMap, objects.WeakSet
|
||||
].forEach(function(ctor) {
|
||||
Object.getOwnPropertyNames(ctor).map(add);
|
||||
if (ctor.prototype) {
|
||||
Object.getOwnPropertyNames(ctor.prototype).map(add);
|
||||
}
|
||||
});
|
||||
function add(name) {
|
||||
reserved.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
function reserve_quoted_keys(ast, reserved) {
|
||||
function add(name) {
|
||||
push_uniq(reserved, name);
|
||||
}
|
||||
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_ObjectKeyVal && node.quote) {
|
||||
add(node.key);
|
||||
} else if (node instanceof AST_ObjectProperty && node.quote) {
|
||||
add(node.key.name);
|
||||
} else if (node instanceof AST_Sub) {
|
||||
addStrings(node.property, add);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
function addStrings(node, add) {
|
||||
node.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
addStrings(node.tail_node(), add);
|
||||
} else if (node instanceof AST_String) {
|
||||
add(node.value);
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
addStrings(node.consequent, add);
|
||||
addStrings(node.alternative, add);
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
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 instanceof AST_PrivateIn
|
||||
) {
|
||||
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 find_annotated_props(ast) {
|
||||
var annotated_props = new Set();
|
||||
walk(ast, node => {
|
||||
if (
|
||||
node instanceof AST_ClassPrivateProperty
|
||||
|| node instanceof AST_PrivateMethod
|
||||
|| node instanceof AST_PrivateGetter
|
||||
|| node instanceof AST_PrivateSetter
|
||||
|| node instanceof AST_DotHash
|
||||
) {
|
||||
// handled by mangle_private_properties
|
||||
} else if (node instanceof AST_ObjectKeyVal) {
|
||||
if (typeof node.key == "string" && has_annotation(node, _MANGLEPROP)) {
|
||||
annotated_props.add(node.key);
|
||||
}
|
||||
} else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter, since KeyVal is handled above
|
||||
if (has_annotation(node, _MANGLEPROP)) {
|
||||
annotated_props.add(node.key.name);
|
||||
}
|
||||
} else if (node instanceof AST_Dot) {
|
||||
if (has_annotation(node, _MANGLEPROP)) {
|
||||
annotated_props.add(node.property);
|
||||
}
|
||||
} else if (node instanceof AST_Sub) {
|
||||
if (node.property instanceof AST_String && has_annotation(node, _MANGLEPROP)) {
|
||||
annotated_props.add(node.property.value);
|
||||
}
|
||||
}
|
||||
});
|
||||
return annotated_props;
|
||||
}
|
||||
|
||||
function mangle_properties(ast, options, annotated_props = find_annotated_props(ast)) {
|
||||
options = defaults(options, {
|
||||
builtins: false,
|
||||
cache: null,
|
||||
debug: false,
|
||||
keep_quoted: false,
|
||||
nth_identifier: base54,
|
||||
only_cache: false,
|
||||
regex: null,
|
||||
reserved: null,
|
||||
undeclared: false,
|
||||
only_annotated: false,
|
||||
}, true);
|
||||
|
||||
var nth_identifier = options.nth_identifier;
|
||||
|
||||
var reserved_option = options.reserved;
|
||||
if (!Array.isArray(reserved_option)) reserved_option = [reserved_option];
|
||||
var reserved = new Set(reserved_option);
|
||||
if (!options.builtins) find_builtins(reserved);
|
||||
|
||||
var cname = -1;
|
||||
|
||||
var cache;
|
||||
if (options.cache) {
|
||||
cache = options.cache.props;
|
||||
} else {
|
||||
cache = new Map();
|
||||
}
|
||||
|
||||
var only_annotated = options.only_annotated;
|
||||
var regex = options.regex && new RegExp(options.regex);
|
||||
|
||||
// note debug is either false (disabled), or a string of the debug suffix to use (enabled).
|
||||
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
|
||||
// the same as passing an empty string.
|
||||
var debug = options.debug !== false;
|
||||
var debug_name_suffix;
|
||||
if (debug) {
|
||||
debug_name_suffix = (options.debug === true ? "" : options.debug);
|
||||
}
|
||||
|
||||
var names_to_mangle = new Set();
|
||||
var unmangleable = new Set();
|
||||
// Track each already-mangled name to prevent nth_identifier from generating
|
||||
// the same name.
|
||||
cache.forEach((mangled_name) => unmangleable.add(mangled_name));
|
||||
|
||||
var keep_quoted = !!options.keep_quoted;
|
||||
|
||||
// step 1: find candidates to mangle
|
||||
ast.walk(new TreeWalker(function(node) {
|
||||
if (
|
||||
node instanceof AST_ClassPrivateProperty
|
||||
|| node instanceof AST_PrivateMethod
|
||||
|| node instanceof AST_PrivateGetter
|
||||
|| node instanceof AST_PrivateSetter
|
||||
|| node instanceof AST_DotHash
|
||||
) {
|
||||
// handled by mangle_private_properties
|
||||
} else if (node instanceof AST_ObjectKeyVal) {
|
||||
if (typeof node.key == "string" && (!keep_quoted || !node.quote)) {
|
||||
add(node.key);
|
||||
}
|
||||
} else if (node instanceof AST_ObjectProperty) {
|
||||
// setter or getter, since KeyVal is handled above
|
||||
if (!keep_quoted || !node.quote) {
|
||||
add(node.key.name);
|
||||
}
|
||||
} else if (node instanceof AST_Dot) {
|
||||
var declared = !!options.undeclared;
|
||||
if (!declared) {
|
||||
var root = node;
|
||||
while (root.expression) {
|
||||
root = root.expression;
|
||||
}
|
||||
declared = !(root.thedef && root.thedef.undeclared);
|
||||
}
|
||||
if (declared &&
|
||||
(!keep_quoted || !node.quote)) {
|
||||
add(node.property);
|
||||
}
|
||||
} else if (node instanceof AST_Sub) {
|
||||
if (!keep_quoted) {
|
||||
addStrings(node.property, add);
|
||||
}
|
||||
} else if (node instanceof AST_Call
|
||||
&& node.expression.print_to_string() == "Object.defineProperty") {
|
||||
addStrings(node.args[1], add);
|
||||
} else if (node instanceof AST_Binary && node.operator === "in") {
|
||||
addStrings(node.left, add);
|
||||
} else if (node instanceof AST_String && has_annotation(node, _KEY)) {
|
||||
add(node.value);
|
||||
}
|
||||
}));
|
||||
|
||||
// step 2: transform the tree, renaming properties
|
||||
return ast.transform(new TreeTransformer(function(node) {
|
||||
if (
|
||||
node instanceof AST_ClassPrivateProperty
|
||||
|| node instanceof AST_PrivateMethod
|
||||
|| node instanceof AST_PrivateGetter
|
||||
|| node instanceof AST_PrivateSetter
|
||||
|| node instanceof AST_DotHash
|
||||
) {
|
||||
// handled by mangle_private_properties
|
||||
} else if (node instanceof AST_ObjectKeyVal) {
|
||||
if (typeof node.key == "string" && (!keep_quoted || !node.quote)) {
|
||||
node.key = mangle(node.key);
|
||||
}
|
||||
} else if (node instanceof AST_ObjectProperty) {
|
||||
// setter, getter, method or class field
|
||||
if (!keep_quoted || !node.quote) {
|
||||
if (!node.computed_key()) {
|
||||
node.key.name = mangle(node.key.name);
|
||||
}
|
||||
}
|
||||
} else if (node instanceof AST_Dot) {
|
||||
if (!keep_quoted || !node.quote) {
|
||||
node.property = mangle(node.property);
|
||||
}
|
||||
} else if (!keep_quoted && node instanceof AST_Sub) {
|
||||
node.property = mangleStrings(node.property);
|
||||
} else if (node instanceof AST_Call
|
||||
&& node.expression.print_to_string() == "Object.defineProperty") {
|
||||
node.args[1] = mangleStrings(node.args[1]);
|
||||
} else if (node instanceof AST_Binary && node.operator === "in") {
|
||||
node.left = mangleStrings(node.left);
|
||||
} else if (node instanceof AST_String && has_annotation(node, _KEY)) {
|
||||
// Clear _KEY annotation to prevent double mangling
|
||||
clear_annotation(node, _KEY);
|
||||
node.value = mangle(node.value);
|
||||
}
|
||||
}));
|
||||
|
||||
// only function declarations after this line
|
||||
|
||||
function can_mangle(name) {
|
||||
if (unmangleable.has(name)) return false;
|
||||
if (reserved.has(name)) return false;
|
||||
if (options.only_cache) {
|
||||
return cache.has(name);
|
||||
}
|
||||
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function should_mangle(name) {
|
||||
if (only_annotated && !annotated_props.has(name)) return false;
|
||||
if (regex && !regex.test(name)) {
|
||||
return annotated_props.has(name);
|
||||
}
|
||||
if (reserved.has(name)) return false;
|
||||
return cache.has(name)
|
||||
|| names_to_mangle.has(name);
|
||||
}
|
||||
|
||||
function add(name) {
|
||||
if (can_mangle(name)) {
|
||||
names_to_mangle.add(name);
|
||||
}
|
||||
|
||||
if (!should_mangle(name)) {
|
||||
unmangleable.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
function mangle(name) {
|
||||
if (!should_mangle(name)) {
|
||||
return name;
|
||||
}
|
||||
|
||||
var mangled = cache.get(name);
|
||||
if (!mangled) {
|
||||
if (debug) {
|
||||
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
|
||||
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
|
||||
|
||||
if (can_mangle(debug_mangled)) {
|
||||
mangled = debug_mangled;
|
||||
}
|
||||
}
|
||||
|
||||
// either debug mode is off, or it is on and we could not use the mangled name
|
||||
if (!mangled) {
|
||||
do {
|
||||
mangled = nth_identifier.get(++cname);
|
||||
} while (!can_mangle(mangled));
|
||||
}
|
||||
|
||||
cache.set(name, mangled);
|
||||
}
|
||||
return mangled;
|
||||
}
|
||||
|
||||
function mangleStrings(node) {
|
||||
return node.transform(new TreeTransformer(function(node) {
|
||||
if (node instanceof AST_Sequence) {
|
||||
var last = node.expressions.length - 1;
|
||||
node.expressions[last] = mangleStrings(node.expressions[last]);
|
||||
} else if (node instanceof AST_String) {
|
||||
// Clear _KEY annotation to prevent double mangling
|
||||
clear_annotation(node, _KEY);
|
||||
node.value = mangle(node.value);
|
||||
} else if (node instanceof AST_Conditional) {
|
||||
node.consequent = mangleStrings(node.consequent);
|
||||
node.alternative = mangleStrings(node.alternative);
|
||||
}
|
||||
return node;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
reserve_quoted_keys,
|
||||
mangle_properties,
|
||||
mangle_private_properties,
|
||||
find_annotated_props,
|
||||
};
|
1066
node_modules/terser/lib/scope.js
generated
vendored
Normal file
1066
node_modules/terser/lib/scope.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
499
node_modules/terser/lib/size.js
generated
vendored
Normal file
499
node_modules/terser/lib/size.js
generated
vendored
Normal file
@ -0,0 +1,499 @@
|
||||
import {
|
||||
AST_Accessor,
|
||||
AST_Array,
|
||||
AST_Arrow,
|
||||
AST_Await,
|
||||
AST_BigInt,
|
||||
AST_Binary,
|
||||
AST_Block,
|
||||
AST_Break,
|
||||
AST_Call,
|
||||
AST_Case,
|
||||
AST_Class,
|
||||
AST_ClassStaticBlock,
|
||||
AST_ClassPrivateProperty,
|
||||
AST_ClassProperty,
|
||||
AST_ConciseMethod,
|
||||
AST_Conditional,
|
||||
AST_Const,
|
||||
AST_Continue,
|
||||
AST_Debugger,
|
||||
AST_Default,
|
||||
AST_Defun,
|
||||
AST_Destructuring,
|
||||
AST_Directive,
|
||||
AST_Do,
|
||||
AST_Dot,
|
||||
AST_DotHash,
|
||||
AST_EmptyStatement,
|
||||
AST_Expansion,
|
||||
AST_Export,
|
||||
AST_False,
|
||||
AST_For,
|
||||
AST_ForIn,
|
||||
AST_Function,
|
||||
AST_Hole,
|
||||
AST_If,
|
||||
AST_Import,
|
||||
AST_ImportMeta,
|
||||
AST_Infinity,
|
||||
AST_LabeledStatement,
|
||||
AST_Let,
|
||||
AST_NameMapping,
|
||||
AST_NaN,
|
||||
AST_New,
|
||||
AST_NewTarget,
|
||||
AST_Node,
|
||||
AST_Null,
|
||||
AST_Number,
|
||||
AST_Object,
|
||||
AST_ObjectKeyVal,
|
||||
AST_ObjectGetter,
|
||||
AST_ObjectSetter,
|
||||
AST_PrivateGetter,
|
||||
AST_PrivateMethod,
|
||||
AST_PrivateSetter,
|
||||
AST_PrivateIn,
|
||||
AST_RegExp,
|
||||
AST_Return,
|
||||
AST_Sequence,
|
||||
AST_String,
|
||||
AST_Sub,
|
||||
AST_Super,
|
||||
AST_Switch,
|
||||
AST_Symbol,
|
||||
AST_SymbolClassProperty,
|
||||
AST_SymbolExportForeign,
|
||||
AST_SymbolImportForeign,
|
||||
AST_SymbolRef,
|
||||
AST_SymbolDeclaration,
|
||||
AST_TemplateSegment,
|
||||
AST_TemplateString,
|
||||
AST_This,
|
||||
AST_Throw,
|
||||
AST_Toplevel,
|
||||
AST_True,
|
||||
AST_Try,
|
||||
AST_Catch,
|
||||
AST_Finally,
|
||||
AST_Unary,
|
||||
AST_Undefined,
|
||||
AST_Var,
|
||||
AST_VarDef,
|
||||
AST_While,
|
||||
AST_With,
|
||||
AST_Yield,
|
||||
walk_parent
|
||||
} from "./ast.js";
|
||||
import { first_in_statement } from "./utils/first_in_statement.js";
|
||||
|
||||
let mangle_options = undefined;
|
||||
AST_Node.prototype.size = function (compressor, stack) {
|
||||
mangle_options = compressor && compressor._mangle_options;
|
||||
|
||||
let size = 0;
|
||||
walk_parent(this, (node, info) => {
|
||||
size += node._size(info);
|
||||
|
||||
// Braceless arrow functions have fake "return" statements
|
||||
if (node instanceof AST_Arrow && node.is_braceless()) {
|
||||
size += node.body[0].value._size(info);
|
||||
return true;
|
||||
}
|
||||
}, stack || (compressor && compressor.stack));
|
||||
|
||||
// just to save a bit of memory
|
||||
mangle_options = undefined;
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
AST_Node.prototype._size = () => 0;
|
||||
|
||||
AST_Debugger.prototype._size = () => 8;
|
||||
|
||||
AST_Directive.prototype._size = function () {
|
||||
// TODO string encoding stuff
|
||||
return 2 + this.value.length;
|
||||
};
|
||||
|
||||
/** Count commas/semicolons necessary to show a list of expressions/statements */
|
||||
const list_overhead = (array) => array.length && array.length - 1;
|
||||
|
||||
AST_Block.prototype._size = function () {
|
||||
return 2 + list_overhead(this.body);
|
||||
};
|
||||
|
||||
AST_Toplevel.prototype._size = function() {
|
||||
return list_overhead(this.body);
|
||||
};
|
||||
|
||||
AST_EmptyStatement.prototype._size = () => 1;
|
||||
|
||||
AST_LabeledStatement.prototype._size = () => 2; // x:
|
||||
|
||||
AST_Do.prototype._size = () => 9;
|
||||
|
||||
AST_While.prototype._size = () => 7;
|
||||
|
||||
AST_For.prototype._size = () => 8;
|
||||
|
||||
AST_ForIn.prototype._size = () => 8;
|
||||
// AST_ForOf inherits ^
|
||||
|
||||
AST_With.prototype._size = () => 6;
|
||||
|
||||
AST_Expansion.prototype._size = () => 3;
|
||||
|
||||
const lambda_modifiers = func =>
|
||||
(func.is_generator ? 1 : 0) + (func.async ? 6 : 0);
|
||||
|
||||
AST_Accessor.prototype._size = function () {
|
||||
return lambda_modifiers(this) + 4 + list_overhead(this.argnames) + list_overhead(this.body);
|
||||
};
|
||||
|
||||
AST_Function.prototype._size = function (info) {
|
||||
const first = !!first_in_statement(info);
|
||||
return (first * 2) + lambda_modifiers(this) + 12 + list_overhead(this.argnames) + list_overhead(this.body);
|
||||
};
|
||||
|
||||
AST_Defun.prototype._size = function () {
|
||||
return lambda_modifiers(this) + 13 + list_overhead(this.argnames) + list_overhead(this.body);
|
||||
};
|
||||
|
||||
AST_Arrow.prototype._size = function () {
|
||||
let args_and_arrow = 2 + list_overhead(this.argnames);
|
||||
|
||||
if (
|
||||
!(
|
||||
this.argnames.length === 1
|
||||
&& this.argnames[0] instanceof AST_Symbol
|
||||
)
|
||||
) {
|
||||
args_and_arrow += 2; // parens around the args
|
||||
}
|
||||
|
||||
const body_overhead = this.is_braceless() ? 0 : list_overhead(this.body) + 2;
|
||||
|
||||
return lambda_modifiers(this) + args_and_arrow + body_overhead;
|
||||
};
|
||||
|
||||
AST_Destructuring.prototype._size = () => 2;
|
||||
|
||||
AST_TemplateString.prototype._size = function () {
|
||||
return 2 + (Math.floor(this.segments.length / 2) * 3); /* "${}" */
|
||||
};
|
||||
|
||||
AST_TemplateSegment.prototype._size = function () {
|
||||
return this.value.length;
|
||||
};
|
||||
|
||||
AST_Return.prototype._size = function () {
|
||||
return this.value ? 7 : 6;
|
||||
};
|
||||
|
||||
AST_Throw.prototype._size = () => 6;
|
||||
|
||||
AST_Break.prototype._size = function () {
|
||||
return this.label ? 6 : 5;
|
||||
};
|
||||
|
||||
AST_Continue.prototype._size = function () {
|
||||
return this.label ? 9 : 8;
|
||||
};
|
||||
|
||||
AST_If.prototype._size = () => 4;
|
||||
|
||||
AST_Switch.prototype._size = function () {
|
||||
return 8 + list_overhead(this.body);
|
||||
};
|
||||
|
||||
AST_Case.prototype._size = function () {
|
||||
return 5 + list_overhead(this.body);
|
||||
};
|
||||
|
||||
AST_Default.prototype._size = function () {
|
||||
return 8 + list_overhead(this.body);
|
||||
};
|
||||
|
||||
AST_Try.prototype._size = () => 3;
|
||||
|
||||
AST_Catch.prototype._size = function () {
|
||||
let size = 7 + list_overhead(this.body);
|
||||
if (this.argname) {
|
||||
size += 2;
|
||||
}
|
||||
return size;
|
||||
};
|
||||
|
||||
AST_Finally.prototype._size = function () {
|
||||
return 7 + list_overhead(this.body);
|
||||
};
|
||||
|
||||
AST_Var.prototype._size = function () {
|
||||
return 4 + list_overhead(this.definitions);
|
||||
};
|
||||
|
||||
AST_Let.prototype._size = function () {
|
||||
return 4 + list_overhead(this.definitions);
|
||||
};
|
||||
|
||||
AST_Const.prototype._size = function () {
|
||||
return 6 + list_overhead(this.definitions);
|
||||
};
|
||||
|
||||
AST_VarDef.prototype._size = function () {
|
||||
return this.value ? 1 : 0;
|
||||
};
|
||||
|
||||
AST_NameMapping.prototype._size = function () {
|
||||
// foreign name isn't mangled
|
||||
return this.name ? 4 : 0;
|
||||
};
|
||||
|
||||
AST_Import.prototype._size = function () {
|
||||
// import
|
||||
let size = 6;
|
||||
|
||||
if (this.imported_name) size += 1;
|
||||
|
||||
// from
|
||||
if (this.imported_name || this.imported_names) size += 5;
|
||||
|
||||
// braces, and the commas
|
||||
if (this.imported_names) {
|
||||
size += 2 + list_overhead(this.imported_names);
|
||||
}
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
AST_ImportMeta.prototype._size = () => 11;
|
||||
|
||||
AST_Export.prototype._size = function () {
|
||||
let size = 7 + (this.is_default ? 8 : 0);
|
||||
|
||||
if (this.exported_value) {
|
||||
size += this.exported_value._size();
|
||||
}
|
||||
|
||||
if (this.exported_names) {
|
||||
// Braces and commas
|
||||
size += 2 + list_overhead(this.exported_names);
|
||||
}
|
||||
|
||||
if (this.module_name) {
|
||||
// "from "
|
||||
size += 5;
|
||||
}
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
AST_Call.prototype._size = function () {
|
||||
if (this.optional) {
|
||||
return 4 + list_overhead(this.args);
|
||||
}
|
||||
return 2 + list_overhead(this.args);
|
||||
};
|
||||
|
||||
AST_New.prototype._size = function () {
|
||||
return 6 + list_overhead(this.args);
|
||||
};
|
||||
|
||||
AST_Sequence.prototype._size = function () {
|
||||
return list_overhead(this.expressions);
|
||||
};
|
||||
|
||||
AST_Dot.prototype._size = function () {
|
||||
if (this.optional) {
|
||||
return this.property.length + 2;
|
||||
}
|
||||
return this.property.length + 1;
|
||||
};
|
||||
|
||||
AST_DotHash.prototype._size = function () {
|
||||
if (this.optional) {
|
||||
return this.property.length + 3;
|
||||
}
|
||||
return this.property.length + 2;
|
||||
};
|
||||
|
||||
AST_Sub.prototype._size = function () {
|
||||
return this.optional ? 4 : 2;
|
||||
};
|
||||
|
||||
AST_Unary.prototype._size = function () {
|
||||
if (this.operator === "typeof") return 7;
|
||||
if (this.operator === "void") return 5;
|
||||
return this.operator.length;
|
||||
};
|
||||
|
||||
AST_Binary.prototype._size = function (info) {
|
||||
if (this.operator === "in") return 4;
|
||||
|
||||
let size = this.operator.length;
|
||||
|
||||
if (
|
||||
(this.operator === "+" || this.operator === "-")
|
||||
&& this.right instanceof AST_Unary && this.right.operator === this.operator
|
||||
) {
|
||||
// 1+ +a > needs space between the +
|
||||
size += 1;
|
||||
}
|
||||
|
||||
if (this.needs_parens(info)) {
|
||||
size += 2;
|
||||
}
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
AST_Conditional.prototype._size = () => 3;
|
||||
|
||||
AST_Array.prototype._size = function () {
|
||||
return 2 + list_overhead(this.elements);
|
||||
};
|
||||
|
||||
AST_Object.prototype._size = function (info) {
|
||||
let base = 2;
|
||||
if (first_in_statement(info)) {
|
||||
base += 2; // parens
|
||||
}
|
||||
return base + list_overhead(this.properties);
|
||||
};
|
||||
|
||||
/*#__INLINE__*/
|
||||
const key_size = key =>
|
||||
typeof key === "string" ? key.length : 0;
|
||||
|
||||
AST_ObjectKeyVal.prototype._size = function () {
|
||||
return key_size(this.key) + 1;
|
||||
};
|
||||
|
||||
/*#__INLINE__*/
|
||||
const static_size = is_static => is_static ? 7 : 0;
|
||||
|
||||
AST_ObjectGetter.prototype._size = function () {
|
||||
return 5 + static_size(this.static) + key_size(this.key);
|
||||
};
|
||||
|
||||
AST_ObjectSetter.prototype._size = function () {
|
||||
return 5 + static_size(this.static) + key_size(this.key);
|
||||
};
|
||||
|
||||
AST_ConciseMethod.prototype._size = function () {
|
||||
return static_size(this.static) + key_size(this.key) + lambda_modifiers(this);
|
||||
};
|
||||
|
||||
AST_PrivateMethod.prototype._size = function () {
|
||||
return AST_ConciseMethod.prototype._size.call(this) + 1;
|
||||
};
|
||||
|
||||
AST_PrivateGetter.prototype._size = function () {
|
||||
return AST_ConciseMethod.prototype._size.call(this) + 4;
|
||||
};
|
||||
|
||||
AST_PrivateSetter.prototype._size = function () {
|
||||
return AST_ConciseMethod.prototype._size.call(this) + 4;
|
||||
};
|
||||
|
||||
AST_PrivateIn.prototype._size = function () {
|
||||
return 5; // "#", and " in "
|
||||
};
|
||||
|
||||
AST_Class.prototype._size = function () {
|
||||
return (
|
||||
(this.name ? 8 : 7)
|
||||
+ (this.extends ? 8 : 0)
|
||||
);
|
||||
};
|
||||
|
||||
AST_ClassStaticBlock.prototype._size = function () {
|
||||
// "static{}" + semicolons
|
||||
return 8 + list_overhead(this.body);
|
||||
};
|
||||
|
||||
AST_ClassProperty.prototype._size = function () {
|
||||
return (
|
||||
static_size(this.static)
|
||||
+ (typeof this.key === "string" ? this.key.length + 2 : 0)
|
||||
+ (this.value ? 1 : 0)
|
||||
);
|
||||
};
|
||||
|
||||
AST_ClassPrivateProperty.prototype._size = function () {
|
||||
return AST_ClassProperty.prototype._size.call(this) + 1;
|
||||
};
|
||||
|
||||
AST_Symbol.prototype._size = function () {
|
||||
if (!(mangle_options && this.thedef && !this.thedef.unmangleable(mangle_options))) {
|
||||
return this.name.length;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO take propmangle into account
|
||||
AST_SymbolClassProperty.prototype._size = function () {
|
||||
return this.name.length;
|
||||
};
|
||||
|
||||
AST_SymbolRef.prototype._size = AST_SymbolDeclaration.prototype._size = function () {
|
||||
if (this.name === "arguments") return 9;
|
||||
|
||||
return AST_Symbol.prototype._size.call(this);
|
||||
};
|
||||
|
||||
AST_NewTarget.prototype._size = () => 10;
|
||||
|
||||
AST_SymbolImportForeign.prototype._size = function () {
|
||||
return this.name.length;
|
||||
};
|
||||
|
||||
AST_SymbolExportForeign.prototype._size = function () {
|
||||
return this.name.length;
|
||||
};
|
||||
|
||||
AST_This.prototype._size = () => 4;
|
||||
|
||||
AST_Super.prototype._size = () => 5;
|
||||
|
||||
AST_String.prototype._size = function () {
|
||||
return this.value.length + 2;
|
||||
};
|
||||
|
||||
AST_Number.prototype._size = function () {
|
||||
const { value } = this;
|
||||
if (value === 0) return 1;
|
||||
if (value > 0 && Math.floor(value) === value) {
|
||||
return Math.floor(Math.log10(value) + 1);
|
||||
}
|
||||
return value.toString().length;
|
||||
};
|
||||
|
||||
AST_BigInt.prototype._size = function () {
|
||||
return this.value.length;
|
||||
};
|
||||
|
||||
AST_RegExp.prototype._size = function () {
|
||||
return this.value.toString().length;
|
||||
};
|
||||
|
||||
AST_Null.prototype._size = () => 4;
|
||||
|
||||
AST_NaN.prototype._size = () => 3;
|
||||
|
||||
AST_Undefined.prototype._size = () => 6; // "void 0"
|
||||
|
||||
AST_Hole.prototype._size = () => 0; // comma is taken into account by list_overhead()
|
||||
|
||||
AST_Infinity.prototype._size = () => 8;
|
||||
|
||||
AST_True.prototype._size = () => 4;
|
||||
|
||||
AST_False.prototype._size = () => 5;
|
||||
|
||||
AST_Await.prototype._size = () => 6;
|
||||
|
||||
AST_Yield.prototype._size = () => 6;
|
148
node_modules/terser/lib/sourcemap.js
generated
vendored
Normal file
148
node_modules/terser/lib/sourcemap.js
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
"use strict";
|
||||
|
||||
import {SourceMapConsumer, SourceMapGenerator} from "@jridgewell/source-map";
|
||||
import {defaults, HOP} from "./utils/index.js";
|
||||
|
||||
// a small wrapper around source-map and @jridgewell/source-map
|
||||
function* SourceMap(options) {
|
||||
options = defaults(options, {
|
||||
file : null,
|
||||
root : null,
|
||||
orig : null,
|
||||
files: {},
|
||||
});
|
||||
|
||||
var orig_map;
|
||||
var generator = new SourceMapGenerator({
|
||||
file : options.file,
|
||||
sourceRoot : options.root
|
||||
});
|
||||
|
||||
let sourcesContent = {__proto__: null};
|
||||
let files = options.files;
|
||||
for (var name in files) if (HOP(files, name)) {
|
||||
sourcesContent[name] = files[name];
|
||||
}
|
||||
if (options.orig) {
|
||||
// We support both @jridgewell/source-map (which has a sync
|
||||
// SourceMapConsumer) and source-map (which has an async
|
||||
// SourceMapConsumer).
|
||||
orig_map = yield new SourceMapConsumer(options.orig);
|
||||
if (orig_map.sourcesContent) {
|
||||
orig_map.sources.forEach(function(source, i) {
|
||||
var content = orig_map.sourcesContent[i];
|
||||
if (content) {
|
||||
sourcesContent[source] = content;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
|
||||
let generatedPos = { line: gen_line, column: gen_col };
|
||||
|
||||
if (orig_map) {
|
||||
var info = orig_map.originalPositionFor({
|
||||
line: orig_line,
|
||||
column: orig_col
|
||||
});
|
||||
if (info.source === null) {
|
||||
generator.addMapping({
|
||||
generated: generatedPos,
|
||||
original: null,
|
||||
source: null,
|
||||
name: null
|
||||
});
|
||||
return;
|
||||
}
|
||||
source = info.source;
|
||||
orig_line = info.line;
|
||||
orig_col = info.column;
|
||||
name = info.name || name;
|
||||
}
|
||||
generator.addMapping({
|
||||
generated : generatedPos,
|
||||
original : { line: orig_line, column: orig_col },
|
||||
source : source,
|
||||
name : name
|
||||
});
|
||||
generator.setSourceContent(source, sourcesContent[source]);
|
||||
}
|
||||
|
||||
function clean(map) {
|
||||
const allNull = map.sourcesContent && map.sourcesContent.every(c => c == null);
|
||||
if (allNull) delete map.sourcesContent;
|
||||
if (map.file === undefined) delete map.file;
|
||||
if (map.sourceRoot === undefined) delete map.sourceRoot;
|
||||
return map;
|
||||
}
|
||||
|
||||
function getDecoded() {
|
||||
if (!generator.toDecodedMap) return null;
|
||||
return clean(generator.toDecodedMap());
|
||||
}
|
||||
|
||||
function getEncoded() {
|
||||
return clean(generator.toJSON());
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
// @jridgewell/source-map's SourceMapConsumer does not need to be
|
||||
// manually freed.
|
||||
if (orig_map && orig_map.destroy) orig_map.destroy();
|
||||
}
|
||||
|
||||
return {
|
||||
add,
|
||||
getDecoded,
|
||||
getEncoded,
|
||||
destroy,
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
SourceMap,
|
||||
};
|
323
node_modules/terser/lib/transform.js
generated
vendored
Normal file
323
node_modules/terser/lib/transform.js
generated
vendored
Normal file
@ -0,0 +1,323 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
"use strict";
|
||||
|
||||
import {
|
||||
AST_Array,
|
||||
AST_Await,
|
||||
AST_Binary,
|
||||
AST_PrivateIn,
|
||||
AST_Block,
|
||||
AST_Call,
|
||||
AST_Case,
|
||||
AST_Catch,
|
||||
AST_Chain,
|
||||
AST_Class,
|
||||
AST_ClassStaticBlock,
|
||||
AST_Conditional,
|
||||
AST_Definitions,
|
||||
AST_Destructuring,
|
||||
AST_Do,
|
||||
AST_Exit,
|
||||
AST_Expansion,
|
||||
AST_Export,
|
||||
AST_For,
|
||||
AST_ForIn,
|
||||
AST_If,
|
||||
AST_Import,
|
||||
AST_LabeledStatement,
|
||||
AST_Lambda,
|
||||
AST_LoopControl,
|
||||
AST_NameMapping,
|
||||
AST_Node,
|
||||
AST_Number,
|
||||
AST_Object,
|
||||
AST_ObjectProperty,
|
||||
AST_PrefixedTemplateString,
|
||||
AST_PropAccess,
|
||||
AST_Sequence,
|
||||
AST_SimpleStatement,
|
||||
AST_Sub,
|
||||
AST_Switch,
|
||||
AST_TemplateString,
|
||||
AST_Try,
|
||||
AST_Unary,
|
||||
AST_VarDef,
|
||||
AST_While,
|
||||
AST_With,
|
||||
AST_Yield,
|
||||
} from "./ast.js";
|
||||
import {
|
||||
MAP as do_list,
|
||||
noop,
|
||||
} from "./utils/index.js";
|
||||
|
||||
function def_transform(node, descend) {
|
||||
node.DEFMETHOD("transform", function(tw, in_list) {
|
||||
let transformed = undefined;
|
||||
tw.push(this);
|
||||
if (tw.before) transformed = tw.before(this, descend, in_list);
|
||||
if (transformed === undefined) {
|
||||
transformed = this;
|
||||
descend(transformed, tw);
|
||||
if (tw.after) {
|
||||
const after_ret = tw.after(transformed, in_list);
|
||||
if (after_ret !== undefined) transformed = after_ret;
|
||||
}
|
||||
}
|
||||
tw.pop();
|
||||
return transformed;
|
||||
});
|
||||
}
|
||||
|
||||
def_transform(AST_Node, noop);
|
||||
|
||||
def_transform(AST_LabeledStatement, function(self, tw) {
|
||||
self.label = self.label.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_SimpleStatement, function(self, tw) {
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Block, function(self, tw) {
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Do, function(self, tw) {
|
||||
self.body = self.body.transform(tw);
|
||||
self.condition = self.condition.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_While, function(self, tw) {
|
||||
self.condition = self.condition.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_For, function(self, tw) {
|
||||
if (self.init) self.init = self.init.transform(tw);
|
||||
if (self.condition) self.condition = self.condition.transform(tw);
|
||||
if (self.step) self.step = self.step.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_ForIn, function(self, tw) {
|
||||
self.init = self.init.transform(tw);
|
||||
self.object = self.object.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_With, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Exit, function(self, tw) {
|
||||
if (self.value) self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_LoopControl, function(self, tw) {
|
||||
if (self.label) self.label = self.label.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_If, function(self, tw) {
|
||||
self.condition = self.condition.transform(tw);
|
||||
self.body = self.body.transform(tw);
|
||||
if (self.alternative) self.alternative = self.alternative.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Switch, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Case, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Try, function(self, tw) {
|
||||
self.body = self.body.transform(tw);
|
||||
if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
|
||||
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Catch, function(self, tw) {
|
||||
if (self.argname) self.argname = self.argname.transform(tw);
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Definitions, function(self, tw) {
|
||||
self.definitions = do_list(self.definitions, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_VarDef, function(self, tw) {
|
||||
self.name = self.name.transform(tw);
|
||||
if (self.value) self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Destructuring, function(self, tw) {
|
||||
self.names = do_list(self.names, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Lambda, function(self, tw) {
|
||||
if (self.name) self.name = self.name.transform(tw);
|
||||
self.argnames = do_list(self.argnames, tw, /* allow_splicing */ false);
|
||||
if (self.body instanceof AST_Node) {
|
||||
self.body = self.body.transform(tw);
|
||||
} else {
|
||||
self.body = do_list(self.body, tw);
|
||||
}
|
||||
});
|
||||
|
||||
def_transform(AST_Call, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.args = do_list(self.args, tw, /* allow_splicing */ false);
|
||||
});
|
||||
|
||||
def_transform(AST_Sequence, function(self, tw) {
|
||||
const result = do_list(self.expressions, tw);
|
||||
self.expressions = result.length
|
||||
? result
|
||||
: [new AST_Number({ value: 0 })];
|
||||
});
|
||||
|
||||
def_transform(AST_PropAccess, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Sub, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
self.property = self.property.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Chain, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Yield, function(self, tw) {
|
||||
if (self.expression) self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Await, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Unary, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Binary, function(self, tw) {
|
||||
self.left = self.left.transform(tw);
|
||||
self.right = self.right.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_PrivateIn, function(self, tw) {
|
||||
self.key = self.key.transform(tw);
|
||||
self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Conditional, function(self, tw) {
|
||||
self.condition = self.condition.transform(tw);
|
||||
self.consequent = self.consequent.transform(tw);
|
||||
self.alternative = self.alternative.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Array, function(self, tw) {
|
||||
self.elements = do_list(self.elements, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Object, function(self, tw) {
|
||||
self.properties = do_list(self.properties, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_ObjectProperty, function(self, tw) {
|
||||
if (self.key instanceof AST_Node) {
|
||||
self.key = self.key.transform(tw);
|
||||
}
|
||||
if (self.value) self.value = self.value.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Class, function(self, tw) {
|
||||
if (self.name) self.name = self.name.transform(tw);
|
||||
if (self.extends) self.extends = self.extends.transform(tw);
|
||||
self.properties = do_list(self.properties, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_ClassStaticBlock, function(self, tw) {
|
||||
self.body = do_list(self.body, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Expansion, function(self, tw) {
|
||||
self.expression = self.expression.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_NameMapping, function(self, tw) {
|
||||
self.foreign_name = self.foreign_name.transform(tw);
|
||||
self.name = self.name.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Import, function(self, tw) {
|
||||
if (self.imported_name) self.imported_name = self.imported_name.transform(tw);
|
||||
if (self.imported_names) do_list(self.imported_names, tw);
|
||||
self.module_name = self.module_name.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_Export, function(self, tw) {
|
||||
if (self.exported_definition) self.exported_definition = self.exported_definition.transform(tw);
|
||||
if (self.exported_value) self.exported_value = self.exported_value.transform(tw);
|
||||
if (self.exported_names) do_list(self.exported_names, tw);
|
||||
if (self.module_name) self.module_name = self.module_name.transform(tw);
|
||||
});
|
||||
|
||||
def_transform(AST_TemplateString, function(self, tw) {
|
||||
self.segments = do_list(self.segments, tw);
|
||||
});
|
||||
|
||||
def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
||||
self.prefix = self.prefix.transform(tw);
|
||||
self.template_string = self.template_string.transform(tw);
|
||||
});
|
||||
|
53
node_modules/terser/lib/utils/first_in_statement.js
generated
vendored
Normal file
53
node_modules/terser/lib/utils/first_in_statement.js
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
import {
|
||||
AST_Binary,
|
||||
AST_Conditional,
|
||||
AST_Chain,
|
||||
AST_Dot,
|
||||
AST_Object,
|
||||
AST_Sequence,
|
||||
AST_Statement,
|
||||
AST_Sub,
|
||||
AST_UnaryPostfix,
|
||||
AST_PrefixedTemplateString
|
||||
} from "../ast.js";
|
||||
|
||||
// return true if the node at the top of the stack (that means the
|
||||
// innermost node in the current output) is lexically the first in
|
||||
// a statement.
|
||||
function first_in_statement(stack) {
|
||||
let node = stack.parent(-1);
|
||||
for (let i = 0, p; p = stack.parent(i); i++) {
|
||||
if (p instanceof AST_Statement && p.body === node)
|
||||
return true;
|
||||
if ((p instanceof AST_Sequence && p.expressions[0] === node) ||
|
||||
(p.TYPE === "Call" && p.expression === node) ||
|
||||
(p instanceof AST_PrefixedTemplateString && p.prefix === node) ||
|
||||
(p instanceof AST_Dot && p.expression === node) ||
|
||||
(p instanceof AST_Sub && p.expression === node) ||
|
||||
(p instanceof AST_Chain && p.expression === node) ||
|
||||
(p instanceof AST_Conditional && p.condition === node) ||
|
||||
(p instanceof AST_Binary && p.left === node) ||
|
||||
(p instanceof AST_UnaryPostfix && p.expression === node)
|
||||
) {
|
||||
node = p;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether the leftmost item in the expression is an object
|
||||
function left_is_object(node) {
|
||||
if (node instanceof AST_Object) return true;
|
||||
if (node instanceof AST_Sequence) return left_is_object(node.expressions[0]);
|
||||
if (node.TYPE === "Call") return left_is_object(node.expression);
|
||||
if (node instanceof AST_PrefixedTemplateString) return left_is_object(node.prefix);
|
||||
if (node instanceof AST_Dot || node instanceof AST_Sub) return left_is_object(node.expression);
|
||||
if (node instanceof AST_Chain) return left_is_object(node.expression);
|
||||
if (node instanceof AST_Conditional) return left_is_object(node.condition);
|
||||
if (node instanceof AST_Binary) return left_is_object(node.left);
|
||||
if (node instanceof AST_UnaryPostfix) return left_is_object(node.expression);
|
||||
return false;
|
||||
}
|
||||
|
||||
export { first_in_statement, left_is_object };
|
295
node_modules/terser/lib/utils/index.js
generated
vendored
Normal file
295
node_modules/terser/lib/utils/index.js
generated
vendored
Normal file
@ -0,0 +1,295 @@
|
||||
/***********************************************************************
|
||||
|
||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
||||
https://github.com/mishoo/UglifyJS2
|
||||
|
||||
-------------------------------- (C) ---------------------------------
|
||||
|
||||
Author: Mihai Bazon
|
||||
<mihai.bazon@gmail.com>
|
||||
http://mihai.bazon.net/blog
|
||||
|
||||
Distributed under the BSD license:
|
||||
|
||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
"use strict";
|
||||
|
||||
import { AST_Node } from "../ast.js";
|
||||
|
||||
function characters(str) {
|
||||
return str.split("");
|
||||
}
|
||||
|
||||
function member(name, array) {
|
||||
return array.includes(name);
|
||||
}
|
||||
|
||||
class DefaultsError extends Error {
|
||||
constructor(msg, defs) {
|
||||
super();
|
||||
|
||||
this.name = "DefaultsError";
|
||||
this.message = msg;
|
||||
this.defs = defs;
|
||||
}
|
||||
}
|
||||
|
||||
function defaults(args, defs, croak) {
|
||||
if (args === true) {
|
||||
args = {};
|
||||
} else if (args != null && typeof args === "object") {
|
||||
args = {...args};
|
||||
}
|
||||
|
||||
const ret = args || {};
|
||||
|
||||
if (croak) for (const i in ret) if (HOP(ret, i) && !HOP(defs, i)) {
|
||||
throw new DefaultsError("`" + i + "` is not a supported option", defs);
|
||||
}
|
||||
|
||||
for (const i in defs) if (HOP(defs, i)) {
|
||||
if (!args || !HOP(args, i)) {
|
||||
ret[i] = defs[i];
|
||||
} else if (i === "ecma") {
|
||||
let ecma = args[i] | 0;
|
||||
if (ecma > 5 && ecma < 2015) ecma += 2009;
|
||||
ret[i] = ecma;
|
||||
} else {
|
||||
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
function return_false() { return false; }
|
||||
function return_true() { return true; }
|
||||
function return_this() { return this; }
|
||||
function return_null() { return null; }
|
||||
|
||||
var MAP = (function() {
|
||||
function MAP(a, tw, allow_splicing = true) {
|
||||
const new_a = [];
|
||||
|
||||
for (let i = 0; i < a.length; ++i) {
|
||||
let item = a[i];
|
||||
let ret = item.transform(tw, allow_splicing);
|
||||
|
||||
if (ret instanceof AST_Node) {
|
||||
new_a.push(ret);
|
||||
} else if (ret instanceof Splice) {
|
||||
new_a.push(...ret.v);
|
||||
}
|
||||
}
|
||||
|
||||
return new_a;
|
||||
}
|
||||
|
||||
MAP.splice = function(val) { return new Splice(val); };
|
||||
MAP.skip = {};
|
||||
function Splice(val) { this.v = val; }
|
||||
return MAP;
|
||||
})();
|
||||
|
||||
function make_node(ctor, orig, props) {
|
||||
if (!props) props = {};
|
||||
if (orig) {
|
||||
if (!props.start) props.start = orig.start;
|
||||
if (!props.end) props.end = orig.end;
|
||||
}
|
||||
return new ctor(props);
|
||||
}
|
||||
|
||||
function push_uniq(array, el) {
|
||||
if (!array.includes(el))
|
||||
array.push(el);
|
||||
}
|
||||
|
||||
function string_template(text, props) {
|
||||
return text.replace(/{(.+?)}/g, function(str, p) {
|
||||
return props && props[p];
|
||||
});
|
||||
}
|
||||
|
||||
function remove(array, el) {
|
||||
for (var i = array.length; --i >= 0;) {
|
||||
if (array[i] === el) array.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function mergeSort(array, cmp) {
|
||||
if (array.length < 2) return array.slice();
|
||||
function merge(a, b) {
|
||||
var r = [], ai = 0, bi = 0, i = 0;
|
||||
while (ai < a.length && bi < b.length) {
|
||||
cmp(a[ai], b[bi]) <= 0
|
||||
? r[i++] = a[ai++]
|
||||
: r[i++] = b[bi++];
|
||||
}
|
||||
if (ai < a.length) r.push.apply(r, a.slice(ai));
|
||||
if (bi < b.length) r.push.apply(r, b.slice(bi));
|
||||
return r;
|
||||
}
|
||||
function _ms(a) {
|
||||
if (a.length <= 1)
|
||||
return a;
|
||||
var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
|
||||
left = _ms(left);
|
||||
right = _ms(right);
|
||||
return merge(left, right);
|
||||
}
|
||||
return _ms(array);
|
||||
}
|
||||
|
||||
function makePredicate(words) {
|
||||
if (!Array.isArray(words)) words = words.split(" ");
|
||||
|
||||
return new Set(words.sort());
|
||||
}
|
||||
|
||||
function map_add(map, key, value) {
|
||||
if (map.has(key)) {
|
||||
map.get(key).push(value);
|
||||
} else {
|
||||
map.set(key, [ value ]);
|
||||
}
|
||||
}
|
||||
|
||||
function map_from_object(obj) {
|
||||
var map = new Map();
|
||||
for (var key in obj) {
|
||||
if (HOP(obj, key) && key.charAt(0) === "$") {
|
||||
map.set(key.substr(1), obj[key]);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
function map_to_object(map) {
|
||||
var obj = Object.create(null);
|
||||
map.forEach(function (value, key) {
|
||||
obj["$" + key] = value;
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
function HOP(obj, prop) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
}
|
||||
|
||||
function keep_name(keep_setting, name) {
|
||||
return keep_setting === true
|
||||
|| (keep_setting instanceof RegExp && keep_setting.test(name));
|
||||
}
|
||||
|
||||
var lineTerminatorEscape = {
|
||||
"\0": "0",
|
||||
"\n": "n",
|
||||
"\r": "r",
|
||||
"\u2028": "u2028",
|
||||
"\u2029": "u2029",
|
||||
};
|
||||
function regexp_source_fix(source) {
|
||||
// V8 does not escape line terminators in regexp patterns in node 12
|
||||
// We'll also remove literal \0
|
||||
return source.replace(/[\0\n\r\u2028\u2029]/g, function (match, offset) {
|
||||
var escaped = source[offset - 1] == "\\"
|
||||
&& (source[offset - 2] != "\\"
|
||||
|| /(?:^|[^\\])(?:\\{2})*$/.test(source.slice(0, offset - 1)));
|
||||
return (escaped ? "" : "\\") + lineTerminatorEscape[match];
|
||||
});
|
||||
}
|
||||
|
||||
// Subset of regexps that is not going to cause regexp based DDOS
|
||||
// https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
|
||||
const re_safe_regexp = /^[\\/|\0\s\w^$.[\]()]*$/;
|
||||
|
||||
/** Check if the regexp is safe for Terser to create without risking a RegExp DOS */
|
||||
export const regexp_is_safe = (source) => re_safe_regexp.test(source);
|
||||
|
||||
const all_flags = "dgimsuyv";
|
||||
function sort_regexp_flags(flags) {
|
||||
const existing_flags = new Set(flags.split(""));
|
||||
let out = "";
|
||||
for (const flag of all_flags) {
|
||||
if (existing_flags.has(flag)) {
|
||||
out += flag;
|
||||
existing_flags.delete(flag);
|
||||
}
|
||||
}
|
||||
if (existing_flags.size) {
|
||||
// Flags Terser doesn't know about
|
||||
existing_flags.forEach(flag => { out += flag; });
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function has_annotation(node, annotation) {
|
||||
return node._annotations & annotation;
|
||||
}
|
||||
|
||||
function set_annotation(node, annotation) {
|
||||
node._annotations |= annotation;
|
||||
}
|
||||
|
||||
function clear_annotation(node, annotation) {
|
||||
node._annotations &= ~annotation;
|
||||
}
|
||||
|
||||
export {
|
||||
characters,
|
||||
defaults,
|
||||
HOP,
|
||||
keep_name,
|
||||
make_node,
|
||||
makePredicate,
|
||||
map_add,
|
||||
map_from_object,
|
||||
map_to_object,
|
||||
MAP,
|
||||
member,
|
||||
mergeSort,
|
||||
noop,
|
||||
push_uniq,
|
||||
regexp_source_fix,
|
||||
remove,
|
||||
return_false,
|
||||
return_null,
|
||||
return_this,
|
||||
return_true,
|
||||
sort_regexp_flags,
|
||||
string_template,
|
||||
has_annotation,
|
||||
set_annotation,
|
||||
clear_annotation,
|
||||
};
|
Reference in New Issue
Block a user