mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1165486 - Add StaticNonSyntacticScopeObjects and teach scope iterators about it. (r=luke)
This commit is contained in:
parent
c27c964ec1
commit
3c634f08a1
@ -1548,14 +1548,14 @@ BytecodeEmitter::tryConvertFreeName(ParseNode* pn)
|
|||||||
// Use generic ops if a catch block is encountered.
|
// Use generic ops if a catch block is encountered.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ssi.hasDynamicScopeObject())
|
if (ssi.hasSyntacticDynamicScopeObject())
|
||||||
hops++;
|
hops++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
RootedScript script(cx, ssi.funScript());
|
RootedScript script(cx, ssi.funScript());
|
||||||
if (script->functionNonDelazifying()->atom() == pn->pn_atom)
|
if (script->functionNonDelazifying()->atom() == pn->pn_atom)
|
||||||
return false;
|
return false;
|
||||||
if (ssi.hasDynamicScopeObject()) {
|
if (ssi.hasSyntacticDynamicScopeObject()) {
|
||||||
uint32_t slot;
|
uint32_t slot;
|
||||||
if (lookupAliasedName(script, pn->pn_atom->asPropertyName(), &slot, pn)) {
|
if (lookupAliasedName(script, pn->pn_atom->asPropertyName(), &slot, pn)) {
|
||||||
JSOp op;
|
JSOp op;
|
||||||
|
@ -1177,6 +1177,7 @@ PopScope(JSContext* cx, ScopeIter& si)
|
|||||||
break;
|
break;
|
||||||
case ScopeIter::Call:
|
case ScopeIter::Call:
|
||||||
case ScopeIter::Eval:
|
case ScopeIter::Eval:
|
||||||
|
case ScopeIter::NonSyntactic:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3934,7 +3935,7 @@ CASE(JSOP_SUPERBASE)
|
|||||||
{
|
{
|
||||||
ScopeIter si(cx, REGS.fp()->scopeChain(), REGS.fp()->script()->innermostStaticScope(REGS.pc));
|
ScopeIter si(cx, REGS.fp()->scopeChain(), REGS.fp()->script()->innermostStaticScope(REGS.pc));
|
||||||
for (; !si.done(); ++si) {
|
for (; !si.done(); ++si) {
|
||||||
if (si.hasScopeObject() && si.type() == ScopeIter::Call) {
|
if (si.hasSyntacticScopeObject() && si.type() == ScopeIter::Call) {
|
||||||
JSFunction& callee = si.scope().as<CallObject>().callee();
|
JSFunction& callee = si.scope().as<CallObject>().callee();
|
||||||
|
|
||||||
// Arrow functions don't have the information we're looking for,
|
// Arrow functions don't have the information we're looking for,
|
||||||
|
@ -84,6 +84,8 @@ StaticScopeIter<allowGC>::operator++(int)
|
|||||||
obj = obj->template as<NestedScopeObject>().enclosingScopeForStaticScopeIter();
|
obj = obj->template as<NestedScopeObject>().enclosingScopeForStaticScopeIter();
|
||||||
} else if (obj->template is<StaticEvalObject>()) {
|
} else if (obj->template is<StaticEvalObject>()) {
|
||||||
obj = obj->template as<StaticEvalObject>().enclosingScopeForStaticScopeIter();
|
obj = obj->template as<StaticEvalObject>().enclosingScopeForStaticScopeIter();
|
||||||
|
} else if (obj->template is<StaticNonSyntacticScopeObjects>()) {
|
||||||
|
obj = obj->template as<StaticNonSyntacticScopeObjects>().enclosingScopeForStaticScopeIter();
|
||||||
} else if (onNamedLambda || !obj->template as<JSFunction>().isNamedLambda()) {
|
} else if (onNamedLambda || !obj->template as<JSFunction>().isNamedLambda()) {
|
||||||
onNamedLambda = false;
|
onNamedLambda = false;
|
||||||
obj = obj->template as<JSFunction>().nonLazyScript()->enclosingStaticScope();
|
obj = obj->template as<JSFunction>().nonLazyScript()->enclosingStaticScope();
|
||||||
@ -92,27 +94,32 @@ StaticScopeIter<allowGC>::operator++(int)
|
|||||||
}
|
}
|
||||||
MOZ_ASSERT_IF(obj, obj->template is<NestedScopeObject>() ||
|
MOZ_ASSERT_IF(obj, obj->template is<NestedScopeObject>() ||
|
||||||
obj->template is<StaticEvalObject>() ||
|
obj->template is<StaticEvalObject>() ||
|
||||||
|
obj->template is<StaticNonSyntacticScopeObjects>() ||
|
||||||
obj->template is<JSFunction>());
|
obj->template is<JSFunction>());
|
||||||
MOZ_ASSERT_IF(onNamedLambda, obj->template is<JSFunction>());
|
MOZ_ASSERT_IF(onNamedLambda, obj->template is<JSFunction>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
template <AllowGC allowGC>
|
||||||
inline bool
|
inline bool
|
||||||
StaticScopeIter<allowGC>::hasDynamicScopeObject() const
|
StaticScopeIter<allowGC>::hasSyntacticDynamicScopeObject() const
|
||||||
{
|
{
|
||||||
return obj->template is<StaticBlockObject>()
|
if (obj->template is<JSFunction>())
|
||||||
? obj->template as<StaticBlockObject>().needsClone()
|
return obj->template as<JSFunction>().isHeavyweight();
|
||||||
: (obj->template is<StaticEvalObject>()
|
if (obj->template is<StaticBlockObject>())
|
||||||
? obj->template as<StaticEvalObject>().isStrict()
|
return obj->template as<StaticBlockObject>().needsClone();
|
||||||
: (obj->template is<StaticWithObject>() ||
|
if (obj->template is<StaticWithObject>())
|
||||||
obj->template as<JSFunction>().isHeavyweight()));
|
return true;
|
||||||
|
if (obj->template is<StaticEvalObject>())
|
||||||
|
return obj->template as<StaticEvalObject>().isStrict();
|
||||||
|
MOZ_ASSERT(obj->template is<StaticNonSyntacticScopeObjects>());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
template <AllowGC allowGC>
|
||||||
inline Shape*
|
inline Shape*
|
||||||
StaticScopeIter<allowGC>::scopeShape() const
|
StaticScopeIter<allowGC>::scopeShape() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(hasDynamicScopeObject());
|
MOZ_ASSERT(hasSyntacticDynamicScopeObject());
|
||||||
MOZ_ASSERT(type() != NamedLambda && type() != Eval);
|
MOZ_ASSERT(type() != NamedLambda && type() != Eval);
|
||||||
if (type() == Block)
|
if (type() == Block)
|
||||||
return block().lastProperty();
|
return block().lastProperty();
|
||||||
@ -131,6 +138,8 @@ StaticScopeIter<allowGC>::type() const
|
|||||||
? With
|
? With
|
||||||
: (obj->template is<StaticEvalObject>()
|
: (obj->template is<StaticEvalObject>()
|
||||||
? Eval
|
? Eval
|
||||||
|
: (obj->template is<StaticNonSyntacticScopeObjects>())
|
||||||
|
? NonSyntactic
|
||||||
: Function));
|
: Function));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +167,14 @@ StaticScopeIter<allowGC>::eval() const
|
|||||||
return obj->template as<StaticEvalObject>();
|
return obj->template as<StaticEvalObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <AllowGC allowGC>
|
||||||
|
inline StaticNonSyntacticScopeObjects&
|
||||||
|
StaticScopeIter<allowGC>::nonSyntactic() const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(type() == NonSyntactic);
|
||||||
|
return obj->template as<StaticNonSyntacticScopeObjects>();
|
||||||
|
}
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
template <AllowGC allowGC>
|
||||||
inline JSScript*
|
inline JSScript*
|
||||||
StaticScopeIter<allowGC>::funScript() const
|
StaticScopeIter<allowGC>::funScript() const
|
||||||
|
@ -43,7 +43,7 @@ js::ScopeCoordinateToStaticScopeShape(JSScript* script, jsbytecode* pc)
|
|||||||
uint32_t hops = ScopeCoordinate(pc).hops();
|
uint32_t hops = ScopeCoordinate(pc).hops();
|
||||||
while (true) {
|
while (true) {
|
||||||
MOZ_ASSERT(!ssi.done());
|
MOZ_ASSERT(!ssi.done());
|
||||||
if (ssi.hasDynamicScopeObject()) {
|
if (ssi.hasSyntacticDynamicScopeObject()) {
|
||||||
if (!hops)
|
if (!hops)
|
||||||
break;
|
break;
|
||||||
hops--;
|
hops--;
|
||||||
@ -107,7 +107,7 @@ js::ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc)
|
|||||||
StaticScopeIter<NoGC> ssi(script->innermostStaticScopeInScript(pc));
|
StaticScopeIter<NoGC> ssi(script->innermostStaticScopeInScript(pc));
|
||||||
uint32_t hops = ScopeCoordinate(pc).hops();
|
uint32_t hops = ScopeCoordinate(pc).hops();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (ssi.hasDynamicScopeObject()) {
|
if (ssi.hasSyntacticDynamicScopeObject()) {
|
||||||
if (!hops)
|
if (!hops)
|
||||||
break;
|
break;
|
||||||
hops--;
|
hops--;
|
||||||
@ -212,7 +212,7 @@ CallObject::create(JSContext* cx, HandleScript script, HandleObject enclosing, H
|
|||||||
if (!callobj)
|
if (!callobj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
callobj->as<ScopeObject>().setEnclosingScope(enclosing);
|
callobj->setEnclosingScope(enclosing);
|
||||||
callobj->initFixedSlot(CALLEE_SLOT, ObjectOrNullValue(callee));
|
callobj->initFixedSlot(CALLEE_SLOT, ObjectOrNullValue(callee));
|
||||||
|
|
||||||
if (script->treatAsRunOnce()) {
|
if (script->treatAsRunOnce()) {
|
||||||
@ -420,7 +420,7 @@ DynamicWithObject::create(JSContext* cx, HandleObject object, HandleObject enclo
|
|||||||
if (!thisp)
|
if (!thisp)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
obj->as<ScopeObject>().setEnclosingScope(enclosing);
|
obj->setEnclosingScope(enclosing);
|
||||||
obj->setFixedSlot(OBJECT_SLOT, ObjectValue(*object));
|
obj->setFixedSlot(OBJECT_SLOT, ObjectValue(*object));
|
||||||
obj->setFixedSlot(THIS_SLOT, ObjectValue(*thisp));
|
obj->setFixedSlot(THIS_SLOT, ObjectValue(*thisp));
|
||||||
obj->setFixedSlot(KIND_SLOT, Int32Value(kind));
|
obj->setFixedSlot(KIND_SLOT, Int32Value(kind));
|
||||||
@ -551,6 +551,25 @@ const Class StaticEvalObject::class_ = {
|
|||||||
JSCLASS_IS_ANONYMOUS
|
JSCLASS_IS_ANONYMOUS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* static */ StaticNonSyntacticScopeObjects*
|
||||||
|
StaticNonSyntacticScopeObjects::create(JSContext*cx, HandleObject enclosing)
|
||||||
|
{
|
||||||
|
StaticNonSyntacticScopeObjects* obj =
|
||||||
|
NewObjectWithNullTaggedProto<StaticNonSyntacticScopeObjects>(cx, TenuredObject,
|
||||||
|
BaseShape::DELEGATE);
|
||||||
|
if (!obj)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
obj->setReservedSlot(SCOPE_CHAIN_SLOT, ObjectOrNullValue(enclosing));
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Class StaticNonSyntacticScopeObjects::class_ = {
|
||||||
|
"StaticNonSyntacticScopeObjects",
|
||||||
|
JSCLASS_HAS_RESERVED_SLOTS(StaticNonSyntacticScopeObjects::RESERVED_SLOTS) |
|
||||||
|
JSCLASS_IS_ANONYMOUS
|
||||||
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
/* static */ ClonedBlockObject*
|
/* static */ ClonedBlockObject*
|
||||||
@ -845,7 +864,7 @@ UninitializedLexicalObject::create(JSContext* cx, HandleObject enclosing)
|
|||||||
BaseShape::DELEGATE);
|
BaseShape::DELEGATE);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
obj->as<ScopeObject>().setEnclosingScope(enclosing);
|
obj->setEnclosingScope(enclosing);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,7 +1002,14 @@ ScopeIter::ScopeIter(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc
|
|||||||
void
|
void
|
||||||
ScopeIter::incrementStaticScopeIter()
|
ScopeIter::incrementStaticScopeIter()
|
||||||
{
|
{
|
||||||
|
// If settled on a non-syntactic static scope, only increment ssi_ once
|
||||||
|
// we've iterated through all the non-syntactic dynamic ScopeObjects.
|
||||||
|
if (ssi_.type() == StaticScopeIter<CanGC>::NonSyntactic) {
|
||||||
|
if (!hasNonSyntacticScopeObject())
|
||||||
ssi_++;
|
ssi_++;
|
||||||
|
} else {
|
||||||
|
ssi_++;
|
||||||
|
}
|
||||||
|
|
||||||
// For named lambdas, DeclEnvObject scopes are always attached to their
|
// For named lambdas, DeclEnvObject scopes are always attached to their
|
||||||
// CallObjects. Skip it here, as they are special cased in users of
|
// CallObjects. Skip it here, as they are special cased in users of
|
||||||
@ -1010,7 +1036,7 @@ ScopeIter::settle()
|
|||||||
frame_ = NullFramePtr();
|
frame_ = NullFramePtr();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (!ssi_.done() && hasScopeObject()) {
|
if (!ssi_.done() && hasAnyScopeObject()) {
|
||||||
switch (ssi_.type()) {
|
switch (ssi_.type()) {
|
||||||
case StaticScopeIter<CanGC>::Function:
|
case StaticScopeIter<CanGC>::Function:
|
||||||
MOZ_ASSERT(scope_->as<CallObject>().callee().nonLazyScript() == ssi_.funScript());
|
MOZ_ASSERT(scope_->as<CallObject>().callee().nonLazyScript() == ssi_.funScript());
|
||||||
@ -1024,6 +1050,9 @@ ScopeIter::settle()
|
|||||||
case StaticScopeIter<CanGC>::Eval:
|
case StaticScopeIter<CanGC>::Eval:
|
||||||
MOZ_ASSERT(scope_->as<CallObject>().isForEval());
|
MOZ_ASSERT(scope_->as<CallObject>().isForEval());
|
||||||
break;
|
break;
|
||||||
|
case StaticScopeIter<CanGC>::NonSyntactic:
|
||||||
|
MOZ_ASSERT(!IsSyntacticScope(scope_));
|
||||||
|
break;
|
||||||
case StaticScopeIter<CanGC>::NamedLambda:
|
case StaticScopeIter<CanGC>::NamedLambda:
|
||||||
MOZ_CRASH("named lambda static scopes should have been skipped");
|
MOZ_CRASH("named lambda static scopes should have been skipped");
|
||||||
}
|
}
|
||||||
@ -1034,7 +1063,7 @@ ScopeIter::settle()
|
|||||||
ScopeIter&
|
ScopeIter&
|
||||||
ScopeIter::operator++()
|
ScopeIter::operator++()
|
||||||
{
|
{
|
||||||
if (hasScopeObject()) {
|
if (hasAnyScopeObject()) {
|
||||||
scope_ = &scope_->as<ScopeObject>().enclosingScope();
|
scope_ = &scope_->as<ScopeObject>().enclosingScope();
|
||||||
if (scope_->is<DeclEnvObject>())
|
if (scope_->is<DeclEnvObject>())
|
||||||
scope_ = &scope_->as<DeclEnvObject>().enclosingScope();
|
scope_ = &scope_->as<DeclEnvObject>().enclosingScope();
|
||||||
@ -1060,6 +1089,8 @@ ScopeIter::type() const
|
|||||||
return With;
|
return With;
|
||||||
case StaticScopeIter<CanGC>::Eval:
|
case StaticScopeIter<CanGC>::Eval:
|
||||||
return Eval;
|
return Eval;
|
||||||
|
case StaticScopeIter<CanGC>::NonSyntactic:
|
||||||
|
return NonSyntactic;
|
||||||
case StaticScopeIter<CanGC>::NamedLambda:
|
case StaticScopeIter<CanGC>::NamedLambda:
|
||||||
MOZ_CRASH("named lambda static scopes should have been skipped");
|
MOZ_CRASH("named lambda static scopes should have been skipped");
|
||||||
default:
|
default:
|
||||||
@ -1070,7 +1101,7 @@ ScopeIter::type() const
|
|||||||
ScopeObject&
|
ScopeObject&
|
||||||
ScopeIter::scope() const
|
ScopeIter::scope() const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(hasScopeObject());
|
MOZ_ASSERT(hasAnyScopeObject());
|
||||||
return scope_->as<ScopeObject>();
|
return scope_->as<ScopeObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1089,6 +1120,8 @@ ScopeIter::maybeStaticScope() const
|
|||||||
return &staticWith();
|
return &staticWith();
|
||||||
case StaticScopeIter<CanGC>::Eval:
|
case StaticScopeIter<CanGC>::Eval:
|
||||||
return &staticEval();
|
return &staticEval();
|
||||||
|
case StaticScopeIter<CanGC>::NonSyntactic:
|
||||||
|
return &staticNonSyntactic();
|
||||||
case StaticScopeIter<CanGC>::NamedLambda:
|
case StaticScopeIter<CanGC>::NamedLambda:
|
||||||
MOZ_CRASH("named lambda static scopes should have been skipped");
|
MOZ_CRASH("named lambda static scopes should have been skipped");
|
||||||
default:
|
default:
|
||||||
@ -1688,7 +1721,7 @@ const DebugScopeProxy DebugScopeProxy::singleton;
|
|||||||
DebugScopeObject::create(JSContext* cx, ScopeObject& scope, HandleObject enclosing)
|
DebugScopeObject::create(JSContext* cx, ScopeObject& scope, HandleObject enclosing)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(scope.compartment() == cx->compartment());
|
MOZ_ASSERT(scope.compartment() == cx->compartment());
|
||||||
MOZ_ASSERT(!IsSyntacticScope(enclosing));
|
MOZ_ASSERT(!enclosing->is<ScopeObject>());
|
||||||
|
|
||||||
RootedValue priv(cx, ObjectValue(scope));
|
RootedValue priv(cx, ObjectValue(scope));
|
||||||
JSObject* obj = NewProxyObject(cx, &DebugScopeProxy::singleton, priv,
|
JSObject* obj = NewProxyObject(cx, &DebugScopeProxy::singleton, priv,
|
||||||
@ -1950,7 +1983,7 @@ DebugScopes::addDebugScope(JSContext* cx, ScopeObject& scope, DebugScopeObject&
|
|||||||
DebugScopeObject*
|
DebugScopeObject*
|
||||||
DebugScopes::hasDebugScope(JSContext* cx, const ScopeIter& si)
|
DebugScopes::hasDebugScope(JSContext* cx, const ScopeIter& si)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!si.hasScopeObject());
|
MOZ_ASSERT(!si.hasSyntacticScopeObject());
|
||||||
|
|
||||||
DebugScopes* scopes = cx->compartment()->debugScopes;
|
DebugScopes* scopes = cx->compartment()->debugScopes;
|
||||||
if (!scopes)
|
if (!scopes)
|
||||||
@ -1966,7 +1999,7 @@ DebugScopes::hasDebugScope(JSContext* cx, const ScopeIter& si)
|
|||||||
bool
|
bool
|
||||||
DebugScopes::addDebugScope(JSContext* cx, const ScopeIter& si, DebugScopeObject& debugScope)
|
DebugScopes::addDebugScope(JSContext* cx, const ScopeIter& si, DebugScopeObject& debugScope)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!si.hasScopeObject());
|
MOZ_ASSERT(!si.hasSyntacticScopeObject());
|
||||||
MOZ_ASSERT(cx->compartment() == debugScope.compartment());
|
MOZ_ASSERT(cx->compartment() == debugScope.compartment());
|
||||||
MOZ_ASSERT_IF(si.withinInitialFrame() && si.initialFrame().isFunctionFrame(),
|
MOZ_ASSERT_IF(si.withinInitialFrame() && si.initialFrame().isFunctionFrame(),
|
||||||
!si.initialFrame().callee()->isGenerator());
|
!si.initialFrame().callee()->isGenerator());
|
||||||
@ -2184,7 +2217,7 @@ DebugScopes::updateLiveScopes(JSContext* cx)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (ScopeIter si(cx, frame, i.pc()); si.withinInitialFrame(); ++si) {
|
for (ScopeIter si(cx, frame, i.pc()); si.withinInitialFrame(); ++si) {
|
||||||
if (si.hasScopeObject()) {
|
if (si.hasSyntacticScopeObject()) {
|
||||||
MOZ_ASSERT(si.scope().compartment() == cx->compartment());
|
MOZ_ASSERT(si.scope().compartment() == cx->compartment());
|
||||||
DebugScopes* scopes = ensureCompartmentData(cx);
|
DebugScopes* scopes = ensureCompartmentData(cx);
|
||||||
if (!scopes)
|
if (!scopes)
|
||||||
@ -2302,7 +2335,7 @@ GetDebugScopeForScope(JSContext* cx, const ScopeIter& si)
|
|||||||
static DebugScopeObject*
|
static DebugScopeObject*
|
||||||
GetDebugScopeForMissing(JSContext* cx, const ScopeIter& si)
|
GetDebugScopeForMissing(JSContext* cx, const ScopeIter& si)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!si.hasScopeObject() && si.canHaveScopeObject());
|
MOZ_ASSERT(!si.hasSyntacticScopeObject() && si.canHaveSyntacticScopeObject());
|
||||||
|
|
||||||
if (DebugScopeObject* debugScope = DebugScopes::hasDebugScope(cx, si))
|
if (DebugScopeObject* debugScope = DebugScopes::hasDebugScope(cx, si))
|
||||||
return debugScope;
|
return debugScope;
|
||||||
@ -2369,6 +2402,8 @@ GetDebugScopeForMissing(JSContext* cx, const ScopeIter& si)
|
|||||||
case ScopeIter::With:
|
case ScopeIter::With:
|
||||||
case ScopeIter::Eval:
|
case ScopeIter::Eval:
|
||||||
MOZ_CRASH("should already have a scope");
|
MOZ_CRASH("should already have a scope");
|
||||||
|
case ScopeIter::NonSyntactic:
|
||||||
|
MOZ_CRASH("non-syntactic scopes cannot be synthesized");
|
||||||
}
|
}
|
||||||
if (!debugScope)
|
if (!debugScope)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -2383,11 +2418,11 @@ static JSObject*
|
|||||||
GetDebugScopeForNonScopeObject(const ScopeIter& si)
|
GetDebugScopeForNonScopeObject(const ScopeIter& si)
|
||||||
{
|
{
|
||||||
JSObject& enclosing = si.enclosingScope();
|
JSObject& enclosing = si.enclosingScope();
|
||||||
MOZ_ASSERT(!IsSyntacticScope(&enclosing));
|
MOZ_ASSERT(!enclosing.is<ScopeObject>());
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
JSObject* o = &enclosing;
|
JSObject* o = &enclosing;
|
||||||
while ((o = o->enclosingScope()))
|
while ((o = o->enclosingScope()))
|
||||||
MOZ_ASSERT(!IsSyntacticScope(o));
|
MOZ_ASSERT(!o->is<ScopeObject>());
|
||||||
#endif
|
#endif
|
||||||
return &enclosing;
|
return &enclosing;
|
||||||
}
|
}
|
||||||
@ -2400,10 +2435,10 @@ GetDebugScope(JSContext* cx, const ScopeIter& si)
|
|||||||
if (si.done())
|
if (si.done())
|
||||||
return GetDebugScopeForNonScopeObject(si);
|
return GetDebugScopeForNonScopeObject(si);
|
||||||
|
|
||||||
if (si.hasScopeObject())
|
if (si.hasAnyScopeObject())
|
||||||
return GetDebugScopeForScope(cx, si);
|
return GetDebugScopeForScope(cx, si);
|
||||||
|
|
||||||
if (si.canHaveScopeObject())
|
if (si.canHaveSyntacticScopeObject())
|
||||||
return GetDebugScopeForMissing(cx, si);
|
return GetDebugScopeForMissing(cx, si);
|
||||||
|
|
||||||
ScopeIter copy(cx, si);
|
ScopeIter copy(cx, si);
|
||||||
|
@ -22,6 +22,7 @@ namespace frontend { struct Definition; }
|
|||||||
|
|
||||||
class StaticWithObject;
|
class StaticWithObject;
|
||||||
class StaticEvalObject;
|
class StaticEvalObject;
|
||||||
|
class StaticNonSyntacticScopeObjects;
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ class StaticScopeIter
|
|||||||
obj->is<StaticBlockObject>() ||
|
obj->is<StaticBlockObject>() ||
|
||||||
obj->is<StaticWithObject>() ||
|
obj->is<StaticWithObject>() ||
|
||||||
obj->is<StaticEvalObject>() ||
|
obj->is<StaticEvalObject>() ||
|
||||||
|
obj->is<StaticNonSyntacticScopeObjects>() ||
|
||||||
obj->is<JSFunction>());
|
obj->is<JSFunction>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +83,7 @@ class StaticScopeIter
|
|||||||
obj->is<StaticBlockObject>() ||
|
obj->is<StaticBlockObject>() ||
|
||||||
obj->is<StaticWithObject>() ||
|
obj->is<StaticWithObject>() ||
|
||||||
obj->is<StaticEvalObject>() ||
|
obj->is<StaticEvalObject>() ||
|
||||||
|
obj->is<StaticNonSyntacticScopeObjects>() ||
|
||||||
obj->is<JSFunction>());
|
obj->is<JSFunction>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,16 +98,19 @@ class StaticScopeIter
|
|||||||
bool done() const;
|
bool done() const;
|
||||||
void operator++(int);
|
void operator++(int);
|
||||||
|
|
||||||
/* Return whether this static scope will be on the dynamic scope chain. */
|
// Return whether this static scope will have a syntactic scope (i.e. a
|
||||||
bool hasDynamicScopeObject() const;
|
// ScopeObject that isn't a non-syntactic With or
|
||||||
|
// NonSyntacticVariablesObject) on the dynamic scope chain.
|
||||||
|
bool hasSyntacticDynamicScopeObject() const;
|
||||||
Shape* scopeShape() const;
|
Shape* scopeShape() const;
|
||||||
|
|
||||||
enum Type { Function, Block, With, NamedLambda, Eval };
|
enum Type { Function, Block, With, NamedLambda, Eval, NonSyntactic };
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
|
||||||
StaticBlockObject& block() const;
|
StaticBlockObject& block() const;
|
||||||
StaticWithObject& staticWith() const;
|
StaticWithObject& staticWith() const;
|
||||||
StaticEvalObject& eval() const;
|
StaticEvalObject& eval() const;
|
||||||
|
StaticNonSyntacticScopeObjects& nonSyntactic() const;
|
||||||
JSScript* funScript() const;
|
JSScript* funScript() const;
|
||||||
JSFunction& fun() const;
|
JSFunction& fun() const;
|
||||||
};
|
};
|
||||||
@ -175,25 +181,27 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
|
|||||||
* scope objects is:
|
* scope objects is:
|
||||||
*
|
*
|
||||||
* JSObject Generic object
|
* JSObject Generic object
|
||||||
* \
|
* |
|
||||||
* ScopeObject Engine-internal scope
|
* ScopeObject---+---+ Engine-internal scope
|
||||||
* \ \ \ \
|
* | | | | |
|
||||||
* \ \ \ StaticEvalObject Placeholder so eval scopes may be iterated through
|
* | | | | StaticNonSyntacticScopeObjects See NB2
|
||||||
* \ \ \
|
* | | | |
|
||||||
* \ \ DeclEnvObject Holds name of recursive/heavyweight named lambda
|
* | | | StaticEvalObject Placeholder so eval scopes may be iterated through
|
||||||
* \ \
|
* | | |
|
||||||
* \ CallObject Scope of entire function or strict eval
|
* | | DeclEnvObject Holds name of recursive/heavyweight named lambda
|
||||||
* \
|
* | |
|
||||||
|
* | CallObject Scope of entire function or strict eval
|
||||||
|
* |
|
||||||
* NestedScopeObject Scope created for a statement
|
* NestedScopeObject Scope created for a statement
|
||||||
* \ \ \
|
* | | |
|
||||||
* \ \ StaticWithObject Template for "with" object in static scope chain
|
* | | StaticWithObject Template for "with" object in static scope chain
|
||||||
* \ \
|
* | |
|
||||||
* \ DynamicWithObject Run-time "with" object on scope chain
|
* | DynamicWithObject Run-time "with" object on scope chain
|
||||||
* \
|
* |
|
||||||
* BlockObject Shared interface of cloned/static block objects
|
* BlockObject Shared interface of cloned/static block objects
|
||||||
* \ \
|
* | |
|
||||||
* \ ClonedBlockObject let, switch, catch, for
|
* | ClonedBlockObject let, switch, catch, for
|
||||||
* \
|
* |
|
||||||
* StaticBlockObject See NB
|
* StaticBlockObject See NB
|
||||||
*
|
*
|
||||||
* This hierarchy represents more than just the interface hierarchy: reserved
|
* This hierarchy represents more than just the interface hierarchy: reserved
|
||||||
@ -206,6 +214,9 @@ ScopeCoordinateFunctionScript(JSScript* script, jsbytecode* pc);
|
|||||||
* are cloned at runtime. These objects should never escape into the wild and
|
* are cloned at runtime. These objects should never escape into the wild and
|
||||||
* support a restricted set of ScopeObject operations.
|
* support a restricted set of ScopeObject operations.
|
||||||
*
|
*
|
||||||
|
* NB2: StaticNonSyntacticScopeObjects notify either of 0+ non-syntactic
|
||||||
|
* DynamicWithObjects on the dynamic scope chain or a NonSyntacticScopeObject.
|
||||||
|
*
|
||||||
* See also "Debug scope objects" below.
|
* See also "Debug scope objects" below.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -352,8 +363,9 @@ class DeclEnvObject : public ScopeObject
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Static eval scope template objects on the static scope. Created at the
|
// Static eval scope placeholder objects on the static scope chain. Created at
|
||||||
// time of compiling the eval script, and set as its static enclosing scope.
|
// the time of compiling the eval script, and set as its static enclosing
|
||||||
|
// scope.
|
||||||
class StaticEvalObject : public ScopeObject
|
class StaticEvalObject : public ScopeObject
|
||||||
{
|
{
|
||||||
static const uint32_t STRICT_SLOT = 1;
|
static const uint32_t STRICT_SLOT = 1;
|
||||||
@ -383,6 +395,34 @@ class StaticEvalObject : public ScopeObject
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Static scope objects that stand in for one or more "polluting global"
|
||||||
|
// scopes on the dynamic scope chain.
|
||||||
|
//
|
||||||
|
// There are two flavors of polluting global scopes on the dynamic scope
|
||||||
|
// chain:
|
||||||
|
//
|
||||||
|
// 1. 0+ non-syntactic DynamicWithObjects. This static scope helps ScopeIter
|
||||||
|
// iterate these DynamicWithObjects.
|
||||||
|
//
|
||||||
|
// 2. 1 PlainObject that is a both a QualifiedVarObj and an UnqualifiedVarObj,
|
||||||
|
// created exclusively in js::ExecuteInGlobalAndReturnScope.
|
||||||
|
//
|
||||||
|
// Since this PlainObject is not a ScopeObject, ScopeIter cannot iterate
|
||||||
|
// through it. Instead, this PlainObject always comes after the syntactic
|
||||||
|
// portion of the dynamic scope chain in front of a GlobalObject.
|
||||||
|
class StaticNonSyntacticScopeObjects : public ScopeObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const unsigned RESERVED_SLOTS = 1;
|
||||||
|
static const Class class_;
|
||||||
|
|
||||||
|
static StaticNonSyntacticScopeObjects* create(JSContext* cx, HandleObject enclosing);
|
||||||
|
|
||||||
|
JSObject* enclosingScopeForStaticScopeIter() {
|
||||||
|
return getReservedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class NestedScopeObject : public ScopeObject
|
class NestedScopeObject : public ScopeObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -747,17 +787,20 @@ class ScopeIter
|
|||||||
inline JSObject& enclosingScope() const;
|
inline JSObject& enclosingScope() const;
|
||||||
|
|
||||||
// If !done():
|
// If !done():
|
||||||
enum Type { Call, Block, With, Eval };
|
enum Type { Call, Block, With, Eval, NonSyntactic };
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
|
||||||
inline bool hasScopeObject() const;
|
inline bool hasNonSyntacticScopeObject() const;
|
||||||
inline bool canHaveScopeObject() const;
|
inline bool hasSyntacticScopeObject() const;
|
||||||
|
inline bool hasAnyScopeObject() const;
|
||||||
|
inline bool canHaveSyntacticScopeObject() const;
|
||||||
ScopeObject& scope() const;
|
ScopeObject& scope() const;
|
||||||
|
|
||||||
JSObject* maybeStaticScope() const;
|
JSObject* maybeStaticScope() const;
|
||||||
StaticBlockObject& staticBlock() const { return ssi_.block(); }
|
StaticBlockObject& staticBlock() const { return ssi_.block(); }
|
||||||
StaticWithObject& staticWith() const { return ssi_.staticWith(); }
|
StaticWithObject& staticWith() const { return ssi_.staticWith(); }
|
||||||
StaticEvalObject& staticEval() const { return ssi_.eval(); }
|
StaticEvalObject& staticEval() const { return ssi_.eval(); }
|
||||||
|
StaticNonSyntacticScopeObjects& staticNonSyntactic() const { return ssi_.nonSyntactic(); }
|
||||||
JSFunction& fun() const { return ssi_.fun(); }
|
JSFunction& fun() const { return ssi_.fun(); }
|
||||||
|
|
||||||
bool withinInitialFrame() const { return !!frame_; }
|
bool withinInitialFrame() const { return !!frame_; }
|
||||||
@ -1054,16 +1097,50 @@ ScopeIter::done() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
ScopeIter::hasScopeObject() const
|
ScopeIter::hasSyntacticScopeObject() const
|
||||||
{
|
{
|
||||||
return ssi_.hasDynamicScopeObject();
|
return ssi_.hasSyntacticDynamicScopeObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
ScopeIter::canHaveScopeObject() const
|
ScopeIter::hasNonSyntacticScopeObject() const
|
||||||
{
|
{
|
||||||
// Non-strict eval scopes cannot have dynamic scope objects.
|
// The case we're worrying about here is a NonSyntactic static scope which
|
||||||
return !ssi_.done() && (type() != Eval || staticEval().isStrict());
|
// has 0+ corresponding non-syntactic DynamicWithObject scopes or a
|
||||||
|
// NonSyntacticVariablesObject.
|
||||||
|
if (ssi_.type() == StaticScopeIter<CanGC>::NonSyntactic) {
|
||||||
|
MOZ_ASSERT_IF(scope_->is<DynamicWithObject>(),
|
||||||
|
!scope_->as<DynamicWithObject>().isSyntactic());
|
||||||
|
return scope_->is<DynamicWithObject>();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
ScopeIter::hasAnyScopeObject() const
|
||||||
|
{
|
||||||
|
return hasSyntacticScopeObject() || hasNonSyntacticScopeObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
ScopeIter::canHaveSyntacticScopeObject() const
|
||||||
|
{
|
||||||
|
if (ssi_.done())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (type()) {
|
||||||
|
case Call:
|
||||||
|
return true;
|
||||||
|
case Block:
|
||||||
|
return true;
|
||||||
|
case With:
|
||||||
|
return true;
|
||||||
|
case Eval:
|
||||||
|
// Only strict eval scopes can have dynamic scope objects.
|
||||||
|
return staticEval().isStrict();
|
||||||
|
case NonSyntactic:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSObject&
|
inline JSObject&
|
||||||
|
@ -153,7 +153,12 @@ AssertDynamicScopeMatchesStaticScope(JSContext* cx, JSScript* script, JSObject*
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
RootedObject enclosingScope(cx, script->enclosingStaticScope());
|
RootedObject enclosingScope(cx, script->enclosingStaticScope());
|
||||||
for (StaticScopeIter<NoGC> i(enclosingScope); !i.done(); i++) {
|
for (StaticScopeIter<NoGC> i(enclosingScope); !i.done(); i++) {
|
||||||
if (i.hasDynamicScopeObject()) {
|
if (i.type() == StaticScopeIter<NoGC>::NonSyntactic) {
|
||||||
|
while (scope->is<DynamicWithObject>()) {
|
||||||
|
MOZ_ASSERT(!scope->as<DynamicWithObject>().isSyntactic());
|
||||||
|
scope = &scope->as<DynamicWithObject>().enclosingScope();
|
||||||
|
}
|
||||||
|
} else if (i.hasSyntacticDynamicScopeObject()) {
|
||||||
switch (i.type()) {
|
switch (i.type()) {
|
||||||
case StaticScopeIter<NoGC>::Function:
|
case StaticScopeIter<NoGC>::Function:
|
||||||
MOZ_ASSERT(scope->as<CallObject>().callee().nonLazyScript() == i.funScript());
|
MOZ_ASSERT(scope->as<CallObject>().callee().nonLazyScript() == i.funScript());
|
||||||
@ -173,13 +178,16 @@ AssertDynamicScopeMatchesStaticScope(JSContext* cx, JSScript* script, JSObject*
|
|||||||
case StaticScopeIter<NoGC>::Eval:
|
case StaticScopeIter<NoGC>::Eval:
|
||||||
scope = &scope->as<CallObject>().enclosingScope();
|
scope = &scope->as<CallObject>().enclosingScope();
|
||||||
break;
|
break;
|
||||||
|
case StaticScopeIter<NoGC>::NonSyntactic:
|
||||||
|
MOZ_CRASH("NonSyntactic should not have a syntactic scope");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The scope chain is always ended by one or more non-syntactic
|
// The scope chain is always ended by one or more non-syntactic
|
||||||
// ScopeObjects (viz. GlobalObject or a non-syntactic WithObject).
|
// ScopeObjects (viz. GlobalObject or an unqualified varobj).
|
||||||
MOZ_ASSERT(!IsSyntacticScope(scope));
|
MOZ_ASSERT(!scope->is<ScopeObject>());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +254,7 @@ InterpreterFrame::epilogue(JSContext* cx)
|
|||||||
DebugScopes::onPopStrictEvalScope(this);
|
DebugScopes::onPopStrictEvalScope(this);
|
||||||
} else if (isDirectEvalFrame()) {
|
} else if (isDirectEvalFrame()) {
|
||||||
if (isDebuggerEvalFrame())
|
if (isDebuggerEvalFrame())
|
||||||
MOZ_ASSERT(!IsSyntacticScope(scopeChain()));
|
MOZ_ASSERT(!scopeChain()->is<ScopeObject>());
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Debugger.Object.prototype.evalInGlobal creates indirect eval
|
* Debugger.Object.prototype.evalInGlobal creates indirect eval
|
||||||
|
Loading…
Reference in New Issue
Block a user