extend ufuzz generator (#1783)
- property access - property assignment - allow bare expression within try-block - normalise `Error` in `console.log()` - generate more unary expressions - add parenthesis to enforce precedence - adjust variable reuse/creation - add parameters to function declaration & expression - add return expression - add trivial arguments to function call
This commit is contained in:
@@ -29,7 +29,7 @@ exports.run_code = function(code) {
|
|||||||
console: {
|
console: {
|
||||||
log: function() {
|
log: function() {
|
||||||
return console.log.apply(console, [].map.call(arguments, function(arg) {
|
return console.log.apply(console, [].map.call(arguments, function(arg) {
|
||||||
return typeof arg == "function" ? arg.toString() : arg;
|
return typeof arg == "function" || arg && /Error$/.test(arg.name) ? arg.toString() : arg;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
294
test/ufuzz.js
294
test/ufuzz.js
@@ -222,15 +222,19 @@ var ASSIGNMENTS = [
|
|||||||
'>>>=',
|
'>>>=',
|
||||||
'%=' ];
|
'%=' ];
|
||||||
|
|
||||||
var UNARY_OPS = [
|
var UNARY_SAFE = [
|
||||||
'--',
|
'+',
|
||||||
'++',
|
'-',
|
||||||
'~',
|
'~',
|
||||||
'!',
|
'!',
|
||||||
'void ',
|
'void ',
|
||||||
'delete ', // should be safe, even `delete foo` and `delete f()` shouldn't crash
|
'delete ',
|
||||||
' - ',
|
];
|
||||||
' + ' ];
|
var UNARY_POSTFIX = [
|
||||||
|
'++',
|
||||||
|
'--',
|
||||||
|
];
|
||||||
|
var UNARY_PREFIX = UNARY_POSTFIX.concat(UNARY_SAFE);
|
||||||
|
|
||||||
var NO_COMMA = true;
|
var NO_COMMA = true;
|
||||||
var COMMA_OK = false;
|
var COMMA_OK = false;
|
||||||
@@ -251,26 +255,26 @@ var NO_DECL = true;
|
|||||||
var DONT_STORE = true;
|
var DONT_STORE = true;
|
||||||
|
|
||||||
var VAR_NAMES = [
|
var VAR_NAMES = [
|
||||||
'foo',
|
'a',
|
||||||
'bar',
|
'a',
|
||||||
|
'a',
|
||||||
'a',
|
'a',
|
||||||
'b',
|
'b',
|
||||||
|
'b',
|
||||||
|
'b',
|
||||||
|
'b',
|
||||||
'c', // prevent redeclaring this, avoid assigning to this
|
'c', // prevent redeclaring this, avoid assigning to this
|
||||||
'undefined', // fun!
|
'foo',
|
||||||
'eval', // mmmm, ok, also fun!
|
'foo',
|
||||||
'NaN', // mmmm, ok, also fun!
|
'bar',
|
||||||
'Infinity', // the fun never ends!
|
'bar',
|
||||||
'arguments', // this one is just creepy
|
'undefined',
|
||||||
'Math', // since Math is assumed to be a non-constructor/function it may trip certain cases
|
'NaN',
|
||||||
|
'Infinity',
|
||||||
|
'arguments',
|
||||||
|
'Math',
|
||||||
'parseInt',
|
'parseInt',
|
||||||
'parseFloat',
|
];
|
||||||
'isNaN',
|
|
||||||
'isFinite',
|
|
||||||
'decodeURI',
|
|
||||||
'decodeURIComponent',
|
|
||||||
'encodeURI',
|
|
||||||
'encodeURIComponent',
|
|
||||||
'Object'];
|
|
||||||
var INITIAL_NAMES_LEN = VAR_NAMES.length;
|
var INITIAL_NAMES_LEN = VAR_NAMES.length;
|
||||||
|
|
||||||
var TYPEOF_OUTCOMES = [
|
var TYPEOF_OUTCOMES = [
|
||||||
@@ -307,6 +311,22 @@ function createFunctions(n, recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createParams() {
|
||||||
|
var params = [];
|
||||||
|
for (var n = rng(4); --n >= 0;) {
|
||||||
|
params.push(createVarName(MANDATORY));
|
||||||
|
}
|
||||||
|
return params.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
|
function createArgs() {
|
||||||
|
var args = [];
|
||||||
|
for (var n = rng(4); --n >= 0;) {
|
||||||
|
args.push(createValue());
|
||||||
|
}
|
||||||
|
return args.join(', ');
|
||||||
|
}
|
||||||
|
|
||||||
function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
||||||
if (--recurmax < 0) { return ';'; }
|
if (--recurmax < 0) { return ';'; }
|
||||||
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
|
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
|
||||||
@@ -317,17 +337,17 @@ function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
|||||||
var s = '';
|
var s = '';
|
||||||
if (rng(5) === 0) {
|
if (rng(5) === 0) {
|
||||||
// functions with functions. lower the recursion to prevent a mess.
|
// functions with functions. lower the recursion to prevent a mess.
|
||||||
s = 'function ' + name + '(' + createVarName(MANDATORY) + '){' + createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), NOT_GLOBAL, ANY_TYPE, canThrow, stmtDepth) + '}\n';
|
s = 'function ' + name + '(' + createParams() + '){' + createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), NOT_GLOBAL, ANY_TYPE, canThrow, stmtDepth) + '}\n';
|
||||||
} else {
|
} else {
|
||||||
// functions with statements
|
// functions with statements
|
||||||
s = 'function ' + name + '(' + createVarName(MANDATORY) + '){' + createStatements(3, recurmax, canThrow, CANNOT_THROW, CANNOT_CONTINUE, CAN_RETURN, stmtDepth) + '}\n';
|
s = 'function ' + name + '(' + createParams() + '){' + createStatements(3, recurmax, canThrow, CANNOT_THROW, CANNOT_CONTINUE, CAN_RETURN, stmtDepth) + '}\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
VAR_NAMES.length = namesLenBefore;
|
VAR_NAMES.length = namesLenBefore;
|
||||||
|
|
||||||
if (noDecl) s = '!' + s + '(' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ')';
|
if (noDecl) s = 'var ' + createVarName(MANDATORY) + ' = ' + s + '(' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ');';
|
||||||
// avoid "function statements" (decl inside statements)
|
// avoid "function statements" (decl inside statements)
|
||||||
else if (inGlobal || rng(10) > 0) s += name + '();'
|
else if (inGlobal || rng(10) > 0) s += 'var ' + createVarName(MANDATORY) + ' = ' + name + '(' + createArgs() + ');';
|
||||||
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
@@ -399,7 +419,8 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
|||||||
if (canBreak && rng(5) === 0) return 'break;';
|
if (canBreak && rng(5) === 0) return 'break;';
|
||||||
if (canContinue && rng(5) === 0) return 'continue;';
|
if (canContinue && rng(5) === 0) return 'continue;';
|
||||||
if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||||
return '/*3*/return;';
|
if (rng(3) == 0) return '/*3*/return;';
|
||||||
|
return '/*4*/return ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||||
case 2:
|
case 2:
|
||||||
// must wrap in curlies to prevent orphaned `else` statement
|
// must wrap in curlies to prevent orphaned `else` statement
|
||||||
if (canThrow && rng(5) === 0) return '{ throw ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + '}';
|
if (canThrow && rng(5) === 0) return '{ throw ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + '}';
|
||||||
@@ -464,42 +485,44 @@ function createSwitchParts(recurmax, n, canThrow, canBreak, canContinue, cannotR
|
|||||||
|
|
||||||
function createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
function createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
if (--recurmax < 0) {
|
if (--recurmax < 0) {
|
||||||
return '(c = 1 + c, ' + createNestedBinaryExpr(recurmax, noComma) + ')'; // note: should return a simple non-recursing expression value!
|
return '(c = 1 + c, ' + createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')'; // note: should return a simple non-recursing expression value!
|
||||||
}
|
}
|
||||||
// since `a` and `b` are our canaries we want them more frequently than other expressions (1/3rd chance of a canary)
|
// since `a` and `b` are our canaries we want them more frequently than other expressions (1/3rd chance of a canary)
|
||||||
var r = rng(6);
|
switch (rng(6)) {
|
||||||
if (r < 1) return 'a++ + ' + _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
case 0:
|
||||||
if (r < 2) return '(--b) + ' + _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
return '(a++ + (' + _createExpression(recurmax, noComma, stmtDepth, canThrow) + '))';
|
||||||
if (r < 3) return '(c = c + 1) + ' + _createExpression(recurmax, noComma, stmtDepth, canThrow); // c only gets incremented
|
case 1:
|
||||||
|
return '((--b) + (' + _createExpression(recurmax, noComma, stmtDepth, canThrow) + '))';
|
||||||
return _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
case 2:
|
||||||
|
return '((c = c + 1) + (' + _createExpression(recurmax, noComma, stmtDepth, canThrow) + '))'; // c only gets incremented
|
||||||
|
default:
|
||||||
|
return '(' + _createExpression(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
switch (rng(31)) {
|
var p = 0;
|
||||||
case 0:
|
switch (rng(_createExpression.N)) {
|
||||||
case 1:
|
case p++:
|
||||||
return createUnaryOp() + (rng(2) === 1 ? 'a' : 'b');
|
case p++:
|
||||||
case 2:
|
return createUnaryPrefix() + (rng(2) === 1 ? 'a' : 'b');
|
||||||
case 3:
|
case p++:
|
||||||
return 'a' + (rng(2) == 1 ? '++' : '--');
|
case p++:
|
||||||
case 4:
|
return (rng(2) === 1 ? 'a' : 'b') + createUnaryPostfix();
|
||||||
case 5:
|
case p++:
|
||||||
|
case p++:
|
||||||
// parens needed because assignments aren't valid unless they're the left-most op(s) in an expression
|
// parens needed because assignments aren't valid unless they're the left-most op(s) in an expression
|
||||||
return '(b ' + createAssignment() + ' a)';
|
return 'b ' + createAssignment() + ' a';
|
||||||
case 6:
|
case p++:
|
||||||
case 7:
|
case p++:
|
||||||
return rng(2) + ' === 1 ? a : b';
|
return rng(2) + ' === 1 ? a : b';
|
||||||
case 8:
|
case p++:
|
||||||
case 9:
|
case p++:
|
||||||
return createNestedBinaryExpr(recurmax, noComma) + createBinaryOp(noComma) + createExpression(recurmax, noComma, stmtDepth, canThrow);
|
|
||||||
case 10:
|
|
||||||
case 11:
|
|
||||||
return createValue();
|
return createValue();
|
||||||
case 12:
|
case p++:
|
||||||
return '(' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ')';
|
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||||
case 13:
|
case p++:
|
||||||
return createExpression(recurmax, noComma, stmtDepth, canThrow) + '?' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ':' + createExpression(recurmax, noComma, stmtDepth, canThrow);
|
return createExpression(recurmax, noComma, stmtDepth, canThrow) + '?' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ':' + createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||||
case 14:
|
case p++:
|
||||||
var nameLenBefore = VAR_NAMES.length;
|
var nameLenBefore = VAR_NAMES.length;
|
||||||
var name = createVarName(MAYBE); // note: this name is only accessible from _within_ the function. and immutable at that.
|
var name = createVarName(MAYBE); // note: this name is only accessible from _within_ the function. and immutable at that.
|
||||||
if (name === 'c') name = 'a';
|
if (name === 'c') name = 'a';
|
||||||
@@ -520,19 +543,18 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
}
|
}
|
||||||
VAR_NAMES.length = nameLenBefore;
|
VAR_NAMES.length = nameLenBefore;
|
||||||
return s;
|
return s;
|
||||||
case 15:
|
case p++:
|
||||||
case 16:
|
case p++:
|
||||||
return createTypeofExpr(recurmax, stmtDepth, canThrow);
|
return createTypeofExpr(recurmax, stmtDepth, canThrow);
|
||||||
case 17:
|
case p++:
|
||||||
// you could statically infer that this is just `Math`, regardless of the other expression
|
return [
|
||||||
// I don't think Uglify does this at this time...
|
'new function() {',
|
||||||
return ''+
|
rng(2) ? '' : createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ';',
|
||||||
'new function(){ \n' +
|
'return ' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ';',
|
||||||
(rng(2) === 1 ? createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + '\n' : '') +
|
'}'
|
||||||
'return Math;\n' +
|
].join('\n');
|
||||||
'}';
|
case p++:
|
||||||
case 18:
|
case p++:
|
||||||
case 19:
|
|
||||||
// more like a parser test but perhaps comment nodes mess up the analysis?
|
// more like a parser test but perhaps comment nodes mess up the analysis?
|
||||||
// note: parens not needed for post-fix (since that's the default when ambiguous)
|
// note: parens not needed for post-fix (since that's the default when ambiguous)
|
||||||
// for prefix ops we need parens to prevent accidental syntax errors.
|
// for prefix ops we need parens to prevent accidental syntax errors.
|
||||||
@@ -542,47 +564,56 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
case 1:
|
case 1:
|
||||||
return 'b/* ignore */--';
|
return 'b/* ignore */--';
|
||||||
case 2:
|
case 2:
|
||||||
return '(++/* ignore */a)';
|
return '++/* ignore */a';
|
||||||
case 3:
|
case 3:
|
||||||
return '(--/* ignore */b)';
|
return '--/* ignore */b';
|
||||||
case 4:
|
case 4:
|
||||||
// only groups that wrap a single variable return a "Reference", so this is still valid.
|
// only groups that wrap a single variable return a "Reference", so this is still valid.
|
||||||
// may just be a parser edge case that is invisible to uglify...
|
// may just be a parser edge case that is invisible to uglify...
|
||||||
return '(--(b))';
|
return '--(b)';
|
||||||
case 5:
|
case 5:
|
||||||
// classic 0.3-0.1 case; 1-0.1-0.1-0.1 is not 0.7 :)
|
// classic 0.3-0.1 case; 1-0.1-0.1-0.1 is not 0.7 :)
|
||||||
return 'b + 1-0.1-0.1-0.1';
|
return 'b + 1-0.1-0.1-0.1';
|
||||||
default:
|
default:
|
||||||
return '(--/* ignore */b)';
|
return '--/* ignore */b';
|
||||||
}
|
}
|
||||||
case 20:
|
case p++:
|
||||||
case 21:
|
case p++:
|
||||||
return createNestedBinaryExpr(recurmax, noComma);
|
return createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow);
|
||||||
case 22:
|
case p++:
|
||||||
|
case p++:
|
||||||
|
return createUnarySafePrefix() + '(' + createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
|
case p++:
|
||||||
return " ((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || a || 3).toString() ";
|
return " ((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || a || 3).toString() ";
|
||||||
case 23:
|
case p++:
|
||||||
return " /[abc4]/.test(((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || b || 5).toString()) ";
|
return " /[abc4]/.test(((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || b || 5).toString()) ";
|
||||||
case 24:
|
case p++:
|
||||||
return " ((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) +
|
return " ((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) +
|
||||||
") || " + rng(10) + ").toString()[" +
|
") || " + rng(10) + ").toString()[" +
|
||||||
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "] ";
|
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "] ";
|
||||||
case 25:
|
case p++:
|
||||||
return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow);
|
return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||||
case 26:
|
case p++:
|
||||||
return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow);
|
return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||||
case 27:
|
case p++:
|
||||||
return '(' + createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '[' +
|
return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '[' +
|
||||||
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]) ";
|
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
||||||
case 28:
|
case p++:
|
||||||
return '(' + createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '[' +
|
return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '[' +
|
||||||
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]) ";
|
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
||||||
case 29:
|
case p++:
|
||||||
return '(' + createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '.' +
|
return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '.' + getDotKey();
|
||||||
SAFE_KEYS[rng(SAFE_KEYS.length)] + ") ";
|
case p++:
|
||||||
case 30:
|
return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '.' + getDotKey();
|
||||||
return '(' + createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '.' +
|
case p++:
|
||||||
SAFE_KEYS[rng(SAFE_KEYS.length)] + ") ";
|
var name = getVarName();
|
||||||
|
return name + ' && ' + name + '[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
||||||
|
case p++:
|
||||||
|
var name = getVarName();
|
||||||
|
return name + ' && ' + name + '.' + getDotKey();
|
||||||
}
|
}
|
||||||
|
_createExpression.N = p;
|
||||||
|
return _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createArrayLiteral(recurmax, noComma, stmtDepth, canThrow) {
|
function createArrayLiteral(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
@@ -618,6 +649,10 @@ var KEYS = [
|
|||||||
"3",
|
"3",
|
||||||
].concat(SAFE_KEYS);
|
].concat(SAFE_KEYS);
|
||||||
|
|
||||||
|
function getDotKey() {
|
||||||
|
return SAFE_KEYS[rng(SAFE_KEYS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
function createObjectLiteral(recurmax, noComma, stmtDepth, canThrow) {
|
function createObjectLiteral(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
recurmax--;
|
recurmax--;
|
||||||
var obj = "({";
|
var obj = "({";
|
||||||
@@ -628,36 +663,52 @@ function createObjectLiteral(recurmax, noComma, stmtDepth, canThrow) {
|
|||||||
return obj + "})";
|
return obj + "})";
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNestedBinaryExpr(recurmax, noComma) {
|
function createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
recurmax = 3; // note that this generates 2^recurmax expression parts... make sure to cap it
|
recurmax = 3; // note that this generates 2^recurmax expression parts... make sure to cap it
|
||||||
return _createSimpleBinaryExpr(recurmax, noComma);
|
return _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow);
|
||||||
}
|
}
|
||||||
function _createSimpleBinaryExpr(recurmax, noComma) {
|
function _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
|
return '(' + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow)
|
||||||
|
+ createBinaryOp(noComma) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
|
}
|
||||||
|
function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||||
// intentionally generate more hardcore ops
|
// intentionally generate more hardcore ops
|
||||||
if (--recurmax < 0) return createValue();
|
if (--recurmax < 0) return createValue();
|
||||||
var r = rng(30);
|
switch (rng(30)) {
|
||||||
if (r === 0) return '(c = c + 1, ' + _createSimpleBinaryExpr(recurmax, noComma) + ')';
|
case 0:
|
||||||
var s = _createSimpleBinaryExpr(recurmax, noComma) + createBinaryOp(noComma) + _createSimpleBinaryExpr(recurmax, noComma);
|
return '(c = c + 1, ' + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
if (r === 1) {
|
case 1:
|
||||||
// try to get a generated name reachable from current scope. default to just `a`
|
return '(' + createUnarySafePrefix() + '(' + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + '))';
|
||||||
var assignee = VAR_NAMES[INITIAL_NAMES_LEN + rng(VAR_NAMES.length - INITIAL_NAMES_LEN)] || 'a';
|
case 2:
|
||||||
return '( ' + assignee + createAssignment() + s + ')';
|
var assignee = getVarName();
|
||||||
|
return '(' + assignee + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
|
case 3:
|
||||||
|
var assignee = getVarName();
|
||||||
|
var expr = '(' + assignee + '[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow)
|
||||||
|
+ ']' + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
|
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
||||||
|
case 4:
|
||||||
|
var assignee = getVarName();
|
||||||
|
var expr = '(' + assignee + '.' + getDotKey() + createAssignment()
|
||||||
|
+ _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||||
|
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
||||||
|
default:
|
||||||
|
return _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow);
|
||||||
}
|
}
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTypeofExpr(recurmax, stmtDepth, canThrow) {
|
function createTypeofExpr(recurmax, stmtDepth, canThrow) {
|
||||||
switch (rng(8)) {
|
switch (rng(8)) {
|
||||||
case 0:
|
case 0:
|
||||||
return 'typeof ' + createVarName(MANDATORY, DONT_STORE) + ' === "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '"';
|
return '(typeof ' + createVarName(MANDATORY, DONT_STORE) + ' === "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||||
case 1:
|
case 1:
|
||||||
return 'typeof ' + createVarName(MANDATORY, DONT_STORE) + ' !== "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '"';
|
return '(typeof ' + createVarName(MANDATORY, DONT_STORE) + ' !== "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||||
case 2:
|
case 2:
|
||||||
return 'typeof ' + createVarName(MANDATORY, DONT_STORE) + ' == "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '"';
|
return '(typeof ' + createVarName(MANDATORY, DONT_STORE) + ' == "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||||
case 3:
|
case 3:
|
||||||
return 'typeof ' + createVarName(MANDATORY, DONT_STORE) + ' != "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '"';
|
return '(typeof ' + createVarName(MANDATORY, DONT_STORE) + ' != "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||||
case 4:
|
case 4:
|
||||||
return 'typeof ' + createVarName(MANDATORY, DONT_STORE);
|
return '(typeof ' + createVarName(MANDATORY, DONT_STORE) + ')';
|
||||||
default:
|
default:
|
||||||
return '(typeof ' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ')';
|
return '(typeof ' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ')';
|
||||||
}
|
}
|
||||||
@@ -676,16 +727,31 @@ function createAssignment() {
|
|||||||
return ASSIGNMENTS[rng(ASSIGNMENTS.length)];
|
return ASSIGNMENTS[rng(ASSIGNMENTS.length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function createUnaryOp() {
|
function createUnarySafePrefix() {
|
||||||
return UNARY_OPS[rng(UNARY_OPS.length)];
|
return UNARY_SAFE[rng(UNARY_SAFE.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function createUnaryPrefix() {
|
||||||
|
return UNARY_PREFIX[rng(UNARY_PREFIX.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function createUnaryPostfix() {
|
||||||
|
return UNARY_POSTFIX[rng(UNARY_POSTFIX.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVarName() {
|
||||||
|
// try to get a generated name reachable from current scope. default to just `a`
|
||||||
|
return VAR_NAMES[INITIAL_NAMES_LEN + rng(VAR_NAMES.length - INITIAL_NAMES_LEN)] || 'a';
|
||||||
}
|
}
|
||||||
|
|
||||||
function createVarName(maybe, dontStore) {
|
function createVarName(maybe, dontStore) {
|
||||||
if (!maybe || rng(2) === 1) {
|
if (!maybe || rng(2)) {
|
||||||
var r = rng(VAR_NAMES.length);
|
var name = VAR_NAMES[rng(VAR_NAMES.length)];
|
||||||
var suffixed = rng(5) > 0;
|
var suffix = rng(3);
|
||||||
var name = VAR_NAMES[r] + (suffixed ? '_' + (++loops) : '');
|
if (suffix) {
|
||||||
if (!dontStore && suffixed) VAR_NAMES.push(name);
|
name += '_' + suffix;
|
||||||
|
if (!dontStore) VAR_NAMES.push(name);
|
||||||
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
|
|||||||
@@ -1,4 +1,21 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"compress": false,
|
||||||
|
"mangle": false,
|
||||||
|
"output": {
|
||||||
|
"beautify": true,
|
||||||
|
"bracketize": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"compress": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"compress": {
|
||||||
|
"warnings": false
|
||||||
|
},
|
||||||
|
"mangle": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"compress": {
|
"compress": {
|
||||||
"warnings": false
|
"warnings": false
|
||||||
@@ -13,24 +30,6 @@
|
|||||||
"toplevel": true
|
"toplevel": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"compress": {
|
|
||||||
"warnings": false
|
|
||||||
},
|
|
||||||
"mangle": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"compress": false,
|
|
||||||
"mangle": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"compress": false,
|
|
||||||
"mangle": false,
|
|
||||||
"output": {
|
|
||||||
"beautify": true,
|
|
||||||
"bracketize": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"compress": {
|
"compress": {
|
||||||
"keep_fargs": false,
|
"keep_fargs": false,
|
||||||
|
|||||||
Reference in New Issue
Block a user