mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
Bug 1360220 - Backed out changeset ed8623eefe6c for causing fuzzblocker bug 1362590, rs=shu on IRC
This commit is contained in:
parent
52209697e6
commit
a6f9d2dd99
@ -5886,7 +5886,7 @@ BytecodeEmitter::emitDestructuringOpsObject(ParseNode* pattern, DestructuringFla
|
||||
|
||||
MOZ_ASSERT(this->stackDepth > 0); // ... RHS
|
||||
|
||||
if (!emit1(JSOP_CHECKOBJCOERCIBLE)) // ... RHS
|
||||
if (!emitRequireObjectCoercible()) // ... RHS
|
||||
return false;
|
||||
|
||||
bool needsRestPropertyExcludedSet = pattern->pn_count > 1 &&
|
||||
@ -6921,6 +6921,42 @@ BytecodeEmitter::emitWith(ParseNode* pn)
|
||||
return emitterScope.leave(this);
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitRequireObjectCoercible()
|
||||
{
|
||||
// For simplicity, handle this in self-hosted code, at cost of 13 bytes of
|
||||
// bytecode versus 1 byte for a dedicated opcode. As more places need this
|
||||
// behavior, we may want to reconsider this tradeoff.
|
||||
|
||||
#ifdef DEBUG
|
||||
auto depth = this->stackDepth;
|
||||
#endif
|
||||
MOZ_ASSERT(depth > 0); // VAL
|
||||
if (!emit1(JSOP_DUP)) // VAL VAL
|
||||
return false;
|
||||
|
||||
// Note that "intrinsic" is a misnomer: we're calling a *self-hosted*
|
||||
// function that's not an intrinsic! But it nonetheless works as desired.
|
||||
if (!emitAtomOp(cx->names().RequireObjectCoercible,
|
||||
JSOP_GETINTRINSIC)) // VAL VAL REQUIREOBJECTCOERCIBLE
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!emit1(JSOP_UNDEFINED)) // VAL VAL REQUIREOBJECTCOERCIBLE UNDEFINED
|
||||
return false;
|
||||
if (!emit2(JSOP_PICK, 2)) // VAL REQUIREOBJECTCOERCIBLE UNDEFINED VAL
|
||||
return false;
|
||||
if (!emitCall(JSOP_CALL_IGNORES_RV, 1))// VAL IGNORED
|
||||
return false;
|
||||
checkTypeSet(JSOP_CALL_IGNORES_RV);
|
||||
|
||||
if (!emit1(JSOP_POP)) // VAL
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(depth == this->stackDepth);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitCopyDataProperties(CopyOption option)
|
||||
{
|
||||
|
@ -708,6 +708,10 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
||||
template <typename NameEmitter>
|
||||
MOZ_MUST_USE bool emitDestructuringDeclsWithEmitter(ParseNode* pattern, NameEmitter emitName);
|
||||
|
||||
// Throw a TypeError if the value atop the stack isn't convertible to an
|
||||
// object, with no overall effect on the stack.
|
||||
MOZ_MUST_USE bool emitRequireObjectCoercible();
|
||||
|
||||
enum class CopyOption {
|
||||
Filtered, Unfiltered
|
||||
};
|
||||
|
@ -183,10 +183,22 @@ check_one("[...].foo",
|
||||
function() { [undefined, ...[]].foo(); },
|
||||
" is not a function");
|
||||
|
||||
check_one("[...][Symbol.iterator](...).next(...).value",
|
||||
function () { var [{x}] = [null, {}]; }, " is null");
|
||||
check_one("[...][Symbol.iterator](...).next(...).value",
|
||||
function () { var [{x}] = [void 0, {}]; }, " is undefined");
|
||||
// Manual testing for this case: the only way to trigger an error is *not* on
|
||||
// an attempted property access during destructuring, and the error message
|
||||
// invoking ToObject(null) is different: "can't convert {0} to object".
|
||||
try
|
||||
{
|
||||
(function() {
|
||||
var [{x}] = [null, {}];
|
||||
})();
|
||||
throw new Error("didn't throw");
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
assertEq(e instanceof TypeError, true,
|
||||
"expected TypeError, got " + e);
|
||||
assertEq(e.message, "can't convert null to object");
|
||||
}
|
||||
|
||||
try {
|
||||
(function() {
|
||||
|
Loading…
Reference in New Issue
Block a user