var unique_vars = [];
var classes = [];
var async = false;
+var export_default = false;
var generator = false;
var loops = 0;
var funcs = 0;
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() {
VAR_NAMES.length = INITIAL_NAMES_LEN; // prune any previous names still in the list
block_vars.length = 0;
unique_vars.length = 0;
classes.length = 0;
async = false;
+ export_default = false;
generator = false;
loops = 0;
funcs = 0;
clazz = 0;
in_class = 0;
called = Object.create(null);
- return [
+ var s = [
strictMode(),
- "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)
- : 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)
- "console.log(null, a, b, c, Infinity, NaN, undefined);"
- ].join("\n");
+ appendExport(1) + "var _calls_ = 10, a = 100, b = 10, c = 0;",
+ ];
+ createBlockVariables(MAX_GENERATION_RECURSION_DEPTH, 0, CANNOT_THROW, function(defns) {
+ s.push(defns());
+ if (rng(2)) {
+ s.push(createStatements(3, MAX_GENERATION_RECURSION_DEPTH, CANNOT_THROW, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, 0));
+ } 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 createBlockVariables(recurmax, stmtDepth, canThrow, fn) {
+ ++stmtDepth;
var block_len = block_vars.length;
var class_len = classes.length;
var nameLenBefore = VAR_NAMES.length;
if (SUPPORT.class) while (rng(100) == 0) {
var name = "C" + clazz++;
classes.push(name);
- s.push(createClassLiteral(recurmax,stmtDepth, canThrow, name));
+ s.push(appendExport(stmtDepth, true) + createClassLiteral(recurmax, stmtDepth, canThrow, name));
}
if (rng(2)) {
s.push(createDefinitions("const", consts), createDefinitions("let", lets));
function createDefinitions(type, names) {
if (!names.length) return "";
- var s = type + " ";
+ var s = appendExport(stmtDepth) + type + " ";
switch (SUPPORT.destructuring ? rng(10) : 2) {
case 0:
while (!rng(10)) names.splice(rng(names.length + 1), 0, "");
function createFunction(recurmax, allowDefun, canThrow, stmtDepth) {
if (--recurmax < 0) { return ";"; }
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
+ ++stmtDepth;
var s = [];
var name, args;
var nameLenBefore = VAR_NAMES.length;
lambda_vars.length = lambda_len;
VAR_NAMES.length = nameLenBefore;
+ if (allowDefun) s = appendExport(stmtDepth, true) + s;
if (!allowDefun) {
// 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 += call_next;
} 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 += call_next;
}
case STMT_SEMI:
return use_strict && rng(20) === 0 ? '"use strict";' : ";";
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) + ";";
case STMT_SWITCH:
// note: case args are actual expressions
case STMT_VAR:
if (SUPPORT.destructuring && rng(20) == 0) {
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;
}).join(", ") + ";";
} else switch (rng(3)) {
unique_vars.push("c");
var name = createVarName(MANDATORY);
unique_vars.pop();
- return "var " + name + ";";
+ return appendExport(stmtDepth) + "var " + name + ";";
case 1:
// initializer can only have one expression
unique_vars.push("c");
var name = createVarName(MANDATORY);
unique_vars.pop();
- return "var " + name + " = " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ";";
+ return appendExport(stmtDepth) + "var " + name + " = " + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ";";
default:
// initializer can only have one expression
unique_vars.push("c");
var n1 = createVarName(MANDATORY);
var n2 = createVarName(MANDATORY);
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:
switch (rng(8)) {
return;
}
+function run_code(code, toplevel) {
+ return sandbox.run_code(sandbox.strip_exports(code), toplevel);
+}
+
function writeln(stream, msg) {
if (typeof msg != "undefined") {
stream.write(typeof msg == "string" ? msg : msg.stack || "" + msg);
printfn("// !!! beautify failed !!!");
printfn(beautified.error);
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;
} else if (options) {
var uglified = UglifyJS.minify(beautified.code, JSON.parse(options));
actual = uglified.error;
} else {
expected = uglify_result;
- actual = sandbox.run_code(uglified.code, toplevel);
+ actual = run_code(uglified.code, toplevel);
}
if (!sandbox.same_stdout(expected, actual)) {
beautified = null;
errorln("Error testing options." + component + "." + name);
errorln(result.error);
} else {
- var r = sandbox.run_code(result.code, toplevel);
+ var r = run_code(result.code, toplevel);
return !sandbox.same_stdout(uglify_result, r);
}
}
errorln("Error testing options." + component);
errorln(result.error);
} else {
- var r = sandbox.run_code(result.code, toplevel);
+ var r = run_code(result.code, toplevel);
return !sandbox.same_stdout(uglify_result, r);
}
});
}
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 (n == "toString") - (m == "toString")
|| (typeof global[n] == "function") - (typeof global[m] == "function")
].join("\n");
}
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 (!stack.filled && match[1]) stack.push({
code: code,
process.stdout.write(round + " of " + num_iterations + "\r");
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 (typeof result == "string") return;
println();
errored = typeof original_result != "string";
if (!uglify_code.error) {
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);
// ignore v8 parser bug
if (!ok && bug_async_arrow_rest(uglify_result)) ok = true;
ok = true;
} else {
// 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);
}
}
// ignore declaration order of global variables
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`
if (!ok && o.compress && o.compress.unsafe_math && typeof original_result == typeof uglify_result) {
ok = original_result.name == uglify_result.name && fuzzy_match(original_result.message, uglify_result.message);
}
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);
}
}
if (!ok && errored && uglify_result.name == "ReferenceError" && original_result.name == "ReferenceError") ok = true;
// ignore difference due to implicit strict-mode in `class`
if (!ok && /\bclass\b/.test(original_code)) {
- var original_strict = sandbox.run_code('"use strict";' + original_code, toplevel);
- var uglify_strict = sandbox.run_code('"use strict";' + uglify_code, toplevel);
+ var original_strict = run_code('"use strict";' + original_code, toplevel);
+ var uglify_strict = run_code('"use strict";' + uglify_code, toplevel);
if (typeof original_strict != "string" && /strict/.test(original_strict.message)) {
ok = typeof uglify_strict != "string" && /strict/.test(uglify_strict.message);
} else {
var orig_skipped = patch_try_catch(original_code, toplevel);
var uglify_skipped = patch_try_catch(uglify_code, toplevel);
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 {