Bug 1799288: Cover destructuring parameters in the parameters try-catch block for async functions. r=mgaudet

Differential Revision: https://phabricator.services.mozilla.com/D161600
This commit is contained in:
André Bargull 2022-11-22 07:05:25 +00:00
parent bdc412e198
commit 06528cdbaa
4 changed files with 88 additions and 31 deletions

View File

@ -17,7 +17,7 @@
using namespace js;
using namespace js::frontend;
bool AsyncEmitter::prepareForParamsWithExpression() {
bool AsyncEmitter::prepareForParamsWithExpressionOrDestructuring() {
MOZ_ASSERT(state_ == State::Start);
#ifdef DEBUG
state_ = State::Parameters;
@ -28,7 +28,7 @@ bool AsyncEmitter::prepareForParamsWithExpression() {
return rejectTryCatch_->emitTry();
}
bool AsyncEmitter::prepareForParamsWithoutExpression() {
bool AsyncEmitter::prepareForParamsWithoutExpressionOrDestructuring() {
MOZ_ASSERT(state_ == State::Start);
#ifdef DEBUG
state_ = State::Parameters;

View File

@ -25,11 +25,12 @@ struct BytecodeEmitter;
// the number of hops required to reach the |.generator| variable. In order
// to handle this, we can't reuse the same TryCatch emitter.
//
// Simple case - For a function without expression parameters:
// Simple case - For a function without expression or destructuring
// parameters:
// `async function f(<params>) {<body>}`,
// AsyncEmitter ae(this);
//
// ae.prepareForParamsWithoutExpression();
// ae.prepareForParamsWithoutExpressionOrDestructuring();
// // Emit Params.
// ...
// ae.paramsEpilogue(); // We need to emit the epilogue before the extra
@ -43,11 +44,11 @@ struct BytecodeEmitter;
//
// ae.emitEndFunction();
//
// Complex case - For a function with expression parameters:
// Complex case - For a function with expression or destructuring parameters:
// `async function f(<expression>) {<body>}`,
// AsyncEmitter ae(this);
//
// ae.prepareForParamsWithExpression();
// ae.prepareForParamsWithExpressionOrDestructuring();
//
// // Emit Params.
// ...
@ -96,26 +97,26 @@ class MOZ_STACK_CLASS AsyncEmitter {
// |
// +----------+
// |
// | [Parameters with Expression]
// | prepareForParamsWithExpression +------------+
// +-------------------------------------| Parameters |-->+
// | +------------+ |
// | |
// | [Parameters Without Expression] |
// | prepareForParamsWithoutExpression +------------+ |
// +-------------------------------------| Parameters |-->+
// | +------------+ |
// | [Modules] |
// | prepareForModule +----------------+ |
// +-------------------->| ModulePrologue |--+ |
// +----------------+ | |
// | |
// | |
// +-----------------------------------------+ |
// | |
// | |
// V +------------+ paramsEpilogue |
// +<--------------------| PostParams |<------------------+
// | [Parameters with Expression or Destructuring]
// | prepareForParamsWithExpressionOrDestructuring +------------+
// +----------------------------------------------------| Parameters |-->+
// | +------------+ |
// | |
// | [Parameters Without Expression or Destructuring] |
// | prepareForParamsWithoutExpressionOrDestructuring +------------+ |
// +----------------------------------------------------| Parameters |-->+
// | +------------+ |
// | [Modules] |
// | prepareForModule +----------------+ |
// +-------------------->| ModulePrologue |--+ |
// +----------------+ | |
// | |
// | |
// +-----------------------------------------+ |
// | |
// | |
// V +------------+ paramsEpilogue |
// +<--------------------| PostParams |<---------------------------------+
// | +------------+
// |
// | [Script body]
@ -158,8 +159,8 @@ class MOZ_STACK_CLASS AsyncEmitter {
public:
explicit AsyncEmitter(BytecodeEmitter* bce) : bce_(bce){};
[[nodiscard]] bool prepareForParamsWithoutExpression();
[[nodiscard]] bool prepareForParamsWithExpression();
[[nodiscard]] bool prepareForParamsWithoutExpressionOrDestructuring();
[[nodiscard]] bool prepareForParamsWithExpressionOrDestructuring();
[[nodiscard]] bool prepareForModule();
[[nodiscard]] bool emitParamsEpilogue();
[[nodiscard]] bool prepareForBody();

View File

@ -360,12 +360,12 @@ bool FunctionScriptEmitter::prepareForParameters() {
}
if (funbox_->needsPromiseResult()) {
if (funbox_->hasParameterExprs) {
if (!asyncEmitter_->prepareForParamsWithExpression()) {
if (funbox_->hasParameterExprs || funbox_->hasDestructuringArgs) {
if (!asyncEmitter_->prepareForParamsWithExpressionOrDestructuring()) {
return false;
}
} else {
if (!asyncEmitter_->prepareForParamsWithoutExpression()) {
if (!asyncEmitter_->prepareForParamsWithoutExpressionOrDestructuring()) {
return false;
}
}

View File

@ -0,0 +1,56 @@
// |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
class ExpectedError extends Error {
name = "ExpectedError";
}
class UnexpectedError extends Error {
name = "UnexpectedError";
}
function throwExpectedError() {
throw new ExpectedError();
}
async function throwsInParameterExpression(a = throwExpectedError()) {
throw new UnexpectedError();
}
assertEventuallyThrows(throwsInParameterExpression(), ExpectedError);
async function throwsInObjectDestructuringParameterEmpty({}) {
throw new UnexpectedError();
}
assertEventuallyThrows(throwsInObjectDestructuringParameterEmpty(), TypeError);
let objectThrowingExpectedError = {
get a() {
throw new ExpectedError();
}
}
async function throwsInObjectDestructuringParameter({a}) {
throw new UnexpectedError();
}
assertEventuallyThrows(throwsInObjectDestructuringParameter(), TypeError);
assertEventuallyThrows(throwsInObjectDestructuringParameter(objectThrowingExpectedError), ExpectedError);
let iteratorThrowingExpectedError = {
[Symbol.iterator]() {
throw new ExpectedError();
}
};
async function throwsInArrayDestructuringParameterEmpty([]) {
throw new UnexpectedError();
}
assertEventuallyThrows(throwsInArrayDestructuringParameterEmpty(), TypeError);
assertEventuallyThrows(throwsInArrayDestructuringParameterEmpty(iteratorThrowingExpectedError), ExpectedError);
async function throwsInArrayDestructuringParameter([a]) {
throw new UnexpectedError();
}
assertEventuallyThrows(throwsInArrayDestructuringParameter(), TypeError);
assertEventuallyThrows(throwsInArrayDestructuringParameter(iteratorThrowingExpectedError), ExpectedError);
if (typeof reportCompare === "function")
reportCompare(true, true);