aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/compress/yields.js589
-rw-r--r--test/mocha/awaits.js (renamed from test/mocha/async.js)0
-rw-r--r--test/mocha/yields.js82
-rw-r--r--test/reduce.js6
-rw-r--r--test/ufuzz/index.js133
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;
}