mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 963641 - Remove PNK_MUTATEPROTO, and just make JSOP_MUTATEPROTO be generated for the PNK_INITPROP+__proto__ combination. r=jorendorff
--HG-- extra : rebase_source : 8317d2a90d55a57fb654f72a57ca40575613072c
This commit is contained in:
parent
2a2fd41d40
commit
cef5bfd081
@ -2908,29 +2908,28 @@ EmitDestructuringDecl(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp,
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitDestructuringDecls(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *pn)
|
||||
EmitDestructuringDecls(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp prologOp,
|
||||
ParseNode *pattern)
|
||||
{
|
||||
ParseNode *pn2, *pn3;
|
||||
DestructuringDeclEmitter emitter;
|
||||
|
||||
if (pn->isKind(PNK_ARRAY)) {
|
||||
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
|
||||
if (pn2->isKind(PNK_ELISION))
|
||||
if (pattern->isKind(PNK_ARRAY)) {
|
||||
for (ParseNode *element = pattern->pn_head; element; element = element->pn_next) {
|
||||
if (element->isKind(PNK_ELISION))
|
||||
continue;
|
||||
emitter = (pn2->isKind(PNK_NAME))
|
||||
? EmitDestructuringDecl
|
||||
: EmitDestructuringDecls;
|
||||
if (!emitter(cx, bce, prologOp, pn2))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(pn->isKind(PNK_OBJECT));
|
||||
for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
|
||||
pn3 = pn2->pn_right;
|
||||
emitter = pn3->isKind(PNK_NAME) ? EmitDestructuringDecl : EmitDestructuringDecls;
|
||||
if (!emitter(cx, bce, prologOp, pn3))
|
||||
DestructuringDeclEmitter emitter =
|
||||
element->isKind(PNK_NAME) ? EmitDestructuringDecl : EmitDestructuringDecls;
|
||||
if (!emitter(cx, bce, prologOp, element))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(pattern->isKind(PNK_OBJECT));
|
||||
for (ParseNode *member = pattern->pn_head; member; member = member->pn_next) {
|
||||
ParseNode *target = member->pn_right;
|
||||
DestructuringDeclEmitter emitter =
|
||||
target->isKind(PNK_NAME) ? EmitDestructuringDecl : EmitDestructuringDecls;
|
||||
if (!emitter(cx, bce, prologOp, target))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -3127,25 +3126,29 @@ EmitDestructuringOpsHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode
|
||||
} else {
|
||||
JS_ASSERT(pn->isKind(PNK_OBJECT));
|
||||
JS_ASSERT(pn2->isKind(PNK_COLON));
|
||||
pn3 = pn2->pn_left;
|
||||
if (pn3->isKind(PNK_NUMBER)) {
|
||||
if (!EmitNumberOp(cx, pn3->pn_dval, bce))
|
||||
|
||||
ParseNode *key = pn2->pn_left;
|
||||
if (key->isKind(PNK_NUMBER)) {
|
||||
if (!EmitNumberOp(cx, key->pn_dval, bce))
|
||||
return false;
|
||||
} else {
|
||||
MOZ_ASSERT(key->isKind(PNK_STRING) || key->isKind(PNK_NAME));
|
||||
PropertyName *name = key->pn_atom->asPropertyName();
|
||||
|
||||
// The parser already checked for atoms representing indexes and
|
||||
// used PNK_NUMBER instead, but also watch for ids which TI treats
|
||||
// as indexes for simpliciation of downstream analysis.
|
||||
JS_ASSERT(pn3->isKind(PNK_STRING) || pn3->isKind(PNK_NAME));
|
||||
jsid id = NameToId(pn3->pn_atom->asPropertyName());
|
||||
// as indexes for simplification of downstream analysis.
|
||||
jsid id = NameToId(name);
|
||||
if (id != types::IdToTypeId(id)) {
|
||||
if (!EmitTree(cx, bce, pn3))
|
||||
if (!EmitTree(cx, bce, key))
|
||||
return false;
|
||||
} else {
|
||||
if (!EmitAtomOp(cx, pn3, JSOP_GETPROP, bce))
|
||||
if (!EmitAtomOp(cx, name, JSOP_GETPROP, bce))
|
||||
return false;
|
||||
doElemOp = false;
|
||||
}
|
||||
}
|
||||
|
||||
pn3 = pn2->pn_right;
|
||||
}
|
||||
|
||||
@ -5914,16 +5917,6 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
}
|
||||
|
||||
for (ParseNode *pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
|
||||
/* Handle __proto__ specially because it's not binary. */
|
||||
if (pn2->isKind(PNK_MUTATEPROTO)) {
|
||||
if (!EmitTree(cx, bce, pn2->pn_kid))
|
||||
return false;
|
||||
obj = nullptr;
|
||||
if (!Emit1(cx, bce, JSOP_MUTATEPROTO))
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Emit an index for t[2] for later consumption by JSOP_INITELEM. */
|
||||
ParseNode *pn3 = pn2->pn_left;
|
||||
bool isIndex = false;
|
||||
@ -5968,13 +5961,22 @@ EmitObject(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
return false;
|
||||
} else {
|
||||
JS_ASSERT(pn3->isKind(PNK_NAME) || pn3->isKind(PNK_STRING));
|
||||
|
||||
// If we have { __proto__: expr }, implement prototype mutation.
|
||||
if (op == JSOP_INITPROP && pn3->pn_atom == cx->names().proto) {
|
||||
obj = nullptr;
|
||||
if (Emit1(cx, bce, JSOP_MUTATEPROTO) < 0)
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
|
||||
jsatomid index;
|
||||
if (!bce->makeAtomIndex(pn3->pn_atom, &index))
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT((op == JSOP_INITPROP_GETTER || op == JSOP_INITPROP_SETTER) ||
|
||||
pn3->pn_atom != cx->names().proto,
|
||||
"__proto__ shouldn't have been generated as an initprop");
|
||||
MOZ_ASSERT(op == JSOP_INITPROP ||
|
||||
op == JSOP_INITPROP_GETTER ||
|
||||
op == JSOP_INITPROP_SETTER);
|
||||
|
||||
if (obj) {
|
||||
JS_ASSERT(!obj->inDictionaryMode());
|
||||
|
@ -235,14 +235,6 @@ class FullParseHandler
|
||||
return literal;
|
||||
}
|
||||
|
||||
bool addPrototypeMutation(ParseNode *literal, uint32_t begin, ParseNode *expr) {
|
||||
ParseNode *mutation = newUnary(PNK_MUTATEPROTO, JSOP_NOP, begin, expr);
|
||||
if (!mutation)
|
||||
return false;
|
||||
literal->append(mutation);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool addPropertyDefinition(ParseNode *literal, ParseNode *name, ParseNode *expr) {
|
||||
ParseNode *propdef = newBinary(PNK_COLON, name, expr, JSOP_INITPROP);
|
||||
if (!propdef)
|
||||
|
@ -139,7 +139,6 @@ class UpvarCookie
|
||||
F(FORHEAD) \
|
||||
F(ARGSBODY) \
|
||||
F(SPREAD) \
|
||||
F(MUTATEPROTO) \
|
||||
\
|
||||
/* Unary operators. */ \
|
||||
F(TYPEOF) \
|
||||
|
@ -3099,32 +3099,31 @@ Parser<FullParseHandler>::checkDestructuring(BindData<FullParseHandler> *data,
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(left->isKind(PNK_OBJECT));
|
||||
for (ParseNode *pair = left->pn_head; pair; pair = pair->pn_next) {
|
||||
JS_ASSERT(pair->isKind(PNK_COLON));
|
||||
ParseNode *pn = pair->pn_right;
|
||||
for (ParseNode *member = left->pn_head; member; member = member->pn_next) {
|
||||
MOZ_ASSERT(member->isKind(PNK_COLON));
|
||||
ParseNode *expr = member->pn_right;
|
||||
|
||||
if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) {
|
||||
ok = checkDestructuring(data, pn, false);
|
||||
if (expr->isKind(PNK_ARRAY) || expr->isKind(PNK_OBJECT)) {
|
||||
ok = checkDestructuring(data, expr, false);
|
||||
} else if (data) {
|
||||
if (!pn->isKind(PNK_NAME)) {
|
||||
report(ParseError, false, pn, JSMSG_NO_VARIABLE_NAME);
|
||||
if (!expr->isKind(PNK_NAME)) {
|
||||
report(ParseError, false, expr, JSMSG_NO_VARIABLE_NAME);
|
||||
return false;
|
||||
}
|
||||
ok = bindDestructuringVar(data, pn);
|
||||
ok = bindDestructuringVar(data, expr);
|
||||
} else {
|
||||
/*
|
||||
* If right and left point to the same node, then this is
|
||||
* destructuring shorthand ({x} = ...). In that case,
|
||||
* identifierName was not used to parse 'x' so 'x' has not been
|
||||
* officially linked to its def or registered in lexdeps. Do
|
||||
* that now.
|
||||
* If this is a destructuring shorthand ({x} = ...), then
|
||||
* identifierName wasn't used to parse |x|. As a result, |x|
|
||||
* hasn't been officially linked to its def or registered in
|
||||
* lexdeps. Do that now.
|
||||
*/
|
||||
if (pair->pn_right == pair->pn_left) {
|
||||
RootedPropertyName name(context, pn->pn_atom->asPropertyName());
|
||||
if (!noteNameUse(name, pn))
|
||||
if (member->pn_right == member->pn_left) {
|
||||
RootedPropertyName name(context, expr->pn_atom->asPropertyName());
|
||||
if (!noteNameUse(name, expr))
|
||||
return false;
|
||||
}
|
||||
ok = checkAndMarkAsAssignmentLhs(pn, KeyedDestructuringAssignment);
|
||||
ok = checkAndMarkAsAssignmentLhs(expr, KeyedDestructuringAssignment);
|
||||
}
|
||||
if (!ok)
|
||||
return false;
|
||||
@ -3659,8 +3658,9 @@ Parser<FullParseHandler>::letStatement()
|
||||
JS_ASSERT_IF(pn, pn->isKind(PNK_LET) || pn->isKind(PNK_SEMI));
|
||||
JS_ASSERT_IF(pn && pn->isKind(PNK_LET) && pn->pn_expr->getOp() != JSOP_POPNV,
|
||||
pn->pn_expr->isOp(JSOP_POPN));
|
||||
} else
|
||||
} else {
|
||||
pn = letDeclaration();
|
||||
}
|
||||
return pn;
|
||||
}
|
||||
|
||||
@ -6807,7 +6807,6 @@ Parser<ParseHandler>::objectLiteral()
|
||||
|
||||
JSOp op = JSOP_INITPROP;
|
||||
Node propname;
|
||||
uint32_t begin;
|
||||
switch (ltok) {
|
||||
case TOK_NUMBER:
|
||||
atom = DoubleToAtom(context, tokenStream.currentToken().number());
|
||||
@ -6826,10 +6825,6 @@ Parser<ParseHandler>::objectLiteral()
|
||||
propname = handler.newIdentifier(atom, pos());
|
||||
if (!propname)
|
||||
return null();
|
||||
if (atom == context->names().proto) {
|
||||
begin = pos().begin;
|
||||
op = JSOP_MUTATEPROTO;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -6898,7 +6893,7 @@ Parser<ParseHandler>::objectLiteral()
|
||||
return null();
|
||||
}
|
||||
|
||||
if (op == JSOP_INITPROP || op == JSOP_MUTATEPROTO) {
|
||||
if (op == JSOP_INITPROP) {
|
||||
TokenKind tt = tokenStream.getToken();
|
||||
Node propexpr;
|
||||
if (tt == TOK_COLON) {
|
||||
@ -6914,15 +6909,11 @@ Parser<ParseHandler>::objectLiteral()
|
||||
* so that we can later assume singleton objects delegate to
|
||||
* the default Object.prototype.
|
||||
*/
|
||||
if (!handler.isConstant(propexpr) || op == JSOP_MUTATEPROTO)
|
||||
if (!handler.isConstant(propexpr) || atom == context->names().proto)
|
||||
handler.setListFlag(literal, PNX_NONCONST);
|
||||
|
||||
if (op == JSOP_MUTATEPROTO
|
||||
? !handler.addPrototypeMutation(literal, begin, propexpr)
|
||||
: !handler.addPropertyDefinition(literal, propname, propexpr))
|
||||
{
|
||||
if (!handler.addPropertyDefinition(literal, propname, propexpr))
|
||||
return null();
|
||||
}
|
||||
}
|
||||
#if JS_HAS_DESTRUCTURING_SHORTHAND
|
||||
else if (ltok == TOK_NAME && (tt == TOK_COMMA || tt == TOK_RC)) {
|
||||
@ -6968,7 +6959,7 @@ Parser<ParseHandler>::objectLiteral()
|
||||
* any part of an accessor property.
|
||||
*/
|
||||
AssignmentType assignType;
|
||||
if (op == JSOP_INITPROP || op == JSOP_MUTATEPROTO)
|
||||
if (op == JSOP_INITPROP)
|
||||
assignType = VALUE;
|
||||
else if (op == JSOP_INITPROP_GETTER)
|
||||
assignType = GET;
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var gTestfile = 'destructuring-__proto__-shorthand-assignment-before-var.js';
|
||||
var BUGNUMBER = 963641;
|
||||
var summary = "{ __proto__ } should work as a destructuring assignment pattern";
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
/**************
|
||||
* BEGIN TEST *
|
||||
**************/
|
||||
|
||||
function objectWithProtoProperty(v)
|
||||
{
|
||||
var obj = {};
|
||||
return Object.defineProperty(obj, "__proto__",
|
||||
{
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: v
|
||||
});
|
||||
}
|
||||
|
||||
({ __proto__ } = objectWithProtoProperty(17));
|
||||
assertEq(__proto__, 17);
|
||||
|
||||
var { __proto__ } = objectWithProtoProperty(42);
|
||||
assertEq(__proto__, 42);
|
||||
|
||||
function nested()
|
||||
{
|
||||
({ __proto__ } = objectWithProtoProperty(undefined));
|
||||
assertEq(__proto__, undefined);
|
||||
|
||||
var { __proto__ } = objectWithProtoProperty("fnord");
|
||||
assertEq(__proto__, "fnord");
|
||||
}
|
||||
nested();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete");
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var gTestfile = 'destructuring-__proto__-shorthand-assignment.js';
|
||||
var BUGNUMBER = 963641;
|
||||
var summary = "{ __proto__ } should work as a destructuring assignment pattern";
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
/**************
|
||||
* BEGIN TEST *
|
||||
**************/
|
||||
|
||||
function objectWithProtoProperty(v)
|
||||
{
|
||||
var obj = {};
|
||||
return Object.defineProperty(obj, "__proto__",
|
||||
{
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: v
|
||||
});
|
||||
}
|
||||
|
||||
var { __proto__ } = objectWithProtoProperty(42);
|
||||
assertEq(__proto__, 42);
|
||||
|
||||
({ __proto__ } = objectWithProtoProperty(17));
|
||||
assertEq(__proto__, 17);
|
||||
|
||||
function nested()
|
||||
{
|
||||
var { __proto__ } = objectWithProtoProperty("fnord");
|
||||
assertEq(__proto__, "fnord");
|
||||
|
||||
({ __proto__ } = objectWithProtoProperty(undefined));
|
||||
assertEq(__proto__, undefined);
|
||||
}
|
||||
nested();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete");
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
*/
|
||||
|
||||
var gTestfile = 'destructuring-__proto__-target--assignment.js';
|
||||
var BUGNUMBER = 963641;
|
||||
var summary =
|
||||
"{ __proto__: target } should work as a destructuring assignment pattern";
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
/**************
|
||||
* BEGIN TEST *
|
||||
**************/
|
||||
|
||||
function objectWithProtoProperty(v)
|
||||
{
|
||||
var obj = {};
|
||||
return Object.defineProperty(obj, "__proto__",
|
||||
{
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
value: v
|
||||
});
|
||||
}
|
||||
|
||||
var { __proto__: target } = objectWithProtoProperty(null);
|
||||
assertEq(target, null);
|
||||
|
||||
({ __proto__: target } = objectWithProtoProperty("aacchhorrt"));
|
||||
assertEq(target, "aacchhorrt");
|
||||
|
||||
function nested()
|
||||
{
|
||||
var { __proto__: target } = objectWithProtoProperty(3.141592654);
|
||||
assertEq(target, 3.141592654);
|
||||
|
||||
({ __proto__: target } = objectWithProtoProperty(-0));
|
||||
assertEq(target, -0);
|
||||
}
|
||||
nested();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete");
|
Loading…
Reference in New Issue
Block a user