Bug 1386026 - Make SpiderMonkey Debugger tests pass even though async generators are Nightly-only. r=tromey
authorJim Blandy <jimb@mozilla.com>
Mon, 31 Jul 2017 22:32:09 -0700
changeset 420945 3232054e0a930e0eceaa41155ce534f92d717f11
parent 420944 b78fd576bdc8d08b630ee3b831352966b90000f2
child 420946 a559d546208cc78791680c57a86dd7819113da1b
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstromey
bugs1386026
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1386026 - Make SpiderMonkey Debugger tests pass even though async generators are Nightly-only. r=tromey
js/src/jit-test/lib/nightly-only.js
js/src/jit-test/tests/debug/Object-displayName-01.js
js/src/jit-test/tests/debug/Object-environment-02.js
js/src/jit-test/tests/debug/Object-name-01.js
js/src/jit-test/tests/debug/Object-parameterNames.js
js/src/jit-test/tests/debug/Object-script.js
js/src/jit-test/tests/debug/isAsyncFunction-isGeneratorFunction.js
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/lib/nightly-only.js
@@ -0,0 +1,20 @@
+// Some experimental features are enabled only on nightly builds, and disabled
+// on beta and release. Tests for these features should not simply disable
+// themselves on all but nightly builds, because if we neglect to update such
+// tests once the features cease to be experimental, we'll silently skip the
+// tests on beta and release, even though they should run.
+
+// Call the function f. On beta and release, expect it to throw an error that is
+// an instance of error.
+function nightlyOnly(error, f) {
+  if (getBuildConfiguration().release_or_beta) {
+    try {
+      f();
+      throw new Error("use of feature expected to fail on release and beta, but succeeded; please update test");
+    } catch (e if e instanceof error) {
+      // All is well.
+    }
+  } else {
+    f();
+  }
+}
--- a/js/src/jit-test/tests/debug/Object-displayName-01.js
+++ b/js/src/jit-test/tests/debug/Object-displayName-01.js
@@ -1,10 +1,12 @@
 // Debugger.Object.prototype.displayName
 
+load(libdir + 'nightly-only.js');
+
 var g = newGlobal();
 var dbg = Debugger(g);
 var name;
 dbg.onDebuggerStatement = function (frame) { name = frame.callee.displayName; };
 
 g.eval("(function f() { debugger; })();");
 assertEq(name, "f");
 g.eval("(function () { debugger; })();");
@@ -12,10 +14,12 @@ assertEq(name, undefined);
 g.eval("Function('debugger;')();");
 assertEq(name, "anonymous");
 g.eval("var f = function() { debugger; }; f()");
 assertEq(name, "f");
 g.eval("var a = {}; a.f = function() { debugger; }; a.f()");
 assertEq(name, "a.f");
 g.eval("(async function grondo() { debugger; })();");
 assertEq(name, "grondo");
-g.eval("(async function* estux() { debugger; })().next();");
-assertEq(name, "estux");
+nightlyOnly(g.SyntaxError, () => {
+  g.eval("(async function* estux() { debugger; })().next();");
+  assertEq(name, "estux");
+})
--- a/js/src/jit-test/tests/debug/Object-environment-02.js
+++ b/js/src/jit-test/tests/debug/Object-environment-02.js
@@ -1,20 +1,26 @@
 // The .environment of a function Debugger.Object is an Environment object.
 
+load(libdir + 'nightly-only.js');
+
 var g = newGlobal()
 var dbg = new Debugger;
 var gDO = dbg.addDebuggee(g);
 
 function check(expr) {
   print("checking " + uneval(expr));
-  let val = gDO.executeInGlobal(expr).return;
-  assertEq(val.environment instanceof Debugger.Environment, true);
+  let completion = gDO.executeInGlobal(expr);
+  if (completion.throw)
+    throw completion.throw.unsafeDereference();
+  assertEq(completion.return.environment instanceof Debugger.Environment, true);
 }
 
 g.eval('function j(a) { }');
 
 check('j');
 check('(() => { })');
 check('(function f() { })');
 check('(function* g() { })');
 check('(async function m() { })');
-check('(async function* n() { })');
+nightlyOnly(g.SyntaxError, () => {
+  check('(async function* n() { })');
+});
--- a/js/src/jit-test/tests/debug/Object-name-01.js
+++ b/js/src/jit-test/tests/debug/Object-name-01.js
@@ -1,17 +1,21 @@
 // Debugger.Object.prototype.name
 
+load(libdir + 'nightly-only.js');
+
 var g = newGlobal();
 var dbg = Debugger(g);
 var name;
 dbg.onDebuggerStatement = function (frame) { name = frame.callee.name; };
 
 g.eval("(function f() { debugger; })();");
 assertEq(name, "f");
 g.eval("(function () { debugger; })();");
 assertEq(name, undefined);
 g.eval("Function('debugger;')();");
 assertEq(name, "anonymous");
 g.eval("(async function grondo() { debugger; })();");
 assertEq(name, "grondo");
-g.eval("(async function* estux() { debugger; })().next();");
-assertEq(name, "estux");
+nightlyOnly(g.SyntaxError, () => {
+  g.eval("(async function* estux() { debugger; })().next();");
+  assertEq(name, "estux");
+});
--- a/js/src/jit-test/tests/debug/Object-parameterNames.js
+++ b/js/src/jit-test/tests/debug/Object-parameterNames.js
@@ -1,27 +1,35 @@
 load(libdir + 'array-compare.js');
