Bug 1168992 - Part 2: Fix reflection of new.target. (r=Waldo)

This commit is contained in:
Eric Faust 2015-09-02 15:09:03 -07:00
Родитель 919c23ca38
Коммит 371c557f97
15 изменённых файлов: 83 добавлений и 21 удалений

Просмотреть файл

@ -756,7 +756,7 @@ class NodeBuilder
bool generatorExpression(HandleValue body, NodeVector& blocks, HandleValue filter,
bool isLegacy, TokenPos* pos, MutableHandleValue dst);
bool newTargetExpression(TokenPos* pos, MutableHandleValue dst);
bool metaProperty(HandleValue meta, HandleValue property, TokenPos* pos, MutableHandleValue dst);
/*
* declarations
@ -1826,13 +1826,16 @@ NodeBuilder::classDefinition(bool expr, HandleValue name, HandleValue heritage,
}
bool
NodeBuilder::newTargetExpression(TokenPos* pos, MutableHandleValue dst)
NodeBuilder::metaProperty(HandleValue meta, HandleValue property, TokenPos* pos, MutableHandleValue dst)
{
RootedValue cb(cx, callbacks[AST_NEWTARGET_EXPR]);
RootedValue cb(cx, callbacks[AST_METAPROPERTY]);
if (!cb.isNull())
return callback(cb, pos, dst);
return callback(cb, meta, property, pos, dst);
return newNode(AST_NEWTARGET_EXPR, pos, dst);
return newNode(AST_METAPROPERTY, pos,
"meta", meta,
"property", property,
dst);
}
namespace {
@ -3312,7 +3315,22 @@ ASTSerializer::expression(ParseNode* pn, MutableHandleValue dst)
return classDefinition(pn, true, dst);
case PNK_NEWTARGET:
return builder.newTargetExpression(&pn->pn_pos, dst);
{
MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER));
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER));
MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
RootedValue newIdent(cx);
RootedValue targetIdent(cx);
RootedAtom newStr(cx, cx->names().new_);
RootedAtom targetStr(cx, cx->names().target);
return identifier(newStr, &pn->pn_left->pn_pos, &newIdent) &&
identifier(targetStr, &pn->pn_right->pn_pos, &targetIdent) &&
builder.metaProperty(newIdent, targetIdent, &pn->pn_pos, dst);
}
default:
LOCAL_NOT_REACHED("unexpected expression type");

Просмотреть файл

@ -1915,7 +1915,6 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
switch (pn->getKind()) {
// Trivial cases with no side effects.
case PNK_NEWTARGET:
case PNK_NOP:
case PNK_STRING:
case PNK_TEMPLATE_STRING:
@ -1932,6 +1931,14 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
*answer = false;
return true;
// Trivial binary nodes with more token pos holders.
case PNK_NEWTARGET:
MOZ_ASSERT(pn->isArity(PN_BINARY));
MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER));
MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER));
*answer = false;
return true;
case PNK_BREAK:
case PNK_CONTINUE:
case PNK_DEBUGGER:
@ -2320,6 +2327,7 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
case PNK_EXPORT_SPEC_LIST: // by PNK_EXPORT
case PNK_EXPORT_SPEC: // by PNK_EXPORT
case PNK_CALLSITEOBJ: // by PNK_TAGGED_TEMPLATE
case PNK_POSHOLDER: // by PNK_NEWTARGET
MOZ_CRASH("handled by parent nodes");
case PNK_LIMIT: // invalid sentinel value
@ -8088,6 +8096,9 @@ BytecodeEmitter::emitTree(ParseNode* pn)
return false;
break;
case PNK_POSHOLDER:
MOZ_ASSERT_UNREACHABLE("Should never try to emit PNK_POSHOLDER");
default:
MOZ_ASSERT(0);
}

Просмотреть файл

@ -417,6 +417,7 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
case PNK_SUPERPROP:
case PNK_SUPERELEM:
case PNK_NEWTARGET:
case PNK_POSHOLDER:
MOZ_CRASH("ContainsHoistedDeclaration should have indicated false on "
"some parent node without recurring to test this node");
@ -1709,7 +1710,6 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
ParseNode* pn = *pnp;
switch (pn->getKind()) {
case PNK_NEWTARGET:
case PNK_NOP:
case PNK_REGEXP:
case PNK_STRING:
@ -1728,6 +1728,7 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
case PNK_OBJECT_PROPERTY_NAME:
case PNK_SUPERPROP:
case PNK_FRESHENBLOCK:
case PNK_POSHOLDER:
MOZ_ASSERT(pn->isArity(PN_NULLARY));
return true;
@ -1918,6 +1919,12 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
return Fold(cx, &pn->pn_left, parser, inGenexpLambda) &&
Fold(cx, &pn->pn_right, parser, inGenexpLambda);
case PNK_NEWTARGET:
MOZ_ASSERT(pn->isArity(PN_BINARY));
MOZ_ASSERT(pn->pn_left->isKind(PNK_POSHOLDER));
MOZ_ASSERT(pn->pn_right->isKind(PNK_POSHOLDER));
return true;
case PNK_CLASSNAMES:
MOZ_ASSERT(pn->isArity(PN_BINARY));
if (ParseNode*& outerBinding = pn->pn_left) {

Просмотреть файл

@ -352,8 +352,11 @@ class FullParseHandler
ParseNode* newSuperElement(ParseNode* expr, const TokenPos& pos) {
return new_<SuperElement>(expr, pos);
}
ParseNode* newNewTarget(const TokenPos& pos) {
return new_<NullaryNode>(PNK_NEWTARGET, pos);
ParseNode* newNewTarget(ParseNode* newHolder, ParseNode* targetHolder) {
return new_<BinaryNode>(PNK_NEWTARGET, JSOP_NOP, newHolder, targetHolder);
}
ParseNode* newPosHolder(const TokenPos& pos) {
return new_<NullaryNode>(PNK_POSHOLDER, pos);
}
bool addPrototypeMutation(ParseNode* literal, uint32_t begin, ParseNode* expr) {

Просмотреть файл

@ -377,7 +377,6 @@ class NameResolver
case PNK_FRESHENBLOCK:
case PNK_SUPERPROP:
case PNK_OBJECT_PROPERTY_NAME:
case PNK_NEWTARGET:
MOZ_ASSERT(cur->isArity(PN_NULLARY));
break;
@ -387,6 +386,12 @@ class NameResolver
MOZ_ASSERT(!cur->pn_kid->maybeExpr());
break;
case PNK_NEWTARGET:
MOZ_ASSERT(cur->isArity(PN_BINARY));
MOZ_ASSERT(cur->pn_left->isKind(PNK_POSHOLDER));
MOZ_ASSERT(cur->pn_right->isKind(PNK_POSHOLDER));
break;
// Nodes with a single non-null child requiring name resolution.
case PNK_TYPEOFEXPR:
case PNK_VOID:
@ -779,6 +784,7 @@ class NameResolver
case PNK_EXPORT_SPEC: // by PNK_EXPORT_SPEC_LIST
case PNK_CALLSITEOBJ: // by PNK_TAGGED_TEMPLATE
case PNK_CLASSNAMES: // by PNK_CLASS
case PNK_POSHOLDER: // by PNK_NEWTARGET
MOZ_CRASH("should have been handled by a parent node");
case PNK_LIMIT: // invalid sentinel value

Просмотреть файл

@ -215,7 +215,7 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
case PNK_OBJECT_PROPERTY_NAME:
case PNK_FRESHENBLOCK:
case PNK_SUPERPROP:
case PNK_NEWTARGET:
case PNK_POSHOLDER:
MOZ_ASSERT(pn->isArity(PN_NULLARY));
MOZ_ASSERT(!pn->isUsed(), "handle non-trivial cases separately");
MOZ_ASSERT(!pn->isDefn(), "handle non-trivial cases separately");
@ -285,6 +285,7 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
case PNK_SWITCH:
case PNK_LETBLOCK:
case PNK_CLASSMETHOD:
case PNK_NEWTARGET:
case PNK_FOR: {
MOZ_ASSERT(pn->isArity(PN_BINARY));
stack->push(pn->pn_left);

Просмотреть файл

@ -179,6 +179,7 @@ class PackedScopeCoordinate
F(SUPERPROP) \
F(SUPERELEM) \
F(NEWTARGET) \
F(POSHOLDER) \
\
/* Unary operators. */ \
F(TYPEOFNAME) \

