diff --git a/harness/asyncHelpers.js b/harness/asyncHelpers.js index 2d55fafebc2..e376caa0422 100644 --- a/harness/asyncHelpers.js +++ b/harness/asyncHelpers.js @@ -50,18 +50,21 @@ function asyncTest(testFunc) { */ assert.throwsAsync = function (expectedErrorConstructor, func, message) { return new Promise(function (resolve) { - var expectedName = expectedErrorConstructor.name; - var expectation = "Expected a " + expectedName + " to be thrown asynchronously"; var fail = function (detail) { if (message === undefined) { throw new Test262Error(detail); } throw new Test262Error(message + " " + detail); }; - var res; + if (typeof expectedErrorConstructor !== "function") { + fail("assert.throwsAsync called with an argument that is not an error constructor"); + } if (typeof func !== "function") { fail("assert.throwsAsync called with an argument that is not a function"); } + var expectedName = expectedErrorConstructor.name; + var expectation = "Expected a " + expectedName + " to be thrown asynchronously"; + var res; try { res = func(); } catch (thrown) { @@ -70,9 +73,9 @@ assert.throwsAsync = function (expectedErrorConstructor, func, message) { if (res === null || typeof res !== "object" || typeof res.then !== "function") { fail(expectation + " but result was not a thenable"); } - + var thenable; try { - resolve(Promise.resolve(res).then( + thenable = res.then( function () { fail(expectation + " but no exception was thrown at all"); }, @@ -89,9 +92,13 @@ assert.throwsAsync = function (expectedErrorConstructor, func, message) { fail(expectation + " but got a " + actualName); } } - )); + ); } catch (thrown) { fail(expectation + " but .then threw synchronously"); } + if (thenable === null || typeof thenable !== "object" || typeof thenable.then !== "function") { + fail(expectation + " but result was not a conforming thenable"); + } + resolve(Promise.resolve(thenable)); }); }; diff --git a/test/harness/asyncHelpers-throwsAsync-func-bad-thenable.js b/test/harness/asyncHelpers-throwsAsync-func-bad-thenable.js new file mode 100644 index 00000000000..5aa58b6ea19 --- /dev/null +++ b/test/harness/asyncHelpers-throwsAsync-func-bad-thenable.js @@ -0,0 +1,34 @@ +// Copyright (C) 2024 Julián Espina. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + assert.throwsAsync returns a promise that rejects if func returns a bad thenable. +flags: [async] +includes: [asyncHelpers.js] +---*/ + +asyncTest(async function() { + var caught = false; + var func = function () { + return { + then: function () {}, + }; + }; + const p = assert.throwsAsync(TypeError, func); + assert(p instanceof Promise, "assert.throwsAsync should return a promise"); + try { + await p; + } catch (e) { + caught = true; + assert.sameValue( + e.constructor, + Test262Error, + "throwsAsync should reject bad thenable with a Test262Error" + ); + } finally { + assert( + caught, + "assert.throwsAsync did not reject bad thenable in " + func + ); + } +});