summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/debug/Frame-onStep-generator-resumption-02.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/debug/Frame-onStep-generator-resumption-02.js')
-rw-r--r--js/src/jit-test/tests/debug/Frame-onStep-generator-resumption-02.js78
1 files changed, 78 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/debug/Frame-onStep-generator-resumption-02.js b/js/src/jit-test/tests/debug/Frame-onStep-generator-resumption-02.js
new file mode 100644
index 0000000000..25f9186c77
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Frame-onStep-generator-resumption-02.js
@@ -0,0 +1,78 @@
+// Like Frame-onStep-generator-resumption-01.js, but bail out by throwing.
+
+let g = newGlobal({newCompartment: true});
+g.eval(`
+ function* f() {
+ yield 1;
+ }
+`);
+
+// Try force-returning from one of the instructions in `f` before the initial
+// yield. In detail:
+//
+// * This test calls `g.f()` under the Debugger.
+// * It uses the Debugger to step `ttl` times.
+// If we reach the initial yield before stepping the `ttl`th time, we're done.
+// * Otherwise, the test tries to force-return from `f`.
+// * That's an error, so the uncaughtExceptionHook is called.
+// * The uncaughtExceptionHook returns a `throw` completion value.
+//
+// Returns `true` if we reached the initial yield, false otherwise.
+//
+// Note that this function is called in a loop so that every possible relevant
+// value of `ttl` is tried once.
+function test(ttl) {
+ let dbg = new Debugger(g);
+ let exiting = false; // we ran out of time-to-live and have forced return
+ let done = false; // we reached the initial yield without forced return
+ let reported = false; // a TypeError was reported.
+
+ dbg.onEnterFrame = frame => {
+ assertEq(frame.callee.name, "f");
+ dbg.onEnterFrame = undefined;
+ frame.onStep = () => {
+ if (ttl == 0) {
+ exiting = true;
+ // This test case never resumes the generator after the initial
+ // yield. Therefore the initial yield has not happened yet. So this
+ // force-return will be an error.
+ return {return: "ponies"};
+ }
+ ttl--;
+ };
+ frame.onPop = completion => {
+ if (!exiting)
+ done = true;
+ };
+ };
+
+ dbg.uncaughtExceptionHook = (exc) => {
+ // When onStep returns an invalid resumption value,
+ // the error is reported here.
+ assertEq(exc instanceof TypeError, true);
+ reported = true;
+ return {throw: "FAIL"}; // Bail out of the test.
+ };
+
+ let result;
+ let caught = undefined;
+ try {
+ result = g.f();
+ } catch (exc) {
+ caught = exc;
+ }
+
+ if (done) {
+ assertEq(reported, false);
+ assertEq(result instanceof g.f, true);
+ assertEq(caught, undefined);
+ } else {
+ assertEq(reported, true);
+ assertEq(caught, "FAIL");
+ }
+
+ dbg.enabled = false;
+ return done;
+}
+
+for (let ttl = 0; !test(ttl); ttl++) {}