diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/compress/yields.js | 589 | ||||
-rw-r--r-- | test/mocha/awaits.js (renamed from test/mocha/async.js) | 0 | ||||
-rw-r--r-- | test/mocha/yields.js | 82 | ||||
-rw-r--r-- | test/reduce.js | 6 | ||||
-rw-r--r-- | test/ufuzz/index.js | 133 |
5 files changed, 786 insertions, 24 deletions
diff --git a/test/compress/yields.js b/test/compress/yields.js new file mode 100644 index 00000000..2c06a4ac --- /dev/null +++ b/test/compress/yields.js @@ -0,0 +1,589 @@ +binary: { + input: { + var a = function*() { + console.log(6 * (yield "PA" + "SS")); + }(); + console.log(a.next("FAIL").value); + console.log(a.next(7).done); + } + expect_exact: 'var a=function*(){console.log(6*(yield"PA"+"SS"))}();console.log(a.next("FAIL").value);console.log(a.next(7).done);' + expect_stdout: [ + "PASS", + "42", + "true", + ] + node_version: ">=4" +} + +empty_yield: { + input: { + var a = function*() { + yield; + console.log(yield); + yield + "FAIL 1"; + }(); + console.log(a.next("FAIL 2").value); + console.log(a.next("FAIL 3").value); + console.log(a.next("PASS").value); + console.log(a.next("FAIL 4").done); + } + expect_exact: 'var a=function*(){yield;console.log(yield);yield;"FAIL 1"}();console.log(a.next("FAIL 2").value);console.log(a.next("FAIL 3").value);console.log(a.next("PASS").value);console.log(a.next("FAIL 4").done);' + expect_stdout: [ + "undefined", + "undefined", + "PASS", + "undefined", + "true", + ] + node_version: ">=4" +} + +empty_yield_conditional: { + input: { + var a = function*() { + console.log((yield) ? yield : yield); + }(); + console.log(a.next("FAIL 1").value); + console.log(a.next("FAIL 2").value); + console.log(a.next("PASS").value); + console.log(a.next("FAIL 3").done); + } + expect_exact: 'var a=function*(){console.log((yield)?yield:yield)}();console.log(a.next("FAIL 1").value);console.log(a.next("FAIL 2").value);console.log(a.next("PASS").value);console.log(a.next("FAIL 3").done);' + expect_stdout: [ + "undefined", + "undefined", + "PASS", + "undefined", + "true", + ] + node_version: ">=4" +} + +nested_yield: { + input: { + console.log(function*() { + (yield* + f()) + function* f() { + return "FAIL"; + } + yield* + f(); + yield *f(); + }().next().value || "PASS"); + } + expect_exact: 'console.log(function*(){yield*f();function*f(){return"FAIL"}yield*f();yield*f()}().next().value||"PASS");' + expect_stdout: "PASS" + node_version: ">=4" +} + +pause_resume: { + input: { + function* f() { + console.log(yield "PASS"); + } + var a = f(); + console.log(a.next("FAIL").value); + console.log(a.next(42).done); + } + expect_exact: 'function*f(){console.log(yield"PASS")}var a=f();console.log(a.next("FAIL").value);console.log(a.next(42).done);' + expect_stdout: [ + "PASS", + "42", + "true", + ] + node_version: ">=4" +} + +collapse_vars_1: { + options = { + collapse_vars: true, + } + input: { + var a = "FAIL"; + (function*() { + a = "PASS"; + yield 42; + return "PASS"; + })().next(); + console.log(a); + } + expect: { + var a = "FAIL"; + (function*() { + a = "PASS"; + yield 42; + return "PASS"; + })().next(); + console.log(a); + } + expect_stdout: "PASS" + node_version: ">=4" +} + +collapse_vars_2: { + options = { + collapse_vars: true, + } + input: { + var a = "FAIL"; + (function*() { + yield (a = "PASS"); + return "PASS"; + })().next(); + console.log(a); + } + expect: { + var a = "FAIL"; + (function*() { + yield (a = "PASS"); + return "PASS"; + })().next(); + console.log(a); + } + expect_stdout: "PASS" + node_version: ">=4" +} + +collapse_vars_3: { + options = { + collapse_vars: true, + } + input: { + var a = "FAIL"; + (function*() { + yield (a = "PASS", 42); + return "PASS"; + })().next(); + console.log(a); + } + expect: { + var a = "FAIL"; + (function*() { + yield (a = "PASS", 42); + return "PASS"; + })().next(); + console.log(a); + } + expect_stdout: "PASS" + node_version: ">=4" +} + +collapse_vars_4: { + options = { + collapse_vars: true, + unused: true, + } + input: { + var a = "FAIL"; + var b = function*(c) { + return c; + }(a = "PASS"); + console.log(a, b.next().done); + } + expect: { + var a = "FAIL"; + var b = function*(c) { + return c; + }(a = "PASS"); + console.log(a, b.next().done); + } + expect_stdout: "PASS true" + node_version: ">=4" +} + +collapse_property_lambda: { + options = { + collapse_vars: true, + pure_getters: "strict", + } + input: { + console.log(function* f() { + f.g = () => 42; + return f.g(); + }().next().value); + } + expect: { + console.log(function* f() { + return (f.g = () => 42)(); + }().next().value); + } + expect_stdout: "42" + node_version: ">=4" +} + +evaluate: { + options = { + evaluate: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + var a = function*() {}(); + console.log(typeof a); + } + expect: { + var a = function*() {}(); + console.log(typeof a); + } + expect_stdout: "object" + node_version: ">=4" +} + +functions: { + options = { + functions: true, + reduce_vars: true, + unused: true, + } + input: { + !function*() { + var a = function* a() { + return a && "a"; + }; + var b = function* x() { + return !!x; + }; + var c = function*(c) { + return c; + }; + if (yield* c(yield* b(yield* a()))) { + var d = function*() {}; + var e = function* y() { + return typeof y; + }; + var f = function*(f) { + return f; + }; + console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f); + } + }().next(); + } + expect: { + !function*() { + function* a() { + return a && "a"; + } + function* b() { + return !!b; + } + var c = function*(c) { + return c; + }; + if (yield* c(yield* b(yield* a()))) { + function* d() {} + function* e() { + return typeof e; + } + var f = function*(f) { + return f; + }; + console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f); + } + }().next(); + } + expect_stdout: "a true 42 function function function" + node_version: ">=4" +} + +functions_use_strict: { + options = { + functions: true, + reduce_vars: true, + unused: true, + } + input: { + "use strict"; + !function*() { + var a = function* a() { + return a && "a"; + }; + var b = function* x() { + return !!x; + }; + var c = function*(c) { + return c; + }; + if (yield* c(yield* b(yield* a()))) { + var d = function*() {}; + var e = function* y() { + return typeof y; + }; + var f = function*(f) { + return f; + }; + console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f); + } + }().next(); + } + expect: { + "use strict"; + !function*() { + function* a() { + return a && "a"; + } + function* b() { + return !!b; + } + var c = function*(c) { + return c; + }; + if (yield* c(yield* b(yield* a()))) { + var d = function*() {}; + var e = function* y() { + return typeof y; + }; + var f = function*(f) { + return f; + }; + console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f); + } + }().next(); + } + expect_stdout: "a true 42 function function function" + node_version: ">=4" +} + +negate_iife: { + options = { + negate_iife: true, + side_effects: true, + } + input: { + (function*(a) { + console.log(a); + })("PASS").next(); + } + expect: { + !function*(a) { + console.log(a); + }("PASS").next(); + } + expect_stdout: "PASS" + node_version: ">=4" +} + +reduce_iife_1: { + options = { + reduce_vars: true, + unused: true, + } + input: { + console.log(function*(a) { + yield a; + }(42).next().value); + } + expect: { + console.log(function*(a) { + yield 42; + }().next().value); + } + expect_stdout: "42" + node_version: ">=4" +} + +reduce_iife_2: { + options = { + evaluate: true, + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + var a = "PASS"; + (function*() { + a = "FAIL"; + })(); + console.log(a); + } + expect: { + var a = "PASS"; + (function*() { + a = "FAIL"; + })(); + console.log(a); + } + expect_stdout: "PASS" + node_version: ">=4" +} + +reduce_single_use_defun: { + options = { + reduce_vars: true, + toplevel: true, + unused: true, + } + input: { + function* f(a) { + console.log(a); + } + f("PASS").next(); + } + expect: { + (function*(a) { + console.log(a); + })("PASS").next(); + } + expect_stdout: "PASS" + node_version: ">=4" +} + +reduce_tagged: { + options = { + reduce_funcs: true, + reduce_vars: true, + unused: true, + } + input: { + function* f() { + function g() { + h`foo`; + } + g(); + function h(s) { + console.log(s[0]); + } + h([ "bar" ]); + } + f().next(); + } + expect: { + function* f() { + (function() { + h`foo`; + })(); + function h(s) { + console.log(s[0]); + } + h([ "bar" ]); + } + f().next(); + } + expect_stdout: [ + "foo", + "bar", + ] + node_version: ">=4" +} + +reduce_tagged_async: { + options = { + reduce_funcs: true, + reduce_vars: true, + unused: true, + } + input: { + async function* f() { + function g() { + h`foo`; + } + g(); + function h(s) { + console.log(s[0]); + } + h([ "bar" ]); + } + f().next(); + } + expect: { + async function* f() { + (function() { + h`foo`; + })(); + function h(s) { + console.log(s[0]); + } + h([ "bar" ]); + } + f().next(); + } + expect_stdout: [ + "foo", + "bar", + ] + node_version: ">=10" +} + +lift_sequence: { + options = { + sequences: true, + yields: true, + } + input: { + console.log(function*() { + yield (console, "PASS"); + }().next().value); + } + expect: { + console.log(function*() { + console, yield "PASS"; + }().next().value); + } + expect_stdout: "PASS" + node_version: ">=4" +} + +inline_nested_yield: { + options = { + inline: true, + sequences: true, + yields: true, + } + input: { + var a = function*() { + yield* function*() { + yield "foo"; + return "FAIL"; + }(); + }(), b; + do { + b = a.next(); + console.log(b.value); + } while (!b.done); + } + expect: { + var a = function*() { + yield "foo", + "FAIL"; + }(), b; + do { + b = a.next(), + console.log(b.value); + } while (!b.done); + } + expect_stdout: [ + "foo", + "undefined", + ] + node_version: ">=4" +} + +issue_4618: { + options = { + functions: true, + reduce_vars: true, + unused: true, + } + input: { + console.log(typeof function() { + var yield = function* f() { + console || f(); + }; + console.log; + return yield; + }()); + } + expect: { + console.log(typeof function() { + var yield = function* f() { + console || f(); + }; + console.log; + return yield; + }()); + } + expect_stdout: "function" + node_version: ">=4" +} diff --git a/test/mocha/async.js b/test/mocha/awaits.js index d4e96609..d4e96609 100644 --- a/test/mocha/async.js +++ b/test/mocha/awaits.js diff --git a/test/mocha/yields.js b/test/mocha/yields.js new file mode 100644 index 00000000..d995d61d --- /dev/null +++ b/test/mocha/yields.js @@ -0,0 +1,82 @@ +var assert = require("assert"); +var UglifyJS = require("../node"); + +describe("generator", function() { + it("Should reject `yield` as symbol name within generator functions only", function() { + [ + "function yield() {}", + "function(yield) {}", + "function() { yield:{} }", + "function() { var yield; }", + "function() { function yield() {} }", + "function() { try {} catch (yield) {} }", + ].forEach(function(code) { + var ast = UglifyJS.parse("(" + code + ")();"); + assert.strictEqual(ast.TYPE, "Toplevel"); + assert.strictEqual(ast.body.length, 1); + assert.strictEqual(ast.body[0].TYPE, "SimpleStatement"); + assert.strictEqual(ast.body[0].body.TYPE, "Call"); + assert.strictEqual(ast.body[0].body.expression.TYPE, "Function"); + assert.throws(function() { + UglifyJS.parse("(" + code.replace(/^function/, "function*") + ")();"); + }, function(e) { + return e instanceof UglifyJS.JS_Parse_Error; + }, code); + }); + }); + it("Should reject `yield` expression outside of generator functions", function() { + [ + "yield 42;", + "function f() { yield 42; }", + "function* f() { function g() { yield 42; } }", + ].forEach(function(code) { + assert.throws(function() { + UglifyJS.parse(code); + }, function(e) { + return e instanceof UglifyJS.JS_Parse_Error; + }, code); + }); + }); + it("Should reject `yield` expression directly on computed key of function argument", function() { + [ + "function f({ [yield 42]: a }) {}", + "function* f({ [yield 42]: a }) {}", + ].forEach(function(code) { + assert.throws(function() { + UglifyJS.parse(code); + }, function(e) { + return e instanceof UglifyJS.JS_Parse_Error; + }, code); + }); + }); + it("Should accept `yield` expression nested within computed key of function argument", function() { + [ + "function f({ [function*() { yield 42; }()]: a }) {}", + "function* f({ [function*() { yield 42; }()]: a }) {}", + ].forEach(function(code) { + var ast = UglifyJS.parse(code); + assert.strictEqual(ast.TYPE, "Toplevel"); + assert.strictEqual(ast.body.length, 1); + assert.strictEqual(ast.body[0].argnames.length, 1); + assert.strictEqual(ast.body[0].argnames[0].TYPE, "DestructuredObject"); + }); + }); + it("Should reject `yield*` without an expression", function() { + [ + "yield*", + "yield*;", + "yield*,", + "(yield*)", + "[ yield* ]", + "42[yield*]", + "yield* && 42", + ].forEach(function(code) { + code = "function* f() { " + code + " }"; + assert.throws(function() { + UglifyJS.parse(code); + }, function(e) { + return e instanceof UglifyJS.JS_Parse_Error; + }, code); + }); + }); +}); diff --git a/test/reduce.js b/test/reduce.js index 9d5f053c..5f192aca 100644 --- a/test/reduce.js +++ b/test/reduce.js @@ -666,11 +666,7 @@ function is_timed_out(result) { } function is_statement(node) { - return node instanceof U.AST_Statement - && !(node instanceof U.AST_Arrow - || node instanceof U.AST_AsyncArrow - || node instanceof U.AST_AsyncFunction - || node instanceof U.AST_Function); + return node instanceof U.AST_Statement && !(node instanceof U.AST_LambdaExpression); } function merge_sequence(array, node) { diff --git a/test/ufuzz/index.js b/test/ufuzz/index.js index 5256ec63..58228bdb 100644 --- a/test/ufuzz/index.js +++ b/test/ufuzz/index.js @@ -134,6 +134,7 @@ var SUPPORT = function(matrix) { }({ arrow: "a => 0;", async: "async function f(){}", + async_generator: "async function* f(){}", bigint: "42n", catch_omit_var: "try {} catch {}", computed_key: "({[0]: 0});", @@ -141,6 +142,7 @@ var SUPPORT = function(matrix) { default_value: "[ a = 0 ] = [];", destructuring: "[] = [];", exponentiation: "0 ** 0", + generator: "function* f(){}", let: "let a;", rest: "var [...a] = [];", rest_object: "var {...a} = {};", @@ -349,6 +351,7 @@ var avoid_vars = []; var block_vars = []; var unique_vars = []; var async = false; +var generator = false; var loops = 0; var funcs = 0; var called = Object.create(null); @@ -368,6 +371,7 @@ function createTopLevelCode() { block_vars.length = 0; unique_vars.length = 0; async = false; + generator = false; loops = 0; funcs = 0; called = Object.create(null); @@ -395,9 +399,11 @@ function addTrailingComma(list) { return SUPPORT.trailing_comma && list && rng(20) == 0 ? list + "," : list; } -function createParams(was_async, noDuplicate) { +function createParams(was_async, was_generator, noDuplicate) { var save_async = async; if (was_async) async = true; + var save_generator = generator; + if (was_generator) generator = true; var len = unique_vars.length; var params = []; for (var n = rng(4); --n >= 0;) { @@ -406,6 +412,7 @@ function createParams(was_async, noDuplicate) { params.push(name); } unique_vars.length = len; + generator = save_generator; async = save_async; return addTrailingComma(params.join(", ")); } @@ -434,7 +441,7 @@ function createArgs(recurmax, stmtDepth, canThrow, noTemplate) { return "(" + addTrailingComma(args.join(", ")) + ")"; } -function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was_async) { +function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was_async, was_generator) { var avoid = []; var len = unique_vars.length; var pairs = createPairs(recurmax, !nameLenBefore); @@ -476,9 +483,18 @@ function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was async = false; if (save_async || was_async) addAvoidVar("await"); } + var save_generator = generator; + if (was_generator != null) { + generator = false; + if (save_generator || was_generator) addAvoidVar("yield"); + } avoid.forEach(addAvoidVar); var save_vars = nameLenBefore && VAR_NAMES.splice(nameLenBefore); if (nameFn) nameFn(); + if (was_generator != null) { + generator = was_generator; + if (save_generator || was_generator) removeAvoidVar("yield"); + } if (was_async != null) { async = was_async; if (save_async || was_async) removeAvoidVar("await"); @@ -486,6 +502,7 @@ function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was if (valueFn) valueFn(); if (save_vars) [].push.apply(VAR_NAMES, save_vars); avoid.forEach(removeAvoidVar); + generator = save_generator; async = save_async; } @@ -509,7 +526,10 @@ function createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was unique_vars.push("a", "b", "c", "undefined", "NaN", "Infinity"); var save_async = async; if (was_async) async = true; + var save_generator = generator; + if (was_generator) generator = true; var name = createVarName(MANDATORY); + generator = save_generator; async = save_async; unique_vars.length -= 6; avoid.push(name); @@ -707,7 +727,25 @@ function mayCreateBlockVariables(recurmax, stmtDepth, canThrow, fn) { } function makeFunction(name) { - return (async ? "async function " : "function ") + name; + if (generator) { + name = "function* " + name; + } else { + name = "function " + name; + } + if (async) name = "async " + name; + return name; +} + +function invokeGenerator(was_generator) { + if (generator && !was_generator) switch (rng(4)) { + case 0: + return ".next()"; + case 1: + return ".next().done"; + case 2: + return ".next().value"; + } + return ""; } function createFunction(recurmax, allowDefun, canThrow, stmtDepth) { @@ -718,6 +756,15 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) { var nameLenBefore = VAR_NAMES.length; var save_async = async; async = SUPPORT.async && rng(50) == 0; + var save_generator = generator; + generator = SUPPORT.generator && rng(50) == 0; + if (async && generator && !SUPPORT.async_generator) { + if (rng(2)) { + async = false; + } else { + generator = false; + } + } createBlockVariables(recurmax, stmtDepth, canThrow, function(defns) { if (allowDefun || rng(5) > 0) { name = "f" + funcs++; @@ -729,12 +776,12 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) { var params; if (SUPPORT.destructuring && (!allowDefun || !(name in called)) && rng(2)) { called[name] = false; - var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, save_async); + var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, save_async, save_generator); params = pairs.names.join(", "); if (!pairs.has_rest) params = addTrailingComma(params); args = "(" + addTrailingComma(pairs.values.join(", ")) + ")"; } else { - params = createParams(save_async); + params = createParams(save_async, save_generator); } s.push(makeFunction(name) + "(" + params + "){", strictMode()); s.push(defns()); @@ -748,6 +795,8 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) { s.push("}", ""); s = filterDirective(s).join("\n"); }); + var call_next = invokeGenerator(save_generator); + generator = save_generator; async = save_async; VAR_NAMES.length = nameLenBefore; @@ -755,9 +804,11 @@ function createFunction(recurmax, allowDefun, canThrow, stmtDepth) { // avoid "function statements" (decl inside statements) s = "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 += args || createArgs(recurmax, stmtDepth, canThrow); + s += call_next; } return s + ";"; @@ -1019,7 +1070,9 @@ function createExpression(recurmax, noComma, stmtDepth, canThrow) { return "((c = c + 1) + (" + _createExpression(recurmax, noComma, stmtDepth, canThrow) + "))"; // c only gets incremented default: var expr = "(" + _createExpression(recurmax, noComma, stmtDepth, canThrow) + ")"; - return async && rng(50) == 0 ? "(await" + expr + ")" : expr; + if (async && rng(50) == 0) return "(await" + expr + ")"; + if (generator && rng(50) == 0) return "(yield" + (canThrow && rng(20) == 0 ? "*" : "") + expr + ")"; + return expr; } } @@ -1027,6 +1080,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { var p = 0; switch (rng(_createExpression.N)) { case p++: + if (generator && rng(50) == 0) return "yield"; case p++: return createUnaryPrefix() + (rng(2) ? "a" : "b"); case p++: @@ -1082,25 +1136,34 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { var nameLenBefore = VAR_NAMES.length; var save_async = async; async = SUPPORT.async && rng(50) == 0; + var save_generator = generator; + generator = SUPPORT.generator && rng(50) == 0; + if (async && generator && !SUPPORT.async_generator) { + if (rng(2)) { + async = false; + } else { + generator = false; + } + } unique_vars.push("c"); var name = createVarName(MAYBE); // note: this name is only accessible from _within_ the function. and immutable at that. unique_vars.pop(); var s = []; switch (rng(5)) { case 0: - if (SUPPORT.arrow && !name && rng(2)) { + if (SUPPORT.arrow && !name && !generator && rng(2)) { var args, suffix; (rng(2) ? createBlockVariables : function() { arguments[3](); })(recurmax, stmtDepth, canThrow, function(defns) { var params; if (SUPPORT.destructuring && rng(2)) { - var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, save_async); + var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, save_async, save_generator); params = pairs.names.join(", "); if (!pairs.has_rest) params = addTrailingComma(params); args = "(" + addTrailingComma(pairs.values.join(", ")) + ")"; } else { - params = createParams(save_async, NO_DUPLICATE); + params = createParams(save_async, save_generator, NO_DUPLICATE); } params = (async ? "async (" : "(") + params + ") => "; if (defns) { @@ -1127,6 +1190,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { suffix = ")"; } }); + generator = save_generator; async = save_async; VAR_NAMES.length = nameLenBefore; if (!args && rng(2)) args = createArgs(recurmax, stmtDepth, canThrow); @@ -1137,7 +1201,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { "(" + makeFunction(name) + "(){", strictMode(), createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), - rng(2) ? "})" : "})()" + rng(2) ? "})" : "})()" + invokeGenerator(save_generator) ); } break; @@ -1146,7 +1210,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { "+" + makeFunction(name) + "(){", strictMode(), createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), - "}()" + "}()" + invokeGenerator(save_generator) ); break; case 2: @@ -1154,7 +1218,7 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { "!" + makeFunction(name) + "(){", strictMode(), createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), - "}()" + "}()" + invokeGenerator(save_generator) ); break; case 3: @@ -1162,15 +1226,16 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { "void " + makeFunction(name) + "(){", strictMode(), createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), - "}()" + "}()" + invokeGenerator(save_generator) ); break; default: async = false; + generator = false; var instantiate = rng(4) ? "new " : ""; createBlockVariables(recurmax, stmtDepth, canThrow, function(defns) { s.push( - instantiate + "function " + name + "(" + createParams(save_async) + "){", + instantiate + "function " + name + "(" + createParams(save_async, save_generator) + "){", strictMode(), defns() ); @@ -1180,11 +1245,13 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { } s.push(_createStatements(rng(5) + 1, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth)); }); + generator = save_generator; async = save_async; VAR_NAMES.length = nameLenBefore; s.push(rng(2) ? "}" : "}" + createArgs(recurmax, stmtDepth, canThrow, instantiate)); break; } + generator = save_generator; async = save_async; VAR_NAMES.length = nameLenBefore; return filterDirective(s).join("\n"); @@ -1328,8 +1395,6 @@ function createTemplateLiteral(recurmax, stmtDepth, canThrow) { } var SAFE_KEYS = [ - "length", - "foo", "a", "b", "c", @@ -1337,7 +1402,13 @@ var SAFE_KEYS = [ "null", "NaN", "Infinity", + "done", + "foo", "in", + "length", + "next", + "then", + "value", "var", ]; var KEYS = [ @@ -1367,12 +1438,14 @@ function createObjectKey(recurmax, stmtDepth, canThrow) { function createObjectFunction(recurmax, stmtDepth, canThrow) { var nameLenBefore = VAR_NAMES.length; var save_async = async; + var save_generator = generator; var s; var name = createObjectKey(recurmax, stmtDepth, canThrow); var fn; switch (rng(SUPPORT.computed_key ? 3 : 2)) { case 0: async = false; + generator = false; fn = function(defns) { s = [ "get " + name + "(){", @@ -1390,6 +1463,7 @@ function createObjectFunction(recurmax, stmtDepth, canThrow) { prop = getDotKey(); } while (name == prop); async = false; + generator = false; fn = function(defns) { s = [ "set " + name + "(" + createVarName(MANDATORY) + "){", @@ -1403,9 +1477,19 @@ function createObjectFunction(recurmax, stmtDepth, canThrow) { break; default: async = SUPPORT.async && rng(50) == 0; + generator = SUPPORT.generator && rng(50) == 0; + if (async && generator && !SUPPORT.async_generator) { + if (rng(2)) { + async = false; + } else { + generator = false; + } + } fn = function(defns) { + if (generator) name = "*" + name; + if (async) name = "async "+ name; s = [ - (async ? "async " : "") + name + "(" + createParams(save_async, NO_DUPLICATE) + "){", + name + "(" + createParams(save_async, save_generator, NO_DUPLICATE) + "){", strictMode(), defns(), _createStatements(3, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), @@ -1415,6 +1499,7 @@ function createObjectFunction(recurmax, stmtDepth, canThrow) { break; } createBlockVariables(recurmax, stmtDepth, canThrow, fn); + generator = save_generator; async = save_async; VAR_NAMES.length = nameLenBefore; return filterDirective(s).join("\n"); @@ -1563,8 +1648,11 @@ function createTypeofExpr(recurmax, stmtDepth, canThrow) { function createVar() { var save_async = async; + var save_generator = generator; if (!async && avoid_vars.indexOf("await") >= 0) async = true; + if (!generator && avoid_vars.indexOf("yield") >= 0) generator = true; var name = createVarName(MANDATORY, DONT_STORE); + generator = save_generator; async = save_async; return name; } @@ -1613,7 +1701,11 @@ function getVarName(noConst) { do { if (--tries < 0) return "a"; name = VAR_NAMES[INITIAL_NAMES_LEN + rng(VAR_NAMES.length - INITIAL_NAMES_LEN)]; - } while (!name || avoid_vars.indexOf(name) >= 0 || noConst && block_vars.indexOf(name) >= 0 || async && name == "await"); + } while (!name + || avoid_vars.indexOf(name) >= 0 + || noConst && block_vars.indexOf(name) >= 0 + || async && name == "await" + || generator && name == "yield"); return name; } @@ -1625,7 +1717,10 @@ function createVarName(maybe, dontStore) { name = VAR_NAMES[rng(VAR_NAMES.length)]; if (--tries < 0) suffix++; if (suffix) name += "_" + suffix; - } while (unique_vars.indexOf(name) >= 0 || block_vars.indexOf(name) >= 0 || async && name == "await"); + } while (unique_vars.indexOf(name) >= 0 + || block_vars.indexOf(name) >= 0 + || async && name == "await" + || generator && name == "yield"); if (!dontStore) VAR_NAMES.push(name); return name; } |