diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index e4816fc5423..2d7cfb1b57b 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -2356,13 +2356,14 @@ BytecodeEmitter::checkRunOnceContext() bool BytecodeEmitter::needsImplicitThis() { - if (sc->isFunctionBox() && sc->asFunctionBox()->inWith) + if (sc->inWith()) return true; for (StmtInfoBCE* stmt = topStmt; stmt; stmt = stmt->down) { if (stmt->type == STMT_WITH) return true; } + return false; } diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 035eeef8581..1084e609618 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -596,7 +596,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct bufEnd(0), length(0), generatorKindBits_(GeneratorKindAsBits(generatorKind)), - inWith(false), // initialized below + inWith_(false), // initialized below inGenexpLambda(false), hasDestructuringArgs(false), useAsm(false), @@ -612,7 +612,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct MOZ_ASSERT(fun->isTenured()); if (!outerpc) { - inWith = false; + inWith_ = false; } else if (outerpc->parsingWith) { // This covers cases that don't involve eval(). For example: @@ -621,7 +621,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct // // In this case, |outerpc| corresponds to global code, and // outerpc->parsingWith is true. - inWith = true; + inWith_ = true; } else if (outerpc->sc->isFunctionBox()) { // This is like the above case, but for more deeply nested functions. @@ -632,8 +632,8 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct // In this case, the inner anonymous function needs to inherit the // setting of |inWith| from the outer one. FunctionBox* parent = outerpc->sc->asFunctionBox(); - if (parent && parent->inWith) - inWith = true; + if (parent && parent->inWith()) + inWith_ = true; } else { // This is like the above case, but when inside eval. // @@ -642,7 +642,7 @@ FunctionBox::FunctionBox(ExclusiveContext* cx, ObjectBox* traceListHead, JSFunct // with(o) { eval("(function() { g(); })();"); } // // In this case, the static scope chain tells us the presence of with. - inWith = outerpc->sc->asGlobalSharedContext()->inWith(); + inWith_ = outerpc->sc->inWith(); } } @@ -2224,7 +2224,7 @@ Parser::finishFunctionDefinition(Node pn, FunctionBox* funbo // while its ParseContext and associated lexdeps and inner functions are // still available. - if (funbox->inWith) + if (funbox->inWith()) return abortIfSyntaxParser(); size_t numFreeVariables = pc->lexdeps->count(); diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index 85c9ad47b45..91945195903 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -235,6 +235,7 @@ class SharedContext SuperProperty }; virtual bool allowSyntax(AllowedSyntax allowed) const = 0; + virtual bool inWith() const = 0; protected: static bool FunctionAllowsSyntax(JSFunction* func, AllowedSyntax allowed) @@ -257,19 +258,11 @@ class GlobalSharedContext : public SharedContext { private: Handle topStaticScope_; + bool allowNewTarget_; + bool allowSuperProperty_; + bool inWith_; - public: - GlobalSharedContext(ExclusiveContext* cx, - Directives directives, Handle topStaticScope, - bool extraWarnings) - : SharedContext(cx, directives, extraWarnings), - topStaticScope_(topStaticScope) - {} - - ObjectBox* toObjectBox() { return nullptr; } - HandleObject topStaticScope() const { return topStaticScope_; } - - bool allowSyntax(AllowedSyntax allowed) const { + bool computeAllowSyntax(AllowedSyntax allowed) const { StaticScopeIter it(context, topStaticScope_); for (; !it.done(); it++) { if (it.type() == StaticScopeIter::Function && @@ -281,13 +274,39 @@ class GlobalSharedContext : public SharedContext return false; } - bool inWith() const { + bool computeInWith() const { for (StaticScopeIter it(context, topStaticScope_); !it.done(); it++) { if (it.type() == StaticScopeIter::With) return true; } return false; } + + public: + GlobalSharedContext(ExclusiveContext* cx, + Directives directives, Handle topStaticScope, + bool extraWarnings) + : SharedContext(cx, directives, extraWarnings), + topStaticScope_(topStaticScope), + allowNewTarget_(computeAllowSyntax(AllowedSyntax::NewTarget)), + allowSuperProperty_(computeAllowSyntax(AllowedSyntax::SuperProperty)), + inWith_(computeInWith()) + {} + + ObjectBox* toObjectBox() { return nullptr; } + HandleObject topStaticScope() const { return topStaticScope_; } + bool allowSyntax(AllowedSyntax allowSyntax) const override { + switch (allowSyntax) { + case AllowedSyntax::NewTarget: + // Any function supports new.target + return allowNewTarget_; + case AllowedSyntax::SuperProperty: + return allowSuperProperty_; + default:; + } + MOZ_CRASH("Unknown AllowedSyntax query"); + } + bool inWith() const override { return inWith_; } }; class FunctionBox : public ObjectBox, public SharedContext @@ -301,7 +320,7 @@ class FunctionBox : public ObjectBox, public SharedContext uint16_t length; uint8_t generatorKindBits_; /* The GeneratorKind of this function. */ - bool inWith:1; /* some enclosing scope is a with-statement */ + bool inWith_:1; /* some enclosing scope is a with-statement */ bool inGenexpLambda:1; /* lambda from generator expression */ bool hasDestructuringArgs:1; /* arguments list contains destructuring expression */ bool useAsm:1; /* see useAsmOrInsideUseAsm */ @@ -380,9 +399,13 @@ class FunctionBox : public ObjectBox, public SharedContext isGenerator(); } - bool allowSyntax(AllowedSyntax allowed) const { + bool allowSyntax(AllowedSyntax allowed) const override { return FunctionAllowsSyntax(function(), allowed); } + + bool inWith() const override { + return inWith_; + } }; inline FunctionBox*