mirror of
https://github.com/classilla/tenfourfox.git
synced 2025-02-09 07:32:04 +00:00
Bug 1071646 - Introduce JSOP_BINDVAR to support Annex B.3.3.3. (r=jorendorff)
This commit is contained in:
parent
37bf861a92
commit
884bd2ab53
@ -4413,7 +4413,7 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption)
|
||||
* i' to be hoisted out of the loop.
|
||||
*/
|
||||
MOZ_ASSERT(binding->isOp(JSOP_NOP));
|
||||
MOZ_ASSERT(emitOption != DefineVars);
|
||||
MOZ_ASSERT(emitOption != DefineVars && emitOption != AnnexB);
|
||||
|
||||
/*
|
||||
* To allow the front end to rewrite var f = x; as f = x; when a
|
||||
@ -4474,13 +4474,18 @@ BytecodeEmitter::emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode
|
||||
op == JSOP_STRICTSETGNAME)
|
||||
{
|
||||
MOZ_ASSERT(emitOption != PushInitialValues);
|
||||
JSOp bindOp;
|
||||
if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME)
|
||||
bindOp = JSOP_BINDNAME;
|
||||
else
|
||||
bindOp = JSOP_BINDGNAME;
|
||||
if (!emitIndex32(bindOp, atomIndex))
|
||||
return false;
|
||||
if (op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME) {
|
||||
if (!emitIndex32(JSOP_BINDGNAME, atomIndex))
|
||||
return false;
|
||||
} else if (emitOption == AnnexB) {
|
||||
// Annex B vars always go on the nearest variable environment,
|
||||
// even if scopes on the chain contain same-named bindings.
|
||||
if (!emit1(JSOP_BINDVAR))
|
||||
return false;
|
||||
} else {
|
||||
if (!emitIndex32(JSOP_BINDNAME, atomIndex))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool oldEmittingForInit = emittingForInit;
|
||||
@ -4504,7 +4509,7 @@ BytecodeEmitter::emitSingleVariable(ParseNode* pn, ParseNode* binding, ParseNode
|
||||
|
||||
// If we are not initializing, nothing to pop. If we are initializing
|
||||
// lets, we must emit the pops.
|
||||
if (emitOption == InitializeVars) {
|
||||
if (emitOption == InitializeVars || emitOption == AnnexB) {
|
||||
MOZ_ASSERT_IF(binding->isDefn(), initializer == binding->pn_expr);
|
||||
if (!binding->pn_scopecoord.isFree()) {
|
||||
if (!emitVarOp(binding, op))
|
||||
@ -6267,12 +6272,13 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
||||
// definitions are seen for the second time, we need to emit the
|
||||
// assignment that assigns the function to the outer 'var' binding.
|
||||
if (assignmentForAnnexB) {
|
||||
if (!emitTree(assignmentForAnnexB))
|
||||
return false;
|
||||
|
||||
// If we did not synthesize a new binding and only a simple
|
||||
// assignment, manually pop the result.
|
||||
if (assignmentForAnnexB->isKind(PNK_ASSIGN)) {
|
||||
if (assignmentForAnnexB->isKind(PNK_VAR)) {
|
||||
if (!emitVariables(assignmentForAnnexB, AnnexB))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(assignmentForAnnexB->isKind(PNK_ASSIGN));
|
||||
if (!emitTree(assignmentForAnnexB))
|
||||
return false;
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
}
|
||||
|
@ -121,7 +121,12 @@ enum VarEmitOption {
|
||||
// Emit code to evaluate initializer expressions and leave those values on
|
||||
// the stack. This is used to implement `for (let/const ...;;)` and
|
||||
// deprecated `let` blocks.
|
||||
PushInitialValues
|
||||
PushInitialValues,
|
||||
|
||||
// Like InitializeVars, but bind using BINDVAR instead of
|
||||
// BINDNAME/BINDGNAME. Only used for emitting declarations synthesized for
|
||||
// Annex B block-scoped function semantics.
|
||||
AnnexB,
|
||||
};
|
||||
|
||||
struct BytecodeEmitter
|
||||
|
@ -2368,8 +2368,8 @@ Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
|
||||
// Under non-strict mode, try ES6 Annex B.3.3 semantics. If
|
||||
// making an additional 'var' binding of the same name does
|
||||
// not throw an early error, do so. This 'var' binding would
|
||||
// be assigned the function object in situ, e.g., when its
|
||||
// declaration is reached, not at the start of the block.
|
||||
// be assigned the function object when its declaration is
|
||||
// reached, not at the start of the block.
|
||||
|
||||
annexDef = pc->decls().lookupFirst(funName);
|
||||
if (annexDef) {
|
||||
|
@ -1753,7 +1753,6 @@ CASE(JSOP_UNUSED209)
|
||||
CASE(JSOP_UNUSED210)
|
||||
CASE(JSOP_UNUSED211)
|
||||
CASE(JSOP_UNUSED212)
|
||||
CASE(JSOP_UNUSED213)
|
||||
CASE(JSOP_UNUSED219)
|
||||
CASE(JSOP_UNUSED220)
|
||||
CASE(JSOP_UNUSED221)
|
||||
@ -2089,6 +2088,12 @@ CASE(JSOP_BINDNAME)
|
||||
}
|
||||
END_CASE(JSOP_BINDNAME)
|
||||
|
||||
CASE(JSOP_BINDVAR)
|
||||
{
|
||||
PUSH_OBJECT(REGS.fp()->varObj());
|
||||
}
|
||||
END_CASE(JSOP_BINDVAR)
|
||||
|
||||
#define BITWISE_OP(OP) \
|
||||
JS_BEGIN_MACRO \
|
||||
int32_t i, j; \
|
||||
|
@ -2052,7 +2052,15 @@
|
||||
macro(JSOP_UNUSED210, 210, "unused210", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
macro(JSOP_UNUSED211, 211, "unused211", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
macro(JSOP_UNUSED212, 212, "unused212", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
macro(JSOP_UNUSED213, 213, "unused213", NULL, 1, 0, 0, JOF_BYTE) \
|
||||
/*
|
||||
* Pushes the nearest 'var' environment.
|
||||
*
|
||||
* Category: Variables and Scopes
|
||||
* Type: Free Variables
|
||||
* Operands:
|
||||
* Stack: => scope
|
||||
*/ \
|
||||
macro(JSOP_BINDVAR, 213, "bindvar", NULL, 1, 0, 1, JOF_BYTE) \
|
||||
/*
|
||||
* Pushes the global scope onto the stack if the script doesn't have a
|
||||
* non-syntactic global scope. Otherwise will act like JSOP_BINDNAME.
|
||||
|
Loading…
x
Reference in New Issue
Block a user