10
lib/ast.js
10
lib/ast.js
@@ -1176,15 +1176,7 @@ var AST_ExportDefault = DEFNODE("ExportDefault", "body", {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
_validate: function() {
|
_validate: function() {
|
||||||
if (this.body instanceof AST_Class && this.body.name) {
|
if (!(this.body instanceof AST_DefClass || this.body instanceof AST_LambdaDefinition)) {
|
||||||
if (!(this.body instanceof AST_DefClass)) {
|
|
||||||
throw new Error("body must be AST_DefClass when named");
|
|
||||||
}
|
|
||||||
} else if (this.body instanceof AST_Lambda && this.body.name) {
|
|
||||||
if (!(this.body instanceof AST_LambdaDefinition)) {
|
|
||||||
throw new Error("body must be AST_LambdaDefinition when named");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
must_be_expression(this, "body");
|
must_be_expression(this, "body");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -940,6 +940,8 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
if (!node.name) return;
|
if (!node.name) return;
|
||||||
var d = node.name.definition();
|
var d = node.name.definition();
|
||||||
|
var parent = tw.parent();
|
||||||
|
if (parent instanceof AST_ExportDeclaration || parent instanceof AST_ExportDefault) d.single_use = false;
|
||||||
if (safe_to_assign(tw, d, true)) {
|
if (safe_to_assign(tw, d, true)) {
|
||||||
mark(tw, d);
|
mark(tw, d);
|
||||||
tw.loop_ids[d.id] = tw.in_loop;
|
tw.loop_ids[d.id] = tw.in_loop;
|
||||||
@@ -6709,6 +6711,7 @@ merge(Compressor.prototype, {
|
|||||||
var var_decl = 0;
|
var var_decl = 0;
|
||||||
self.walk(new TreeWalker(function(node) {
|
self.walk(new TreeWalker(function(node) {
|
||||||
if (var_decl > 1) return true;
|
if (var_decl > 1) return true;
|
||||||
|
if (node instanceof AST_ExportDeclaration) return true;
|
||||||
if (node instanceof AST_Scope && node !== self) return true;
|
if (node instanceof AST_Scope && node !== self) return true;
|
||||||
if (node instanceof AST_Var) {
|
if (node instanceof AST_Var) {
|
||||||
var_decl++;
|
var_decl++;
|
||||||
@@ -6728,12 +6731,15 @@ merge(Compressor.prototype, {
|
|||||||
dirs.push(node);
|
dirs.push(node);
|
||||||
return make_node(AST_EmptyStatement, node);
|
return make_node(AST_EmptyStatement, node);
|
||||||
}
|
}
|
||||||
if (hoist_funs && node instanceof AST_Defun
|
if (node instanceof AST_Defun) {
|
||||||
&& (tt.parent() === self || !compressor.has_directive("use strict"))) {
|
if (!hoist_funs) return node;
|
||||||
|
if (tt.parent() !== self && compressor.has_directive("use strict")) return node;
|
||||||
hoisted.push(node);
|
hoisted.push(node);
|
||||||
return make_node(AST_EmptyStatement, node);
|
return make_node(AST_EmptyStatement, node);
|
||||||
}
|
}
|
||||||
if (hoist_vars && node instanceof AST_Var) {
|
if (node instanceof AST_Var) {
|
||||||
|
if (!hoist_vars) return node;
|
||||||
|
if (tt.parent() instanceof AST_ExportDeclaration) return node;
|
||||||
if (!all(node.definitions, function(defn) {
|
if (!all(node.definitions, function(defn) {
|
||||||
var sym = defn.name;
|
var sym = defn.name;
|
||||||
return sym instanceof AST_SymbolVar
|
return sym instanceof AST_SymbolVar
|
||||||
|
|||||||
@@ -664,7 +664,9 @@ function OutputStream(options) {
|
|||||||
function needs_parens_function(output) {
|
function needs_parens_function(output) {
|
||||||
if (!output.has_parens() && first_in_statement(output)) return true;
|
if (!output.has_parens() && first_in_statement(output)) return true;
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
// export default (function() {})()
|
// export default (function foo() {});
|
||||||
|
if (this.name && p instanceof AST_ExportDefault) return true;
|
||||||
|
// export default (function() {})(foo);
|
||||||
if (p && p.TYPE == "Call" && output.parent(1) instanceof AST_ExportDefault) return true;
|
if (p && p.TYPE == "Call" && output.parent(1) instanceof AST_ExportDefault) return true;
|
||||||
if (output.option("webkit") && p instanceof AST_PropAccess && p.expression === this) return true;
|
if (output.option("webkit") && p instanceof AST_PropAccess && p.expression === this) return true;
|
||||||
if (output.option("wrap_iife") && p instanceof AST_Call && p.expression === this) return true;
|
if (output.option("wrap_iife") && p instanceof AST_Call && p.expression === this) return true;
|
||||||
@@ -725,6 +727,8 @@ function OutputStream(options) {
|
|||||||
// { [(1, 2)]: foo } = bar
|
// { [(1, 2)]: foo } = bar
|
||||||
// { 1: (2, foo) } = bar
|
// { 1: (2, foo) } = bar
|
||||||
|| p instanceof AST_DestructuredKeyVal
|
|| p instanceof AST_DestructuredKeyVal
|
||||||
|
// export default (foo, bar)
|
||||||
|
|| p instanceof AST_ExportDefault
|
||||||
// for (foo of (bar, baz));
|
// for (foo of (bar, baz));
|
||||||
|| p instanceof AST_ForOf
|
|| p instanceof AST_ForOf
|
||||||
// { [(1, 2)]: 3 }[2] ---> 3
|
// { [(1, 2)]: 3 }[2] ---> 3
|
||||||
@@ -1032,9 +1036,16 @@ function OutputStream(options) {
|
|||||||
output.space();
|
output.space();
|
||||||
output.print("default");
|
output.print("default");
|
||||||
output.space();
|
output.space();
|
||||||
this.body.print(output);
|
var body = this.body;
|
||||||
if (this.body instanceof AST_Class) return;
|
body.print(output);
|
||||||
if (this.body instanceof AST_Lambda && !is_arrow(this.body)) return;
|
if (body instanceof AST_ClassExpression) {
|
||||||
|
if (!body.name) return;
|
||||||
|
}
|
||||||
|
if (body instanceof AST_DefClass) return;
|
||||||
|
if (body instanceof AST_LambdaDefinition) return;
|
||||||
|
if (body instanceof AST_LambdaExpression) {
|
||||||
|
if (!body.name && !is_arrow(body)) return;
|
||||||
|
}
|
||||||
output.semicolon();
|
output.semicolon();
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_ExportForeign, function(output) {
|
DEFPRINT(AST_ExportForeign, function(output) {
|
||||||
|
|||||||
@@ -56,6 +56,20 @@ defaults_parentheses_2: {
|
|||||||
expect_exact: 'export default(async function(){console.log("PASS")})();'
|
expect_exact: 'export default(async function(){console.log("PASS")})();'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaults_parentheses_3: {
|
||||||
|
input: {
|
||||||
|
export default (42, "PASS");
|
||||||
|
}
|
||||||
|
expect_exact: 'export default(42,"PASS");'
|
||||||
|
}
|
||||||
|
|
||||||
|
defaults_parentheses_4: {
|
||||||
|
input: {
|
||||||
|
export default (function f() {});
|
||||||
|
}
|
||||||
|
expect_exact: "export default(function f(){});"
|
||||||
|
}
|
||||||
|
|
||||||
foreign: {
|
foreign: {
|
||||||
input: {
|
input: {
|
||||||
export * from "foo";
|
export * from "foo";
|
||||||
@@ -203,6 +217,20 @@ hoist_exports: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hoist_vars: {
|
||||||
|
options = {
|
||||||
|
hoist_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
export var b = 42;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
export var b = 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
keep_return_values: {
|
keep_return_values: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -301,3 +329,35 @@ single_use_default: {
|
|||||||
f();
|
f();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
single_use_class: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
export class A {}
|
||||||
|
A.prototype.p = "PASS";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
export class A {}
|
||||||
|
A.prototype.p = "PASS";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
single_use_class_default: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
export default class A {}
|
||||||
|
A.prototype.p = "PASS";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
export default class A {}
|
||||||
|
A.prototype.p = "PASS";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -132,6 +132,11 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parent instanceof U.AST_VarDef && parent.name === node) return;
|
if (parent instanceof U.AST_VarDef && parent.name === node) return;
|
||||||
|
// preserve exports
|
||||||
|
if (parent instanceof U.AST_ExportDeclaration) return;
|
||||||
|
if (parent instanceof U.AST_ExportDefault) return;
|
||||||
|
if (parent instanceof U.AST_ExportForeign) return;
|
||||||
|
if (parent instanceof U.AST_ExportReferences) return;
|
||||||
// preserve for (var xxx; ...)
|
// preserve for (var xxx; ...)
|
||||||
if (parent instanceof U.AST_For && parent.init === node && node instanceof U.AST_Definitions) return node;
|
if (parent instanceof U.AST_For && parent.init === node && node instanceof U.AST_Definitions) return node;
|
||||||
// preserve for (xxx in/of ...)
|
// preserve for (xxx in/of ...)
|
||||||
@@ -455,6 +460,13 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
|
|||||||
return List.skip;
|
return List.skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// preserve sole definition of an export statement
|
||||||
|
if (node instanceof U.AST_VarDef
|
||||||
|
&& parent.definitions.length == 1
|
||||||
|
&& tt.parent(1) instanceof U.AST_ExportDeclaration) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
// remove this node unless its the sole element of a (transient) sequence
|
// remove this node unless its the sole element of a (transient) sequence
|
||||||
if (!(parent instanceof U.AST_Sequence) || parent.expressions.length > 1) {
|
if (!(parent instanceof U.AST_Sequence) || parent.expressions.length > 1) {
|
||||||
node.start._permute++;
|
node.start._permute++;
|
||||||
@@ -720,7 +732,7 @@ function run_code(code, toplevel, result_cache, timeout) {
|
|||||||
if (!value) {
|
if (!value) {
|
||||||
var start = Date.now();
|
var start = Date.now();
|
||||||
result_cache[key] = value = {
|
result_cache[key] = value = {
|
||||||
result: sandbox.run_code(code, toplevel, timeout),
|
result: sandbox.run_code(sandbox.strip_exports(code), toplevel, timeout),
|
||||||
elapsed: Date.now() - start,
|
elapsed: Date.now() - start,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,14 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
|
|||||||
} : function(expected, actual) {
|
} : function(expected, actual) {
|
||||||
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
|
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
|
||||||
};
|
};
|
||||||
|
exports.strip_exports = function(code) {
|
||||||
|
var count = 0;
|
||||||
|
return code.replace(/\bexport(?:\s*\{[^}]*};|\s+default\b(?:\s*(\(|\{|class\s*\{|class\s+(?=extends\b)|(?:async\s+)?function\s*(?:\*\s*)?\())?|\b)/g, function(match, header) {
|
||||||
|
if (!header) return "";
|
||||||
|
if (header.length == 1) return "~" + header;
|
||||||
|
return header.slice(0, -1) + " _" + ++count + header.slice(-1);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function is_error(result) {
|
function is_error(result) {
|
||||||
return result && typeof result.name == "string" && typeof result.message == "string";
|
return result && typeof result.name == "string" && typeof result.message == "string";
|
||||||
|
|||||||
@@ -363,6 +363,7 @@ var lambda_vars = [];
|
|||||||
var unique_vars = [];
|
var unique_vars = [];
|
||||||
var classes = [];
|
var classes = [];
|
||||||
var async = false;
|
var async = false;
|
||||||
|
var export_default = false;
|
||||||
var generator = false;
|
var generator = false;
|
||||||
var loops = 0;
|
var loops = 0;
|
||||||
var funcs = 0;
|
var funcs = 0;
|
||||||
@@ -380,6 +381,17 @@ function strictMode() {
|
|||||||
return use_strict && rng(4) == 0 ? '"use strict";' : "";
|
return use_strict && rng(4) == 0 ? '"use strict";' : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function appendExport(stmtDepth, allowDefault) {
|
||||||
|
if (stmtDepth == 1 && rng(20) == 0) {
|
||||||
|
if (allowDefault && !export_default && rng(5) == 0) {
|
||||||
|
export_default = true;
|
||||||
|
return "export default ";
|
||||||
|
}
|
||||||
|
return "export ";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
function createTopLevelCode() {
|
function createTopLevelCode() {
|
||||||
VAR_NAMES.length = INITIAL_NAMES_LEN; // prune any previous names still in the list
|
VAR_NAMES.length = INITIAL_NAMES_LEN; // prune any previous names still in the list
|
||||||
block_vars.length = 0;
|
block_vars.length = 0;
|
||||||
@@ -387,21 +399,28 @@ function createTopLevelCode() {
|
|||||||
unique_vars.length = 0;
|
unique_vars.length = 0;
|
||||||
classes.length = 0;
|
classes.length = 0;
|
||||||
async = false;
|
async = false;
|
||||||
|
export_default = false;
|
||||||
generator = false;
|
generator = false;
|
||||||
loops = 0;
|
loops = 0;
|
||||||
funcs = 0;
|
funcs = 0;
|
||||||
clazz = 0;
|
clazz = 0;
|
||||||
in_class = 0;
|
in_class = 0;
|
||||||
called = Object.create(null);
|
called = Object.create(null);
|
||||||
return [
|
var s = [
|
||||||
strictMode(),
|
strictMode(),
|
||||||
"var _calls_ = 10, a = 100, b = 10, c = 0;",
|
appendExport(1) + "var _calls_ = 10, a = 100, b = 10, c = 0;",
|
||||||
rng(2)
|
];
|
||||||
? createStatements(3, MAX_GENERATION_RECURSION_DEPTH, CANNOT_THROW, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, 0)
|
createBlockVariables(MAX_GENERATION_RECURSION_DEPTH, 0, CANNOT_THROW, function(defns) {
|
||||||
: createFunctions(rng(MAX_GENERATED_TOPLEVELS_PER_RUN) + 1, MAX_GENERATION_RECURSION_DEPTH, DEFUN_OK, CANNOT_THROW, 0),
|
s.push(defns());
|
||||||
// preceding `null` makes for a cleaner output (empty string still shows up etc)
|
if (rng(2)) {
|
||||||
"console.log(null, a, b, c, Infinity, NaN, undefined);"
|
s.push(createStatements(3, MAX_GENERATION_RECURSION_DEPTH, CANNOT_THROW, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, 0));
|
||||||
].join("\n");
|
} else {
|
||||||
|
s.push(createFunctions(rng(MAX_GENERATED_TOPLEVELS_PER_RUN) + 1, MAX_GENERATION_RECURSION_DEPTH, DEFUN_OK, CANNOT_THROW, 0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// preceding `null` makes for a cleaner output (empty string still shows up etc)
|
||||||
|
s.push("console.log(null, a, b, c, Infinity, NaN, undefined);");
|
||||||
|
return s.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function createFunctions(n, recurmax, allowDefun, canThrow, stmtDepth) {
|
function createFunctions(n, recurmax, allowDefun, canThrow, stmtDepth) {
|
||||||
@@ -668,6 +687,7 @@ function filterDirective(s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createBlockVariables(recurmax, stmtDepth, canThrow, fn) {
|
function createBlockVariables(recurmax, stmtDepth, canThrow, fn) {
|
||||||
|
++stmtDepth;
|
||||||
var block_len = block_vars.length;
|
var block_len = block_vars.length;
|
||||||
var class_len = classes.length;
|
var class_len = classes.length;
|
||||||
var nameLenBefore = VAR_NAMES.length;
|
var nameLenBefore = VAR_NAMES.length;
|
||||||
@@ -691,7 +711,7 @@ function createBlockVariables(recurmax, stmtDepth, canThrow, fn) {
|
|||||||
if (SUPPORT.class) while (rng(100) == 0) {
|
if (SUPPORT.class) while (rng(100) == 0) {
|
||||||
var name = "C" + clazz++;
|
var name = "C" + clazz++;
|
||||||
classes.push(name);
|
classes.push(name);
|
||||||
s.push(createClassLiteral(recurmax,stmtDepth, canThrow, name));
|
s.push(appendExport(stmtDepth, true) + createClassLiteral(recurmax, stmtDepth, canThrow, name));
|
||||||
}
|
}
|
||||||
if (rng(2)) {
|
if (rng(2)) {
|
||||||
s.push(createDefinitions("const", consts), createDefinitions("let", lets));
|
s.push(createDefinitions("const", consts), createDefinitions("let", lets));
|
||||||
@@ -707,7 +727,7 @@ function createBlockVariables(recurmax, stmtDepth, canThrow, fn) {
|
|||||||
|
|
||||||
function createDefinitions(type, names) {
|
function createDefinitions(type, names) {
|
||||||
if (!names.length) return "";
|
if (!names.length) return "";
|
||||||
var s = type + " ";
|
var s = appendExport(stmtDepth) + type + " ";
|
||||||
switch (SUPPORT.destructuring ? rng(10) : 2) {
|
switch (SUPPORT.destructuring ? rng(10) : 2) {
|
||||||
case 0:
|
case 0:
|
||||||
while (!rng(10)) names.splice(rng(names.length + 1), 0, "");
|
while (!rng(10)) names.splice(rng(names.length + 1), 0, "");
|
||||||
@@ -780,6 +800,7 @@ function invokeGenerator(was_generator) {
|
|||||||
function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
|
function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
|
||||||
if (--recurmax < 0) { return ";"; }
|
if (--recurmax < 0) { return ";"; }
|
||||||
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
|
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
|
||||||
|
++stmtDepth;
|
||||||
var s = [];
|
var s = [];
|
||||||
var name, args;
|
var name, args;
|
||||||
var nameLenBefore = VAR_NAMES.length;
|
var nameLenBefore = VAR_NAMES.length;
|
||||||
@@ -831,13 +852,14 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
|
|||||||
lambda_vars.length = lambda_len;
|
lambda_vars.length = lambda_len;
|
||||||
VAR_NAMES.length = nameLenBefore;
|
VAR_NAMES.length = nameLenBefore;
|
||||||
|
|
||||||
|
if (allowDefun) s = appendExport(stmtDepth, true) + s;
|
||||||
if (!allowDefun) {
|
if (!allowDefun) {
|
||||||
// avoid "function statements" (decl inside statements)
|
// avoid "function statements" (decl inside statements)
|
||||||
s = "var " + createVarName(MANDATORY) + " = " + s;
|
s = appendExport(stmtDepth) + "var " + createVarName(MANDATORY) + " = " + s;
|
||||||
s += args || createArgs(recurmax, stmtDepth, canThrow);
|
s += args || createArgs(recurmax, stmtDepth, canThrow);
|
||||||
s += call_next;
|
s += call_next;
|
||||||
} else if (!(name in called) || args || rng(3)) {
|
} else if (!(name in called) || args || rng(3)) {
|
||||||
s += "var " + createVarName(MANDATORY) + " = " + name;
|
s += appendExport(stmtDepth) + "var " + createVarName(MANDATORY) + " = " + name;
|
||||||
s += args || createArgs(recurmax, stmtDepth, canThrow);
|
s += args || createArgs(recurmax, stmtDepth, canThrow);
|
||||||
s += call_next;
|
s += call_next;
|
||||||
}
|
}
|
||||||
@@ -987,6 +1009,10 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
case STMT_SEMI:
|
case STMT_SEMI:
|
||||||
return use_strict && rng(20) === 0 ? '"use strict";' : ";";
|
return use_strict && rng(20) === 0 ? '"use strict";' : ";";
|
||||||
case STMT_EXPR:
|
case STMT_EXPR:
|
||||||
|
if (stmtDepth == 1 && !export_default && rng(20) == 0) {
|
||||||
|
export_default = true;
|
||||||
|
return "export default " + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ";";
|
||||||
|
}
|
||||||
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ";";
|
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ";";
|
||||||
case STMT_SWITCH:
|
case STMT_SWITCH:
|
||||||
// note: case args are actual expressions
|
// note: case args are actual expressions
|
||||||
@@ -995,7 +1021,7 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
case STMT_VAR:
|
case STMT_VAR:
|
||||||
if (SUPPORT.destructuring && rng(20) == 0) {
|
if (SUPPORT.destructuring && rng(20) == 0) {
|
||||||
var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow);
|
var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow);
|
||||||
return "var " + pairs.names.map(function(name, index) {
|
return appendExport(stmtDepth) + "var " + pairs.names.map(function(name, index) {
|
||||||
return index in pairs.values ? name + " = " + pairs.values[index] : name;
|
return index in pairs.values ? name + " = " + pairs.values[index] : name;
|
||||||
}).join(", ") + ";";
|
}).join(", ") + ";";
|
||||||
} else switch (rng(3)) {
|
} else switch (rng(3)) {
|
||||||
@@ -1003,20 +1029,20 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
unique_vars.push("c");
|
unique_vars.push("c");
|
||||||
var name = createVarName(MANDATORY);
|
var name = createVarName(MANDATORY);
|
||||||
unique_vars.pop();
|
unique_vars.pop();
|
||||||
return "var " + name + ";";
|
return appendExport(stmtDepth) + "var " + name + ";";
|
||||||
case 1:
|
case 1:
|
||||||
// initializer can only have one expression
|
// initializer can only have one expression
|
||||||
unique_vars.push("c");
|
unique_vars.push("c");
|
||||||
var name = createVarName(MANDATORY);
|
var name = createVarName(MANDATORY);
|
||||||
unique_vars.pop();
|
unique_vars.pop();
|
||||||
return "var " + name + " = " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ";";
|
return appendExport(stmtDepth) + "var " + name + " = " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ";";
|
||||||
default:
|
default:
|
||||||
// initializer can only have one expression
|
// initializer can only have one expression
|
||||||
unique_vars.push("c");
|
unique_vars.push("c");
|
||||||
var n1 = createVarName(MANDATORY);
|
var n1 = createVarName(MANDATORY);
|
||||||
var n2 = createVarName(MANDATORY);
|
var n2 = createVarName(MANDATORY);
|
||||||
unique_vars.pop();
|
unique_vars.pop();
|
||||||
return "var " + n1 + " = " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ", " + n2 + " = " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ";";
|
return appendExport(stmtDepth) + "var " + n1 + " = " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ", " + n2 + " = " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ";";
|
||||||
}
|
}
|
||||||
case STMT_RETURN_ETC:
|
case STMT_RETURN_ETC:
|
||||||
switch (rng(8)) {
|
switch (rng(8)) {
|
||||||
@@ -1939,6 +1965,10 @@ if (require.main !== module) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function run_code(code, toplevel) {
|
||||||
|
return sandbox.run_code(sandbox.strip_exports(code), toplevel);
|
||||||
|
}
|
||||||
|
|
||||||
function writeln(stream, msg) {
|
function writeln(stream, msg) {
|
||||||
if (typeof msg != "undefined") {
|
if (typeof msg != "undefined") {
|
||||||
stream.write(typeof msg == "string" ? msg : msg.stack || "" + msg);
|
stream.write(typeof msg == "string" ? msg : msg.stack || "" + msg);
|
||||||
@@ -1960,7 +1990,7 @@ function try_beautify(code, toplevel, result, printfn, options) {
|
|||||||
printfn("// !!! beautify failed !!!");
|
printfn("// !!! beautify failed !!!");
|
||||||
printfn(beautified.error);
|
printfn(beautified.error);
|
||||||
beautified = null;
|
beautified = null;
|
||||||
} else if (!sandbox.same_stdout(sandbox.run_code(beautified.code, toplevel), result)) {
|
} else if (!sandbox.same_stdout(run_code(beautified.code, toplevel), result)) {
|
||||||
beautified = null;
|
beautified = null;
|
||||||
} else if (options) {
|
} else if (options) {
|
||||||
var uglified = UglifyJS.minify(beautified.code, JSON.parse(options));
|
var uglified = UglifyJS.minify(beautified.code, JSON.parse(options));
|
||||||
@@ -1970,7 +2000,7 @@ function try_beautify(code, toplevel, result, printfn, options) {
|
|||||||
actual = uglified.error;
|
actual = uglified.error;
|
||||||
} else {
|
} else {
|
||||||
expected = uglify_result;
|
expected = uglify_result;
|
||||||
actual = sandbox.run_code(uglified.code, toplevel);
|
actual = run_code(uglified.code, toplevel);
|
||||||
}
|
}
|
||||||
if (!sandbox.same_stdout(expected, actual)) {
|
if (!sandbox.same_stdout(expected, actual)) {
|
||||||
beautified = null;
|
beautified = null;
|
||||||
@@ -2008,7 +2038,7 @@ function log_suspects(minify_options, component) {
|
|||||||
errorln("Error testing options." + component + "." + name);
|
errorln("Error testing options." + component + "." + name);
|
||||||
errorln(result.error);
|
errorln(result.error);
|
||||||
} else {
|
} else {
|
||||||
var r = sandbox.run_code(result.code, toplevel);
|
var r = run_code(result.code, toplevel);
|
||||||
return !sandbox.same_stdout(uglify_result, r);
|
return !sandbox.same_stdout(uglify_result, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2036,7 +2066,7 @@ function log_suspects_global(options, toplevel) {
|
|||||||
errorln("Error testing options." + component);
|
errorln("Error testing options." + component);
|
||||||
errorln(result.error);
|
errorln(result.error);
|
||||||
} else {
|
} else {
|
||||||
var r = sandbox.run_code(result.code, toplevel);
|
var r = run_code(result.code, toplevel);
|
||||||
return !sandbox.same_stdout(uglify_result, r);
|
return !sandbox.same_stdout(uglify_result, r);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2108,7 +2138,7 @@ function log(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sort_globals(code) {
|
function sort_globals(code) {
|
||||||
var globals = sandbox.run_code("throw Object.keys(this).sort(" + function(global) {
|
var globals = run_code("throw Object.keys(this).sort(" + function(global) {
|
||||||
return function(m, n) {
|
return function(m, n) {
|
||||||
return (n == "toString") - (m == "toString")
|
return (n == "toString") - (m == "toString")
|
||||||
|| (typeof global[n] == "function") - (typeof global[m] == "function")
|
|| (typeof global[n] == "function") - (typeof global[m] == "function")
|
||||||
@@ -2221,7 +2251,7 @@ function patch_try_catch(orig, toplevel) {
|
|||||||
].join("\n");
|
].join("\n");
|
||||||
}
|
}
|
||||||
var new_code = code.slice(0, index) + insert + code.slice(index) + tail_throw;
|
var new_code = code.slice(0, index) + insert + code.slice(index) + tail_throw;
|
||||||
var result = sandbox.run_code(new_code, toplevel);
|
var result = run_code(new_code, toplevel);
|
||||||
if (!sandbox.is_error(result)) {
|
if (!sandbox.is_error(result)) {
|
||||||
if (!stack.filled && match[1]) stack.push({
|
if (!stack.filled && match[1]) stack.push({
|
||||||
code: code,
|
code: code,
|
||||||
@@ -2292,7 +2322,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
process.stdout.write(round + " of " + num_iterations + "\r");
|
process.stdout.write(round + " of " + num_iterations + "\r");
|
||||||
|
|
||||||
original_code = createTopLevelCode();
|
original_code = createTopLevelCode();
|
||||||
var orig_result = [ sandbox.run_code(original_code), sandbox.run_code(original_code, true) ];
|
var orig_result = [ run_code(original_code), run_code(original_code, true) ];
|
||||||
if (orig_result.some(function(result, toplevel) {
|
if (orig_result.some(function(result, toplevel) {
|
||||||
if (typeof result == "string") return;
|
if (typeof result == "string") return;
|
||||||
println();
|
println();
|
||||||
@@ -2317,7 +2347,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
errored = typeof original_result != "string";
|
errored = typeof original_result != "string";
|
||||||
if (!uglify_code.error) {
|
if (!uglify_code.error) {
|
||||||
uglify_code = uglify_code.code;
|
uglify_code = uglify_code.code;
|
||||||
uglify_result = sandbox.run_code(uglify_code, toplevel);
|
uglify_result = run_code(uglify_code, toplevel);
|
||||||
ok = sandbox.same_stdout(original_result, uglify_result);
|
ok = sandbox.same_stdout(original_result, uglify_result);
|
||||||
// ignore v8 parser bug
|
// ignore v8 parser bug
|
||||||
if (!ok && bug_async_arrow_rest(uglify_result)) ok = true;
|
if (!ok && bug_async_arrow_rest(uglify_result)) ok = true;
|
||||||
@@ -2328,13 +2358,13 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
ok = true;
|
ok = true;
|
||||||
} else {
|
} else {
|
||||||
// ignore spurious time-outs
|
// ignore spurious time-outs
|
||||||
if (!orig_result[toplevel ? 3 : 2]) orig_result[toplevel ? 3 : 2] = sandbox.run_code(original_code, toplevel, 10000);
|
if (!orig_result[toplevel ? 3 : 2]) orig_result[toplevel ? 3 : 2] = run_code(original_code, toplevel, 10000);
|
||||||
ok = sandbox.same_stdout(orig_result[toplevel ? 3 : 2], uglify_result);
|
ok = sandbox.same_stdout(orig_result[toplevel ? 3 : 2], uglify_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ignore declaration order of global variables
|
// ignore declaration order of global variables
|
||||||
if (!ok && !toplevel) {
|
if (!ok && !toplevel) {
|
||||||
ok = sandbox.same_stdout(sandbox.run_code(sort_globals(original_code)), sandbox.run_code(sort_globals(uglify_code)));
|
ok = sandbox.same_stdout(run_code(sort_globals(original_code)), run_code(sort_globals(uglify_code)));
|
||||||
}
|
}
|
||||||
// ignore numerical imprecision caused by `unsafe_math`
|
// ignore numerical imprecision caused by `unsafe_math`
|
||||||
if (!ok && o.compress && o.compress.unsafe_math && typeof original_result == typeof uglify_result) {
|
if (!ok && o.compress && o.compress.unsafe_math && typeof original_result == typeof uglify_result) {
|
||||||
@@ -2344,7 +2374,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
ok = original_result.name == uglify_result.name && fuzzy_match(original_result.message, uglify_result.message);
|
ok = original_result.name == uglify_result.name && fuzzy_match(original_result.message, uglify_result.message);
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
var fuzzy_result = sandbox.run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3"), toplevel);
|
var fuzzy_result = run_code(original_code.replace(/( - 0\.1){3}/g, " - 0.3"), toplevel);
|
||||||
ok = sandbox.same_stdout(fuzzy_result, uglify_result);
|
ok = sandbox.same_stdout(fuzzy_result, uglify_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2352,8 +2382,8 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
if (!ok && errored && uglify_result.name == "ReferenceError" && original_result.name == "ReferenceError") ok = true;
|
if (!ok && errored && uglify_result.name == "ReferenceError" && original_result.name == "ReferenceError") ok = true;
|
||||||
// ignore difference due to implicit strict-mode in `class`
|
// ignore difference due to implicit strict-mode in `class`
|
||||||
if (!ok && /\bclass\b/.test(original_code)) {
|
if (!ok && /\bclass\b/.test(original_code)) {
|
||||||
var original_strict = sandbox.run_code('"use strict";' + original_code, toplevel);
|
var original_strict = run_code('"use strict";' + original_code, toplevel);
|
||||||
var uglify_strict = sandbox.run_code('"use strict";' + uglify_code, toplevel);
|
var uglify_strict = run_code('"use strict";' + uglify_code, toplevel);
|
||||||
if (typeof original_strict != "string" && /strict/.test(original_strict.message)) {
|
if (typeof original_strict != "string" && /strict/.test(original_strict.message)) {
|
||||||
ok = typeof uglify_strict != "string" && /strict/.test(uglify_strict.message);
|
ok = typeof uglify_strict != "string" && /strict/.test(uglify_strict.message);
|
||||||
} else {
|
} else {
|
||||||
@@ -2385,7 +2415,7 @@ for (var round = 1; round <= num_iterations; round++) {
|
|||||||
var orig_skipped = patch_try_catch(original_code, toplevel);
|
var orig_skipped = patch_try_catch(original_code, toplevel);
|
||||||
var uglify_skipped = patch_try_catch(uglify_code, toplevel);
|
var uglify_skipped = patch_try_catch(uglify_code, toplevel);
|
||||||
if (orig_skipped && uglify_skipped) {
|
if (orig_skipped && uglify_skipped) {
|
||||||
ok = sandbox.same_stdout(sandbox.run_code(orig_skipped, toplevel), sandbox.run_code(uglify_skipped, toplevel));
|
ok = sandbox.same_stdout(run_code(orig_skipped, toplevel), run_code(uglify_skipped, toplevel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user