summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/generators
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/generators')
-rw-r--r--js/src/jit-test/tests/generators/bug1098947.js11
-rw-r--r--js/src/jit-test/tests/generators/bug1151326.js16
-rw-r--r--js/src/jit-test/tests/generators/bug908920.js9
-rw-r--r--js/src/jit-test/tests/generators/bug931414.js11
-rw-r--r--js/src/jit-test/tests/generators/closing-osr.js24
-rw-r--r--js/src/jit-test/tests/generators/es6-syntax.js34
-rw-r--r--js/src/jit-test/tests/generators/next-on-finished.js6
-rw-r--r--js/src/jit-test/tests/generators/return-break-continue.js66
-rw-r--r--js/src/jit-test/tests/generators/return.js181
-rw-r--r--js/src/jit-test/tests/generators/throw-closes.js63
-rw-r--r--js/src/jit-test/tests/generators/throw-on-finished.js7
-rw-r--r--js/src/jit-test/tests/generators/wrappers.js37
-rw-r--r--js/src/jit-test/tests/generators/yield-in-finally.js178
-rw-r--r--js/src/jit-test/tests/generators/yield-regexp.js41
-rw-r--r--js/src/jit-test/tests/generators/yield-yield.js12
15 files changed, 696 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/generators/bug1098947.js b/js/src/jit-test/tests/generators/bug1098947.js
new file mode 100644
index 000000000..c84ccd8d7
--- /dev/null
+++ b/js/src/jit-test/tests/generators/bug1098947.js
@@ -0,0 +1,11 @@
+function f() {
+ try {
+ let foo = 3;
+ for (var i=0; i<50; i++)
+ yield i + foo;
+ } catch(e) {}
+}
+var it = f();
+for (var i=0; i<40; i++)
+ it.next();
+it.close();
diff --git a/js/src/jit-test/tests/generators/bug1151326.js b/js/src/jit-test/tests/generators/bug1151326.js
new file mode 100644
index 000000000..17120fbf9
--- /dev/null
+++ b/js/src/jit-test/tests/generators/bug1151326.js
@@ -0,0 +1,16 @@
+// |jit-test| error: closing generator
+var finally3;
+function gen() {
+ try {
+ try {
+ yield 1;
+ } finally {
+ finally3();
+ }
+ } catch (e) {
+ yield finally3 === parseInt;
+ }
+}
+iter = gen();
+iter.next();
+iter.close();
diff --git a/js/src/jit-test/tests/generators/bug908920.js b/js/src/jit-test/tests/generators/bug908920.js
new file mode 100644
index 000000000..4cb781b57
--- /dev/null
+++ b/js/src/jit-test/tests/generators/bug908920.js
@@ -0,0 +1,9 @@
+if (typeof schedulegc != 'undefined') {
+ Function("\
+ x = (function() { yield })();\
+ new Set(x);\
+ schedulegc(1);\
+ print( /x/ );\
+ for (p in x) {}\
+ ")();
+}
diff --git a/js/src/jit-test/tests/generators/bug931414.js b/js/src/jit-test/tests/generators/bug931414.js
new file mode 100644
index 000000000..df1f24d09
--- /dev/null
+++ b/js/src/jit-test/tests/generators/bug931414.js
@@ -0,0 +1,11 @@
+// |jit-test| error: TypeError
+
+load(libdir + "iteration.js");
+
+function iterable() {
+ var iterable = {};
+ iterable[Symbol.iterator] = () => ({next: () => void 0});
+ return iterable;
+}
+
+(function*(){yield*iterable()}()).next();
diff --git a/js/src/jit-test/tests/generators/closing-osr.js b/js/src/jit-test/tests/generators/closing-osr.js
new file mode 100644
index 000000000..2bb609993
--- /dev/null
+++ b/js/src/jit-test/tests/generators/closing-osr.js
@@ -0,0 +1,24 @@
+// OSR into a |finally| block while closing a legacy generator should work.
+var log = "";
+function f() {
+ try {
+ try {
+ log += "a";
+ yield 2;
+ log += "b";
+ yield 3;
+ } finally {
+ log += "c";
+ for (var i=0; i<20; i++) {};
+ log += "d";
+ }
+ } catch(e) {
+ log += "e";
+ }
+ log += "f";
+}
+
+var it = f();
+assertEq(it.next(), 2);
+it.close();
+assertEq(log, "acd");
diff --git a/js/src/jit-test/tests/generators/es6-syntax.js b/js/src/jit-test/tests/generators/es6-syntax.js
new file mode 100644
index 000000000..e805a0b62
--- /dev/null
+++ b/js/src/jit-test/tests/generators/es6-syntax.js
@@ -0,0 +1,34 @@
+// Test interactions between ES6 generators and not-yet-standard
+// features.
+
+function assertSyntaxError(str) {
+ var msg;
+ var evil = eval;
+ try {
+ // Non-direct eval.
+ evil(str);
+ } catch (exc) {
+ if (exc instanceof SyntaxError)
+ return;
+ msg = "Assertion failed: expected SyntaxError, got " + exc;
+ }
+ if (msg === undefined)
+ msg = "Assertion failed: expected SyntaxError, but no exception thrown";
+ throw new Error(msg + " - " + str);
+}
+
+// Destructuring binding.
+assertSyntaxError("function* f(x = yield) {}");
+assertSyntaxError("function* f(x = yield 17) {}");
+assertSyntaxError("function* f([yield]) {}");
+assertSyntaxError("function* f({ yield }) {}");
+assertSyntaxError("function* f(...yield) {}");
+
+// For each.
+assertSyntaxError("for yield");
+assertSyntaxError("for yield (;;) {}");
+assertSyntaxError("for yield (x of y) {}");
+assertSyntaxError("for yield (var i in o) {}");
+
+// Expression bodies.
+assertSyntaxError("function* f() yield 7");
diff --git a/js/src/jit-test/tests/generators/next-on-finished.js b/js/src/jit-test/tests/generators/next-on-finished.js
new file mode 100644
index 000000000..66c25a13f
--- /dev/null
+++ b/js/src/jit-test/tests/generators/next-on-finished.js
@@ -0,0 +1,6 @@
+function*g(){ };
+o = g();
+o.next();
+result = o.next();
+assertEq(result.done, true);
+assertEq(o.value, undefined);
diff --git a/js/src/jit-test/tests/generators/return-break-continue.js b/js/src/jit-test/tests/generators/return-break-continue.js
new file mode 100644
index 000000000..1d3070e28
--- /dev/null
+++ b/js/src/jit-test/tests/generators/return-break-continue.js
@@ -0,0 +1,66 @@
+load(libdir + "iteration.js");
+
+// break in finally.
+function *f1() {
+ L: try {
+ yield 1;
+ } finally {
+ break L;
+ }
+ return 2;
+}
+it = f1();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(4), 2, true);
+assertIteratorDone(it);
+
+// continue in finally, followed by return.
+function *f2() {
+ do try {
+ yield 1;
+ } catch (e) {
+ assertEq(0, 1);
+ } finally {
+ continue;
+ } while (0);
+ return 2;
+}
+it = f2();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(4), 2, true);
+assertIteratorDone(it);
+
+// continue in finally, followed by yield.
+function *f3() {
+ do try {
+ yield 1;
+ } catch (e) {
+ assertEq(0, 1);
+ } finally {
+ continue;
+ } while (0);
+ yield 2;
+}
+it = f3();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(4), 2, false);
+assertIteratorDone(it);
+
+// continue in finally.
+function *f4() {
+ var i = 0;
+ while (true) {
+ try {
+ yield i++;
+ } finally {
+ if (i < 3)
+ continue;
+ }
+ }
+}
+it = f4();
+assertIteratorNext(it, 0);
+assertIteratorResult(it.return(-1), 1, false);
+assertIteratorResult(it.return(-2), 2, false);
+assertIteratorResult(it.return(-3), -3, true);
+assertIteratorDone(it);
diff --git a/js/src/jit-test/tests/generators/return.js b/js/src/jit-test/tests/generators/return.js
new file mode 100644
index 000000000..b71b38921
--- /dev/null
+++ b/js/src/jit-test/tests/generators/return.js
@@ -0,0 +1,181 @@
+// |jit-test| error:done
+
+load(libdir + "iteration.js");
+
+function *f1() {
+ yield 1;
+ yield 2;
+}
+
+// Return after initial yield.
+var it = f1();
+assertIteratorResult(it.return(3), 3, true);
+assertIteratorResult(it.return(Math), Math, true);
+assertIteratorResult(it.return(), undefined, true);
+assertIteratorDone(it);
+
+// Return after other yield.
+it = f1();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(null), null, true);
+assertIteratorDone(it);
+
+// Finally blocks should run and can override the return value.
+function *f2() {
+ try {
+ yield 1;
+ yield 2;
+ } finally {
+ return 9;
+ }
+}
+it = f2();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(3), 9, true);
+assertIteratorDone(it);
+
+// Yield in finally block can override the return, but we should still
+// return the correct value after that.
+function *f3() {
+ try {
+ try {
+ yield 1;
+ yield 2;
+ } finally {
+ yield 3;
+ }
+ } finally {
+ yield 4;
+ }
+}
+it = f3();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(9), 3, false);
+assertIteratorNext(it, 4);
+assertIteratorDone(it, 9);
+assertIteratorDone(it, undefined);
+
+// Finally block can throw.
+function *f4() {
+ try {
+ yield 1;
+ yield 2;
+ } finally {
+ throw 3;
+ }
+}
+it = f4();
+assertIteratorNext(it, 1);
+assertThrowsValue(() => it.return(8), 3);
+assertIteratorDone(it);
+
+function *f5() {}
+it = f5();
+assertIteratorDone(it);
+assertIteratorResult(it.return(3), 3, true);
+assertIteratorDone(it);
+
+function *f6() {
+ try {
+ yield 1;
+ yield 2;
+ } finally {
+ try {
+ return 9;
+ } finally {
+ yield 3;
+ }
+ }
+}
+it = f6();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(5), 3, false);
+assertIteratorDone(it, 9);
+assertIteratorDone(it);
+
+// If we yield in a finally block, a second .return() can override
+// the first one.
+function *f7() {
+ try {
+ yield 1;
+ yield 2;
+ } finally {
+ try {
+ yield 3;
+ } finally {
+ yield 4;
+ }
+ }
+}
+it = f7();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(5), 3, false);
+assertIteratorResult(it.return(6), 4, false);
+assertIteratorDone(it, 6);
+assertIteratorDone(it);
+
+// If we yield in a finally block, .throw() should work.
+function *f8() {
+ try {
+ yield 1;
+ yield 2;
+ } finally {
+ yield 3;
+ }
+}
+it = f8();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(5), 3, false);
+assertThrowsValue(() => it.throw(4), 4);
+assertIteratorDone(it);
+
+// If the generator is already running, we should throw a TypeError.
+function *f9() {
+ try {
+ yield 1;
+ yield 2;
+ } finally {
+ it.return(4);
+ yield 3;
+ }
+}
+it = f9();
+assertIteratorNext(it, 1);
+assertThrowsInstanceOf(() => it.return(5), TypeError);
+assertIteratorDone(it);
+assertIteratorDone(it);
+
+// Second return overrides first one and closes the generator.
+function *f10() {
+ try {
+ yield 1;
+ } finally {
+ yield 2;
+ }
+}
+it = f10();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(-1), 2, false);
+assertIteratorResult(it.return(-2), -2, true);
+assertIteratorDone(it);
+
+function *f11() {
+ try {
+ try {
+ yield 1;
+ } finally {
+ throw 2;
+ }
+ } catch(e) {
+ yield e;
+ } finally {
+ yield 3;
+ }
+}
+it = f11();
+assertIteratorNext(it, 1);
+assertIteratorResult(it.return(9), 2, false);
+assertIteratorNext(it, 3);
+assertIteratorDone(it);
+
+throw "done";
diff --git a/js/src/jit-test/tests/generators/throw-closes.js b/js/src/jit-test/tests/generators/throw-closes.js
new file mode 100644
index 000000000..072e40e3d
--- /dev/null
+++ b/js/src/jit-test/tests/generators/throw-closes.js
@@ -0,0 +1,63 @@
+// When a generator function throws, the generator is closed.
+
+load(libdir + "asserts.js");
+load(libdir + "iteration.js");
+
+// Star generator, next() throws.
+function *g() {
+ yield 1;
+ yield 2;
+ throw 3;
+ yield 4;
+}
+var i = g();
+assertIteratorNext(i, 1);
+assertIteratorNext(i, 2);
+assertThrowsValue(() => i.next(), 3);
+assertIteratorDone(i);
+assertIteratorDone(i);
+
+// Star generator, throw() throws.
+function *h() {
+ yield 1;
+ yield 2;
+}
+var i = h();
+assertIteratorNext(i, 1);
+assertThrowsValue(() => i.throw(4), 4);
+assertIteratorDone(i);
+
+// Star generator, return() throws.
+function *h2() {
+ try {
+ yield 1;
+ yield 2;
+ } finally {
+ throw 6;
+ }
+}
+var i = h2();
+assertIteratorNext(i, 1);
+assertThrowsValue(() => i.return(4), 6);
+assertIteratorDone(i);
+
+// Legacy generator, throw() throws.
+function l1() {
+ yield 1;
+ yield 2;
+}
+var i = l1();
+assertEq(i.next(), 1);
+assertThrowsValue(() => i.throw(5), 5);
+assertThrowsInstanceOf(() => i.next(), StopIteration);
+
+// Legacy generator, next() throws.
+function l2() {
+ yield 1;
+ throw 6;
+ yield 2;
+}
+var i = l2();
+assertEq(i.next(), 1);
+assertThrowsValue(() => i.next(), 6);
+assertThrowsInstanceOf(() => i.next(), StopIteration);
diff --git a/js/src/jit-test/tests/generators/throw-on-finished.js b/js/src/jit-test/tests/generators/throw-on-finished.js
new file mode 100644
index 000000000..541e48f1f
--- /dev/null
+++ b/js/src/jit-test/tests/generators/throw-on-finished.js
@@ -0,0 +1,7 @@
+load(libdir + "asserts.js");
+
+function*g(){ };
+o = g();
+o.next();
+function TestException() {};
+assertThrowsInstanceOf(() => o.throw(new TestException()), TestException);
diff --git a/js/src/jit-test/tests/generators/wrappers.js b/js/src/jit-test/tests/generators/wrappers.js
new file mode 100644
index 000000000..5cada5201
--- /dev/null
+++ b/js/src/jit-test/tests/generators/wrappers.js
@@ -0,0 +1,37 @@
+// Generator methods work transparently on CrossCompartmentWrappers.
+
+load(libdir + "asserts.js");
+load(libdir + "iteration.js");
+
+function gen() { yield 1; yield 2; }
+var it = gen();
+
+var g = newGlobal();
+g.eval("function gen2() { yield 3; yield 4; }; var it2 = gen2();");
+
+// LegacyGenerator.next
+assertEq(it.next.call(g.it2), 3);
+
+// LegacyGenerator.throw
+assertThrowsValue(() => it.throw.call(g.it2, 7), 7);
+
+function *gen3() { yield 1; yield 2; }
+it = gen3();
+g.eval("function *gen4() { yield 5; yield 6; }; var it4 = gen4();");
+
+// StarGenerator.next
+assertIteratorResult(it.next.call(g.it4), 5, false)
+
+// StarGenerator.throw
+assertThrowsValue(() => it.throw.call(g.it4, 8), 8);
+
+// StarGenerator.return
+assertIteratorResult(it.return.call(g.it4, 8), 8, true);
+
+// Other objects should throw.
+try {
+ it.next.call([]);
+ assertEq(0, 1);
+} catch (e) {
+ assertEq(e.toString().includes("called on incompatible Array"), true);
+}
diff --git a/js/src/jit-test/tests/generators/yield-in-finally.js b/js/src/jit-test/tests/generators/yield-in-finally.js
new file mode 100644
index 000000000..a99e5a61a
--- /dev/null
+++ b/js/src/jit-test/tests/generators/yield-in-finally.js
@@ -0,0 +1,178 @@
+// return value in try block should not be overridden by yield in finally block.
+
+load(libdir + "asserts.js");
+
+// simple
+function* g1() {
+ try {
+ return 42;
+ } finally {
+ yield 43;
+ }
+}
+var o = g1();
+var v = o.next();
+assertEq(v.done, false);
+assertEq(v.value, 43);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, 42);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, undefined);
+
+// without return value
+function* g2() {
+ try {
+ return;
+ } finally {
+ yield 43;
+ }
+}
+o = g2();
+v = o.next();
+assertEq(v.done, false);
+assertEq(v.value, 43);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, undefined);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, undefined);
+
+// nested try-finally
+function* g3() {
+ try {
+ try {
+ return 42;
+ } finally {
+ try {
+ return 43;
+ } finally {
+ yield 44;
+ }
+ }
+ } finally {
+ yield 45;
+ }
+}
+o = g3();
+v = o.next();
+assertEq(v.done, false);
+assertEq(v.value, 44);
+v = o.next();
+assertEq(v.done, false);
+assertEq(v.value, 45);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, 43);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, undefined);
+
+// yield*
+function* g4() {
+ try {
+ return 42;
+ } finally {
+ try {
+ return 43;
+ } finally {
+ yield* g5();
+ }
+ }
+}
+function* g5() {
+ yield 44;
+ return 45;
+}
+o = g4();
+v = o.next();
+assertEq(v.done, false);
+assertEq(v.value, 44);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, 43);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, undefined);
+
+// return in block scope
+function* g6() {
+ let a = 10;
+ {
+ let a = 20;
+ try {
+ let a = 30;
+ {
+ let a = 40;
+ return 42;
+ }
+ } finally {
+ yield 43;
+ }
+ }
+}
+o = g6();
+v = o.next();
+assertEq(v.done, false);
+assertEq(v.value, 43);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, 42);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, undefined);
+
+// no finally
+function* g7() {
+ try {
+ return 42;
+ } catch (e) {
+ yield 1;
+ }
+}
+o = g7();
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, 42);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, undefined);
+
+// legacy iterator have no return value
+function g8() {
+ try {
+ return;
+ } finally {
+ yield 43;
+ }
+}
+o = g8();
+v = o.next();
+assertEq(v, 43);
+assertThrowsInstanceOf(() => o.next(), StopIteration);
+
+// in "with" statement
+options("strict");
+eval(`
+function* g9() {
+ with ({ ".genrval": { value: 44, done: false } }) {
+ try {
+ return 42;
+ } finally {
+ yield 43;
+ }
+ }
+}
+o = g9();
+v = o.next();
+assertEq(v.done, false);
+assertEq(v.value, 43);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, 42);
+v = o.next();
+assertEq(v.done, true);
+assertEq(v.value, undefined);
+`);
diff --git a/js/src/jit-test/tests/generators/yield-regexp.js b/js/src/jit-test/tests/generators/yield-regexp.js
new file mode 100644
index 000000000..bcef03af0
--- /dev/null
+++ b/js/src/jit-test/tests/generators/yield-regexp.js
@@ -0,0 +1,41 @@
+// Bug 1099956
+
+load(libdir + "asserts.js");
+
+// ES6 treating yield as an identifier except in ES6 generators introduces a
+// syntax conflict with permissible JS >= 1.7 legacy generator syntax. Is
+// |yield /a/g| inside a function an attempt to convert the function into a
+// legacy generator, yielding a RegExp instance? Or does it instead read as
+// |(yield / a) / g|? Similar ambiguities exist for different textual content
+// in place of |a| -- |yield /x+17/g| or |(yield / x) + 17 / g|, and so on.
+// (And, much less importantly, is |yield /a/g| a syntax error in global code
+// as in JS >= 1.7, or is it |(yield / a) / g|.)
+//
+// For now, in JS >= 1.7, we preserve the old behavior. In all other JS we
+// conform to ES6: |yield /a/g| is a YieldExpression inside an ES6 generator,
+// and it's an IdentifierReference divided twice when not in an ES6 generator.
+// This test will need changes if we change our JS >= 1.7 parsing to be
+// ES6-compatible.
+
+function f1() {
+ yield /abc/g;
+}
+
+var g = f1();
+var v;
+v = g.next();
+assertEq(v instanceof RegExp, true);
+assertEq(v.toString(), "/abc/g");
+assertThrowsValue(() => g.next(), StopIteration);
+
+function* f2() {
+ yield /abc/g;
+}
+
+g = f2();
+v = g.next();
+assertEq(v.done, false);
+assertEq(v.value instanceof RegExp, true);
+assertEq(v.value.toString(), "/abc/g");
+v = g.next();
+assertEq(v.done, true);
diff --git a/js/src/jit-test/tests/generators/yield-yield.js b/js/src/jit-test/tests/generators/yield-yield.js
new file mode 100644
index 000000000..123abc5b7
--- /dev/null
+++ b/js/src/jit-test/tests/generators/yield-yield.js
@@ -0,0 +1,12 @@
+// Bug 880447
+
+load(libdir + "asserts.js");
+
+function f() {
+ yield yield 1;
+}
+
+var g = f();
+assertEq(g.next(), 1);
+assertEq(g.send("hello"), "hello");
+assertThrowsValue(() => g.next(), StopIteration);