mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 1408740 - Correctly throw a TypeError when closing iterators when <generator>.return is an object emulating undefined. r=anba
--HG-- extra : rebase_source : f7bf3c2c955a8711eab3dd2c9edcbfaf9df6e45e
This commit is contained in:
parent
012a6c1870
commit
542c511e67
@ -5313,6 +5313,37 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = Iter
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitPushNotUndefinedOrNull()
|
||||
{
|
||||
MOZ_ASSERT(this->stackDepth > 0); // V
|
||||
|
||||
if (!emit1(JSOP_DUP)) // V V
|
||||
return false;
|
||||
if (!emit1(JSOP_UNDEFINED)) // V V UNDEFINED
|
||||
return false;
|
||||
if (!emit1(JSOP_STRICTNE)) // V ?NEQL
|
||||
return false;
|
||||
|
||||
JumpList undefinedOrNullJump;
|
||||
if (!emitJump(JSOP_AND, &undefinedOrNullJump)) // V ?NEQL
|
||||
return false;
|
||||
|
||||
if (!emit1(JSOP_POP)) // V
|
||||
return false;
|
||||
if (!emit1(JSOP_DUP)) // V V
|
||||
return false;
|
||||
if (!emit1(JSOP_NULL)) // V V NULL
|
||||
return false;
|
||||
if (!emit1(JSOP_STRICTNE)) // V ?NEQL
|
||||
return false;
|
||||
|
||||
if (!emitJumpTargetAndPatch(undefinedOrNullJump)) // V NOT-UNDEF-OR-NULL
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync */,
|
||||
CompletionKind completionKind /* = CompletionKind::Normal */,
|
||||
@ -5338,15 +5369,12 @@ BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync
|
||||
|
||||
// Step 4.
|
||||
//
|
||||
// Do nothing if "return" is null or undefined.
|
||||
// Do nothing if "return" is undefined or null.
|
||||
IfThenElseEmitter ifReturnMethodIsDefined(this);
|
||||
if (!emit1(JSOP_DUP)) // ... ITER RET RET
|
||||
if (!emitPushNotUndefinedOrNull()) // ... ITER RET NOT-UNDEF-OR-NULL
|
||||
return false;
|
||||
if (!emit1(JSOP_UNDEFINED)) // ... ITER RET RET UNDEFINED
|
||||
return false;
|
||||
if (!emit1(JSOP_NE)) // ... ITER RET ?NEQL
|
||||
return false;
|
||||
if (!ifReturnMethodIsDefined.emitIfElse())
|
||||
|
||||
if (!ifReturnMethodIsDefined.emitIfElse()) // ... ITER RET
|
||||
return false;
|
||||
|
||||
if (completionKind == CompletionKind::Throw) {
|
||||
@ -5447,10 +5475,12 @@ BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync
|
||||
}
|
||||
}
|
||||
|
||||
if (!ifReturnMethodIsDefined.emitElse())
|
||||
if (!ifReturnMethodIsDefined.emitElse()) // ... ITER RET
|
||||
return false;
|
||||
|
||||
if (!emit1(JSOP_POP)) // ... ITER
|
||||
return false;
|
||||
|
||||
if (!ifReturnMethodIsDefined.emitEnd())
|
||||
return false;
|
||||
|
||||
@ -8920,13 +8950,9 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter)
|
||||
|
||||
// Step iii.
|
||||
//
|
||||
// Do nothing if "return" is undefined.
|
||||
// Do nothing if "return" is undefined or null.
|
||||
IfThenElseEmitter ifReturnMethodIsDefined(this);
|
||||
if (!emit1(JSOP_DUP)) // ITER RESULT FTYPE FVALUE ITER RET RET
|
||||
return false;
|
||||
if (!emit1(JSOP_UNDEFINED)) // ITER RESULT FTYPE FVALUE ITER RET RET UNDEFINED
|
||||
return false;
|
||||
if (!emit1(JSOP_NE)) // ITER RESULT FTYPE FVALUE ITER RET ?NEQL
|
||||
if (!emitPushNotUndefinedOrNull()) // ITER RESULT FTYPE FVALUE ITER RET NOT-UNDEF-OR-NULL
|
||||
return false;
|
||||
|
||||
// Step iv.
|
||||
|
@ -508,6 +508,9 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
||||
// Helper to emit JSOP_CHECKISCALLABLE.
|
||||
MOZ_MUST_USE bool emitCheckIsCallable(CheckIsCallableKind kind);
|
||||
|
||||
// Push whether the value atop of the stack is non-undefined and non-null.
|
||||
MOZ_MUST_USE bool emitPushNotUndefinedOrNull();
|
||||
|
||||
// Emit a bytecode followed by an uint16 immediate operand stored in
|
||||
// big-endian order.
|
||||
MOZ_MUST_USE bool emitUint16Operand(JSOp op, uint32_t operand);
|
||||
|
Loading…
Reference in New Issue
Block a user