+load(libdir + 'nightly-only.js');
 
 var g = newGlobal();
 var dbg = new Debugger;
 var gDO = dbg.addDebuggee(g);
 var hits = 0;
 
 function check(expr, expected) {
   print("checking " + uneval(expr));
-  let fn = gDO.executeInGlobal(expr).return;
+
+  let completion = gDO.executeInGlobal(expr);
+  if (completion.throw)
+    throw completion.throw.unsafeDereference();
+
+  let fn = completion.return;
   if (expected === undefined)
     assertEq(fn.parameterNames, undefined);
   else
     assertEq(arraysEqual(fn.parameterNames, expected), true);
 }
 
 check('(function () {})', []);
 check('(function (x) {})', ["x"]);
 check('(function (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z) {})',
       ["a","b","c","d","e","f","g","h","i","j","k","l","m",
        "n","o","p","q","r","s","t","u","v","w","x","y","z"]);
 check('(function (a, [b, c], {d, e:f}) { })',
       ["a", undefined, undefined]);
 check('({a:1})', undefined);
 check('Math.atan2', [undefined, undefined]);
 check('(async function (a, b, c) {})', ["a", "b", "c"]);
-check('(async function* (d, e, f) {})', ["d", "e", "f"]);
+nightlyOnly(g.SyntaxError, () => {
+  check('(async function* (d, e, f) {})', ["d", "e", "f"]);
+});
--- a/js/src/jit-test/tests/debug/Object-script.js
+++ b/js/src/jit-test/tests/debug/Object-script.js
@@ -1,20 +1,29 @@
+load(libdir + 'nightly-only.js');
+
 var g = newGlobal();
 var dbg = new Debugger;
 var gDO = dbg.addDebuggee(g);
 
 function check(expr, expected) {
   print("checking " + uneval(expr) + ", expecting " +
         (expected ? "script" : "no script"));
-  let val = gDO.executeInGlobal(expr).return;
+
+  let completion = gDO.executeInGlobal(expr);
+  if (completion.throw)
+    throw completion.throw.unsafeDereference();
+
+  let val = completion.return;
   if (expected)
     assertEq(val.script instanceof Debugger.Script, true);
   else
     assertEq(val.script, undefined);
 }
 
 check('(function g(){})', true);
 check('(function* h() {})', true);
 check('(async function j() {})', true);
-check('(async function* k() {})', true);
+nightlyOnly(g.SyntaxError, () => {
+  check('(async function* k() {})', true);
+});
 check('({})', false);
 check('Math.atan2', false);
--- a/js/src/jit-test/tests/debug/isAsyncFunction-isGeneratorFunction.js
+++ b/js/src/jit-test/tests/debug/isAsyncFunction-isGeneratorFunction.js
@@ -1,45 +1,54 @@
 // Debugger.Script.prototype.isAsyncFunction, Debugger.Object.prototype.isAsyncFunction,
 // Debugger.Script.prototype.isGeneratorFunction, Debugger.Object.prototype.isGeneratorFunction
 
+load(libdir + 'nightly-only.js');
+
 var g = newGlobal();
 var dbg = new Debugger();
 var gDO = dbg.addDebuggee(g);
 g.non_debuggee = function non_debuggee () {}
 
 function checkExpr(expr, { isAsync, isGenerator })
 {
   print("Evaluating: " + uneval(expr));
-  let fn = gDO.executeInGlobal(expr).return;
+  let completion = gDO.executeInGlobal(expr);
+  if (completion.throw)
+    throw completion.throw.unsafeDereference();
 
+  let fn = completion.return;
   assertEq(fn.isAsyncFunction, isAsync);
   assertEq(fn.isGeneratorFunction, isGenerator);
 
   // The Debugger.Object and its Debugger.Script should always agree.
   if (fn.script) {
     assertEq(fn.isAsyncFunction, fn.script.isAsyncFunction);
     assertEq(fn.isGeneratorFunction, fn.script.isGeneratorFunction);
   }
 }
 
 checkExpr('({})', { isAsync: undefined, isGenerator: undefined });
 checkExpr('non_debuggee', { isAsync: undefined, isGenerator: undefined });
 checkExpr('(function(){})', { isAsync: false, isGenerator: false });
 checkExpr('(function*(){})', { isAsync: false, isGenerator: true });
 checkExpr('(async function snerf(){})', { isAsync: true, isGenerator: false });
-checkExpr('(async function* omlu(){})', { isAsync: true, isGenerator: true });
+nightlyOnly(g.SyntaxError, () => {
+  checkExpr('(async function* omlu(){})', { isAsync: true, isGenerator: true });
+});
 
 checkExpr('new Function("1+2")', { isAsync: false, isGenerator: false });
 checkExpr('Object.getPrototypeOf(function*(){}).constructor("1+2")',
           { isAsync: false, isGenerator: true });
 checkExpr('Object.getPrototypeOf(async function(){}).constructor("1+2")',
           { isAsync: true, isGenerator: false });
-checkExpr('Object.getPrototypeOf(async function*(){}).constructor("1+2")',
-          { isAsync: true, isGenerator: true });
+nightlyOnly(g.SyntaxError, () => {
+  checkExpr('Object.getPrototypeOf(async function*(){}).constructor("1+2")',
+            { isAsync: true, isGenerator: true });
+});
 
 // Check eval scripts.
 function checkFrame(expr, type)
 {
   var log = '';
   dbg.onDebuggerStatement = function(frame) {
     log += 'd';
     assertEq(frame.type, type);