Просмотреть файл

@ -8949,9 +8949,14 @@ Parser<ParseHandler>::tryNewTarget(Node &newTarget)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_NEW));
uint32_t begin = pos().begin;
newTarget = null();
Node newHolder = handler.newPosHolder(pos());
if (!newHolder)
return false;
uint32_t begin = pos().begin;
// |new| expects to look for an operand, so we will honor that.
TokenKind next;
if (!tokenStream.getToken(&next, TokenStream::Operand))
@ -8975,7 +8980,11 @@ Parser<ParseHandler>::tryNewTarget(Node &newTarget)
return false;
}
newTarget = handler.newNewTarget(TokenPos(begin, pos().end));
Node targetHolder = handler.newPosHolder(pos());
if (!targetHolder)
return false;
newTarget = handler.newNewTarget(newHolder, targetHolder);
return !!newTarget;
}

Просмотреть файл

@ -281,7 +281,8 @@ class SyntaxParseHandler
Node newSuperElement(Node expr, const TokenPos& pos) {
return NodeSuperElement;
}
Node newNewTarget(const TokenPos& pos) { return NodeGeneric; }
Node newNewTarget(Node newHolder, Node targetHolder) { return NodeGeneric; }
Node newPosHolder(const TokenPos& pos) { return NodeGeneric; }
bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
bool addPropertyDefinition(Node literal, Node name, Node expr) { return true; }

