From c00fc2c512bfbd9b99bb4ffb0fb8f7d8cb8cda9c Mon Sep 17 00:00:00 2001 From: Eric Faust Date: Tue, 10 Mar 2015 20:27:34 -0700 Subject: [PATCH] Bug 1066234 - Part 6: Emitter support for 'extends' in ES6 Classes. (r=jorendorff) --- js/src/frontend/BytecodeEmitter.cpp | 32 ++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index ef575252f095..22f654cf44ed 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -5360,7 +5360,7 @@ EmitFor(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top } static MOZ_NEVER_INLINE bool -EmitFunc(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn) +EmitFunc(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool needsProto = false) { FunctionBox *funbox = pn->pn_funbox; RootedFunction fun(cx, funbox->function()); @@ -5459,7 +5459,13 @@ EmitFunc(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn) MOZ_ASSERT(fun->isArrow() == (pn->getOp() == JSOP_LAMBDA_ARROW)); if (fun->isArrow() && Emit1(cx, bce, JSOP_THIS) < 0) return false; + if (needsProto) { + MOZ_ASSERT(pn->getOp() == JSOP_LAMBDA); + pn->setOp(JSOP_FUNWITHPROTO); + } return EmitIndex32(cx, pn->getOp(), index, bce); + } else { + MOZ_ASSERT(!needsProto); } /* @@ -6942,7 +6948,7 @@ EmitClass(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn) ClassNames *names = classNode.names(); - MOZ_ASSERT(!classNode.heritage(), "For now, no heritage expressions"); + ParseNode *heritageExpression = classNode.heritage(); LexicalScopeNode *innerBlock = classNode.scope(); ParseNode *classMethods = innerBlock->pn_expr; @@ -6967,11 +6973,27 @@ EmitClass(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn) if (!EnterBlockScope(cx, bce, &stmtInfo, innerBlock->pn_objbox, JSOP_UNINITIALIZED)) return false; - if (!EmitFunc(cx, bce, constructor)) + if (heritageExpression) { + if (!EmitTree(cx, bce, heritageExpression)) + return false; + if (Emit1(cx, bce, JSOP_CLASSHERITAGE) < 0) + return false; + } + + if (!EmitFunc(cx, bce, constructor, !!heritageExpression)) return false; - if (!EmitNewInit(cx, bce, JSProto_Object)) - return false; + if (heritageExpression) { + // JSOP_CLASSHERITAGE leaves both prototypes on the stack. After + // creating the constructor, trickly it to the bottom to make the object. + if (Emit1(cx, bce, JSOP_SWAP) < 0) + return false; + if (Emit1(cx, bce, JSOP_OBJWITHPROTO) < 0) + return false; + } else { + if (!EmitNewInit(cx, bce, JSProto_Object)) + return false; + } if (Emit1(cx, bce, JSOP_DUP2) < 0) return false;