Просмотреть файл

@ -38,7 +38,7 @@ ASTDEF(AST_COMP_EXPR, "ComprehensionExpression", "comprehensi
ASTDEF(AST_GENERATOR_EXPR, "GeneratorExpression", "generatorExpression")
ASTDEF(AST_YIELD_EXPR, "YieldExpression", "yieldExpression")
ASTDEF(AST_CLASS_EXPR, "ClassExpression", "classExpression")
ASTDEF(AST_NEWTARGET_EXPR, "NewTargetExpression", "newTargetExpression")
ASTDEF(AST_METAPROPERTY, "MetaProperty", "metaProperty")
ASTDEF(AST_EMPTY_STMT, "EmptyStatement", "emptyStatement")
ASTDEF(AST_BLOCK_STMT, "BlockStatement", "blockStatement")

Просмотреть файл

@ -76,7 +76,6 @@ const char js_import_str[] = "import";
const char js_in_str[] = "in";
const char js_instanceof_str[] = "instanceof";
const char js_interface_str[] = "interface";
const char js_new_str[] = "new";
const char js_package_str[] = "package";
const char js_private_str[] = "private";
const char js_protected_str[] = "protected";

Просмотреть файл

@ -176,7 +176,6 @@ extern const char js_import_str[];
extern const char js_in_str[];
extern const char js_instanceof_str[];
extern const char js_interface_str[];
extern const char js_new_str[];
extern const char js_package_str[];
extern const char js_private_str[];
extern const char js_protected_str[];

Просмотреть файл

@ -170,9 +170,15 @@ function arrowExpr(args, body) {
body: body });
}
function newTarget() {
return Pattern({ type: "NewTargetExpression" });
function metaProperty(meta, property) {
return Pattern({ type: "MetaProperty",
meta: meta,
property: property });
}
function newTarget() {
return metaProperty(ident("new"), ident("target"));
}
function unExpr(op, arg) {
return Pattern({ type: "UnaryExpression", operator: op, argument: arg });
}

Просмотреть файл

@ -150,6 +150,7 @@
macro(multiline, multiline, "multiline") \
macro(name, name, "name") \
macro(NaN, NaN, "NaN") \
macro(new, new_, "new") \
macro(next, next, "next") \
macro(NFC, NFC, "NFC") \
macro(NFD, NFD, "NFD") \

Просмотреть файл

@ -769,7 +769,7 @@
* Stack: callee, this, args[0], ..., args[argc-1], newTarget => rval
* nuses: (argc+3)
*/ \
macro(JSOP_NEW, 82, js_new_str, NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) \
macro(JSOP_NEW, 82, "new", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) \
/*
* Pushes newly created object onto the stack with provided [[Prototype]].
*