mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Address bug 638316 and bug 694247 review comments, r=luke.
This commit is contained in:
parent
708b16abe9
commit
831cd84d89
@ -48,7 +48,6 @@
|
||||
#include "nsJSUtils.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "prprf.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptObjectOwner.h"
|
||||
@ -107,7 +106,7 @@ nsJSUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj)
|
||||
if (!glob)
|
||||
return nsnull;
|
||||
|
||||
glob = js::GetObjectGlobal(glob);
|
||||
glob = JS_GetGlobalForObject(aContext, glob);
|
||||
NS_ABORT_IF_FALSE(glob, "Infallible returns null");
|
||||
|
||||
clazz = JS_GET_CLASS(aContext, glob);
|
||||
|
@ -3071,6 +3071,7 @@ JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetParent(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(!obj->isInternalScope());
|
||||
assertSameCompartment(cx, obj);
|
||||
return obj->getParent();
|
||||
}
|
||||
@ -3079,7 +3080,7 @@ JS_PUBLIC_API(JSBool)
|
||||
JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
JS_ASSERT(!obj->isScope());
|
||||
JS_ASSERT(!obj->isInternalScope());
|
||||
JS_ASSERT(parent || !obj->getParent());
|
||||
assertSameCompartment(cx, obj, parent);
|
||||
return obj->setParent(cx, parent);
|
||||
@ -4357,7 +4358,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
|
||||
JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
|
||||
return NULL;
|
||||
}
|
||||
obj = obj->getParentOrScopeChain();
|
||||
obj = obj->scopeChain();
|
||||
}
|
||||
|
||||
Value v;
|
||||
|
@ -180,19 +180,13 @@ AutoSwitchCompartment::~AutoSwitchCompartment()
|
||||
JS_FRIEND_API(bool)
|
||||
js::IsScopeObject(const JSObject *obj)
|
||||
{
|
||||
return obj->isScope();
|
||||
return obj->isInternalScope();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js::GetObjectParentMaybeScope(const JSObject *obj)
|
||||
{
|
||||
return obj->getParentOrScopeChain();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js::GetObjectGlobal(JSObject *obj)
|
||||
{
|
||||
return obj->getGlobal();
|
||||
return obj->scopeChain();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(uint32)
|
||||
|
@ -283,9 +283,6 @@ GetObjectParent(const JSObject *obj)
|
||||
JS_FRIEND_API(JSObject *)
|
||||
GetObjectParentMaybeScope(const JSObject *obj);
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
GetObjectGlobal(JSObject *obj);
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
IsOriginalScriptFunction(JSFunction *fun);
|
||||
|
||||
|
@ -718,7 +718,7 @@ NewDeclEnvObject(JSContext *cx, StackFrame *fp)
|
||||
envobj->initialize(emptyDeclEnvShape, type, NULL);
|
||||
envobj->setPrivate(fp);
|
||||
|
||||
if (!envobj->setScopeChain(cx, &fp->scopeChain()))
|
||||
if (!envobj->setInternalScopeChain(cx, &fp->scopeChain()))
|
||||
return NULL;
|
||||
|
||||
return envobj;
|
||||
@ -861,7 +861,7 @@ js_PutCallObject(StackFrame *fp)
|
||||
|
||||
/* Clear private pointers to fp, which is about to go away. */
|
||||
if (js_IsNamedLambda(fun)) {
|
||||
JSObject *env = callobj.scopeChain();
|
||||
JSObject *env = callobj.internalScopeChain();
|
||||
|
||||
JS_ASSERT(env->isDeclEnv());
|
||||
JS_ASSERT(env->getPrivate() == fp);
|
||||
|
@ -328,8 +328,8 @@ SkipScopeParent(JSObject *parent)
|
||||
{
|
||||
if (!parent)
|
||||
return NULL;
|
||||
while (parent->isScope())
|
||||
parent = parent->getParentMaybeScope();
|
||||
while (parent->isInternalScope())
|
||||
parent = parent->scopeChain();
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
@ -694,7 +694,7 @@ ScanObject(GCMarker *gcmarker, JSObject *obj)
|
||||
types::TypeObject *type = obj->typeFromGC();
|
||||
PushMarkStack(gcmarker, type);
|
||||
|
||||
if (JSObject *parent = obj->getParentMaybeScope())
|
||||
if (JSObject *parent = obj->getParent())
|
||||
PushMarkStack(gcmarker, parent);
|
||||
|
||||
/*
|
||||
@ -763,7 +763,7 @@ MarkChildren(JSTracer *trc, JSObject *obj)
|
||||
MarkTypeObject(trc, obj->typeFromGC(), "type");
|
||||
|
||||
/* Trace universal (ops-independent) members. */
|
||||
if (JSObject *parent = obj->getParentMaybeScope())
|
||||
if (JSObject *parent = obj->getParent())
|
||||
MarkObject(trc, *parent, "parent");
|
||||
|
||||
Class *clasp = obj->getClass();
|
||||
|
@ -5162,7 +5162,7 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
|
||||
* the script is nested inside.
|
||||
*/
|
||||
while (!scope->isCall())
|
||||
scope = scope->scopeChain();
|
||||
scope = scope->internalScopeChain();
|
||||
|
||||
CallObject &call = scope->asCall();
|
||||
|
||||
@ -5195,7 +5195,7 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
|
||||
if (!parent->ensureHasTypes(cx))
|
||||
return false;
|
||||
if (!parent->types->hasScope()) {
|
||||
if (!SetScope(cx, parent, scope->scopeChain()))
|
||||
if (!SetScope(cx, parent, scope->internalScopeChain()))
|
||||
return false;
|
||||
parent->nesting()->activeCall = scope;
|
||||
parent->nesting()->argArray = call.argArray();
|
||||
@ -5290,7 +5290,7 @@ CheckNestingParent(JSContext *cx, JSObject *scope, JSScript *script)
|
||||
JS_ASSERT(parent);
|
||||
|
||||
while (!scope->isCall() || scope->asCall().getCalleeFunction()->script() != parent)
|
||||
scope = scope->scopeChain();
|
||||
scope = scope->internalScopeChain();
|
||||
|
||||
if (scope != parent->nesting()->activeCall) {
|
||||
parent->reentrantOuterFunction = true;
|
||||
@ -5305,7 +5305,7 @@ CheckNestingParent(JSContext *cx, JSObject *scope, JSScript *script)
|
||||
* parent.
|
||||
*/
|
||||
if (parent->nesting()->parent) {
|
||||
scope = scope->scopeChain();
|
||||
scope = scope->internalScopeChain();
|
||||
script = parent;
|
||||
goto restart;
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ GetScopeChainFull(JSContext *cx, StackFrame *fp, JSObject *blockChain)
|
||||
*/
|
||||
limitClone = &fp->scopeChain();
|
||||
while (limitClone->isWith())
|
||||
limitClone = limitClone->scopeChain();
|
||||
limitClone = limitClone->internalScopeChain();
|
||||
JS_ASSERT(limitClone);
|
||||
|
||||
/*
|
||||
@ -357,11 +357,11 @@ GetScopeChainFull(JSContext *cx, StackFrame *fp, JSObject *blockChain)
|
||||
if (!clone)
|
||||
return NULL;
|
||||
|
||||
if (!newChild->setScopeChain(cx, clone))
|
||||
if (!newChild->setInternalScopeChain(cx, clone))
|
||||
return NULL;
|
||||
newChild = clone;
|
||||
}
|
||||
if (!newChild->setScopeChain(cx, &fp->scopeChain()))
|
||||
if (!newChild->setInternalScopeChain(cx, &fp->scopeChain()))
|
||||
return NULL;
|
||||
|
||||
|
||||
@ -1215,7 +1215,7 @@ LeaveWith(JSContext *cx)
|
||||
JS_ASSERT(withobj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()));
|
||||
JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
|
||||
withobj->setPrivate(NULL);
|
||||
cx->fp()->setScopeChainNoCallObj(*withobj->scopeChain());
|
||||
cx->fp()->setScopeChainNoCallObj(*withobj->internalScopeChain());
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2139,7 +2139,7 @@ BEGIN_CASE(JSOP_POPN)
|
||||
JS_ASSERT_IF(obj,
|
||||
OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
|
||||
<= (size_t) (regs.sp - regs.fp()->base()));
|
||||
for (obj = ®s.fp()->scopeChain(); obj; obj = obj->getParentOrScopeChain()) {
|
||||
for (obj = ®s.fp()->scopeChain(); obj; obj = obj->scopeChain()) {
|
||||
if (!obj->isBlock() || !obj->isWith())
|
||||
continue;
|
||||
if (obj->getPrivate() != js_FloatingFrameIfGenerator(cx, regs.fp()))
|
||||
@ -5440,13 +5440,13 @@ BEGIN_CASE(JSOP_ENTERBLOCK)
|
||||
*/
|
||||
JSObject *obj2 = ®s.fp()->scopeChain();
|
||||
while (obj2->isWith())
|
||||
obj2 = obj2->scopeChain();
|
||||
obj2 = obj2->internalScopeChain();
|
||||
if (obj2->isBlock() &&
|
||||
obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, regs.fp())) {
|
||||
JSObject *youngestProto = obj2->getProto();
|
||||
JS_ASSERT(youngestProto->isStaticBlock());
|
||||
JSObject *parent = obj;
|
||||
while ((parent = parent->getParentOrScopeChain()) != youngestProto)
|
||||
while ((parent = parent->scopeChain()) != youngestProto)
|
||||
JS_ASSERT(parent);
|
||||
}
|
||||
#endif
|
||||
|
@ -962,7 +962,7 @@ static void
|
||||
AssertInnerizedScopeChain(JSContext *cx, JSObject &scopeobj)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (JSObject *o = &scopeobj; o; o = o->getParentOrScopeChain()) {
|
||||
for (JSObject *o = &scopeobj; o; o = o->scopeChain()) {
|
||||
if (JSObjectOp op = o->getClass()->ext.innerObject)
|
||||
JS_ASSERT(op(cx, o) == o);
|
||||
}
|
||||
@ -3604,7 +3604,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
|
||||
obj->initialize(emptyWithShape, type, NULL);
|
||||
OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
|
||||
|
||||
if (!obj->setScopeChain(cx, parent))
|
||||
if (!obj->setInternalScopeChain(cx, parent))
|
||||
return NULL;
|
||||
obj->setPrivate(priv);
|
||||
|
||||
@ -3664,8 +3664,8 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, StackFrame *fp)
|
||||
|
||||
/* Set the parent if necessary, as for call objects. */
|
||||
JSObject *global = priv->scopeChain().getGlobal();
|
||||
if (global != clone->getParentMaybeScope()) {
|
||||
JS_ASSERT(clone->getParentMaybeScope() == NULL);
|
||||
if (global != clone->getParent()) {
|
||||
JS_ASSERT(clone->getParent() == NULL);
|
||||
if (!clone->setParent(cx, global))
|
||||
return NULL;
|
||||
}
|
||||
@ -3711,7 +3711,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
|
||||
|
||||
/* We must clear the private slot even with errors. */
|
||||
obj->setPrivate(NULL);
|
||||
fp->setScopeChainNoCallObj(*obj->scopeChain());
|
||||
fp->setScopeChainNoCallObj(*obj->internalScopeChain());
|
||||
return normalUnwind;
|
||||
}
|
||||
|
||||
@ -5303,7 +5303,7 @@ js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id)
|
||||
* may gain such properties via eval introducing new vars; see bug 490364.
|
||||
*/
|
||||
if (obj->isCall()) {
|
||||
while ((obj = obj->getParentOrScopeChain()) != NULL) {
|
||||
while ((obj = obj->scopeChain()) != NULL) {
|
||||
if (!PurgeProtoChain(cx, obj, id))
|
||||
return false;
|
||||
}
|
||||
@ -5748,7 +5748,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
|
||||
/* Scan entries on the scope chain that we can cache across. */
|
||||
entry = JS_NO_PROP_CACHE_FILL;
|
||||
obj = scopeChain;
|
||||
parent = obj->getParentOrScopeChain();
|
||||
parent = obj->scopeChain();
|
||||
for (scopeIndex = 0;
|
||||
parent
|
||||
? IsCacheableNonGlobalScope(obj)
|
||||
@ -5794,7 +5794,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
|
||||
goto out;
|
||||
}
|
||||
obj = parent;
|
||||
parent = obj->getParentOrScopeChain();
|
||||
parent = obj->scopeChain();
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@ -5809,7 +5809,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
|
||||
* We conservatively assume that a resolve hook could mutate the scope
|
||||
* chain during JSObject::lookupGeneric. So we read parent here again.
|
||||
*/
|
||||
parent = obj->getParentOrScopeChain();
|
||||
parent = obj->scopeChain();
|
||||
if (!parent) {
|
||||
pobj = NULL;
|
||||
break;
|
||||
@ -5868,14 +5868,14 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
|
||||
JS_ASSERT(obj->isGlobal());
|
||||
return obj;
|
||||
}
|
||||
JS_ASSERT_IF(obj->isScope(), pobj->getClass() == obj->getClass());
|
||||
JS_ASSERT_IF(obj->isInternalScope(), pobj->getClass() == obj->getClass());
|
||||
DebugOnly<PropertyCacheEntry*> entry =
|
||||
JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, (Shape *) prop);
|
||||
JS_ASSERT(entry);
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSObject *parent = obj->getParentOrScopeChain();
|
||||
JSObject *parent = obj->scopeChain();
|
||||
if (!parent)
|
||||
return obj;
|
||||
obj = parent;
|
||||
@ -5895,7 +5895,7 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
|
||||
* chain during JSObject::lookupGeneric. So we must check if parent is
|
||||
* not null here even if it wasn't before the lookup.
|
||||
*/
|
||||
JSObject *parent = obj->getParentOrScopeChain();
|
||||
JSObject *parent = obj->scopeChain();
|
||||
if (!parent)
|
||||
break;
|
||||
obj = parent;
|
||||
@ -7471,7 +7471,7 @@ js_DumpObject(JSObject *obj)
|
||||
fputc('\n', stderr);
|
||||
|
||||
fprintf(stderr, "parent ");
|
||||
dumpValue(ObjectOrNullValue(obj->getParentMaybeScope()));
|
||||
dumpValue(ObjectOrNullValue(obj->getParent()));
|
||||
fputc('\n', stderr);
|
||||
|
||||
if (clasp->flags & JSCLASS_HAS_PRIVATE)
|
||||
|
@ -851,32 +851,63 @@ struct JSObject : js::gc::Cell
|
||||
return type_->proto;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parents and scope chains.
|
||||
*
|
||||
* All script-accessible objects with a NULL parent are global objects,
|
||||
* and all global objects have a NULL parent. Some builtin objects which
|
||||
* are not script-accessible also have a NULL parent, such as parser
|
||||
* created functions for non-compileAndGo scripts.
|
||||
*
|
||||
* Except for the non-script-accessible builtins, the global with which an
|
||||
* object is associated can be reached by following parent links to that
|
||||
* global (see getGlobal()).
|
||||
*
|
||||
* The scope chain of an object is the link in the search path when a
|
||||
* script does a name lookup on a scope object. For JS internal scope
|
||||
* objects --- Call, Block, DeclEnv and With --- the chain is stored in
|
||||
* the first fixed slot of the object, and the object's parent is the
|
||||
* associated global. For other scope objects, the chain is stored in the
|
||||
* object's parent.
|
||||
*
|
||||
* In compileAndGo code, scope chains can contain only internal scope
|
||||
* objects with a global object at the root as the scope of the outermost
|
||||
* non-function script. In non-compileAndGo code, the scope of the
|
||||
* outermost non-function script might not be a global object, and can have
|
||||
* a mix of other objects above it before the global object is reached.
|
||||
*/
|
||||
|
||||
/* Access the parent link of an object. */
|
||||
inline JSObject *getParent() const;
|
||||
bool setParent(JSContext *cx, JSObject *newParent);
|
||||
|
||||
/* Get the scope chain of an arbitrary scope object. */
|
||||
inline JSObject *scopeChain() const;
|
||||
|
||||
inline bool isGlobal() const;
|
||||
inline js::GlobalObject *asGlobal();
|
||||
|
||||
inline js::GlobalObject *getGlobal() const;
|
||||
|
||||
inline bool isInternalScope() const;
|
||||
|
||||
/* Access the scope chain of an internal scope object. */
|
||||
inline JSObject *internalScopeChain() const;
|
||||
inline bool setInternalScopeChain(JSContext *cx, JSObject *obj);
|
||||
static inline size_t offsetOfInternalScopeChain();
|
||||
|
||||
/*
|
||||
* Information for non-global scope chain objects (call/with/etc.). All
|
||||
* objects on a scope chain are either isScope() or isGlobal(). isScope()
|
||||
* objects do not escape to script and only appear on scope chains.
|
||||
* Access the scope chain of a static block object. These do not appear
|
||||
* on scope chains but mirror their structure, and can have a NULL
|
||||
* scope chain.
|
||||
*/
|
||||
inline bool isScope() const;
|
||||
inline JSObject *scopeChain() const;
|
||||
inline bool setScopeChain(JSContext *cx, JSObject *obj);
|
||||
|
||||
static inline size_t offsetOfScopeChain();
|
||||
|
||||
inline JSObject *getParentOrScopeChain() const;
|
||||
inline JSObject *getParentMaybeScope() const;
|
||||
inline JSObject *getStaticBlockScopeChain() const;
|
||||
inline void setStaticBlockScopeChain(JSObject *obj);
|
||||
|
||||
/* Common fixed slot for the scope chain of internal scope objects. */
|
||||
static const uint32 SCOPE_CHAIN_SLOT = 0;
|
||||
|
||||
/* Private data accessors. */
|
||||
|
||||
inline bool hasPrivate() const;
|
||||
inline void *getPrivate() const;
|
||||
inline void setPrivate(void *data);
|
||||
|
@ -274,74 +274,56 @@ JSObject::finalize(JSContext *cx, bool background)
|
||||
inline JSObject *
|
||||
JSObject::getParent() const
|
||||
{
|
||||
JS_ASSERT(!isScope());
|
||||
return lastProperty()->getObjectParent();
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::isScope() const
|
||||
JSObject::isInternalScope() const
|
||||
{
|
||||
return isCall() || isDeclEnv() || isBlock() || isWith();
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
JSObject::scopeChain() const
|
||||
JSObject::internalScopeChain() const
|
||||
{
|
||||
JS_ASSERT(isScope());
|
||||
return &getFixedSlot(0).toObject();
|
||||
JS_ASSERT(isInternalScope());
|
||||
return &getFixedSlot(SCOPE_CHAIN_SLOT).toObject();
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::setInternalScopeChain(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(isInternalScope());
|
||||
if (!obj->setDelegate(cx))
|
||||
return false;
|
||||
setFixedSlot(SCOPE_CHAIN_SLOT, JS::ObjectValue(*obj));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ inline size_t
|
||||
JSObject::offsetOfInternalScopeChain()
|
||||
{
|
||||
return getFixedSlotOffset(SCOPE_CHAIN_SLOT);
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
JSObject::getParentOrScopeChain() const
|
||||
JSObject::scopeChain() const
|
||||
{
|
||||
return isScope() ? scopeChain() : getParent();
|
||||
return isInternalScope() ? internalScopeChain() : getParent();
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
JSObject::getStaticBlockScopeChain() const
|
||||
{
|
||||
/*
|
||||
* Unlike other scope objects, static blocks not nested in one another
|
||||
* do not have a scope chain.
|
||||
*/
|
||||
JS_ASSERT(isStaticBlock());
|
||||
return getFixedSlot(0).isObject() ? &getFixedSlot(0).toObject() : NULL;
|
||||
return getFixedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setStaticBlockScopeChain(JSObject *obj)
|
||||
{
|
||||
/*
|
||||
* Static blocks may have a block chain set and then overwritten with NULL.
|
||||
* XXX bug 700799 this should not be able to happen.
|
||||
*/
|
||||
JS_ASSERT(isStaticBlock());
|
||||
if (obj)
|
||||
setFixedSlot(0, js::ObjectValue(*obj));
|
||||
else
|
||||
setFixedSlot(0, js::UndefinedValue());
|
||||
}
|
||||
|
||||
inline JSObject *
|
||||
JSObject::getParentMaybeScope() const
|
||||
{
|
||||
return lastProperty()->getObjectParent();
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::setScopeChain(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(isScope());
|
||||
if (!obj->setDelegate(cx))
|
||||
return false;
|
||||
setFixedSlot(0, JS::ObjectValue(*obj));
|
||||
return true;
|
||||
}
|
||||
|
||||
/*static*/ inline size_t
|
||||
JSObject::offsetOfScopeChain()
|
||||
{
|
||||
return getFixedSlotOffset(0);
|
||||
setFixedSlot(SCOPE_CHAIN_SLOT, JS::ObjectOrNullValue(obj));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -453,11 +435,11 @@ inline bool
|
||||
JSObject::canRemoveLastProperty()
|
||||
{
|
||||
/*
|
||||
* Some information stored in shapes describes the object itself, and can
|
||||
* be changed via replaceLastProperty without converting to a dictionary.
|
||||
* Parent shapes in the property tree may not have this information set,
|
||||
* and we need to ensure when unwinding properties that the per-object
|
||||
* information is not accidentally reset.
|
||||
* Check that the information about the object stored in the last
|
||||
* property's base shape is consistent with that stored in the previous
|
||||
* shape. If not consistent, then the last property cannot be removed as it
|
||||
* will induce a change in the object itself, and the object must be
|
||||
* converted to dictionary mode instead. See BaseShape comment in jsscope.h
|
||||
*/
|
||||
JS_ASSERT(!inDictionaryMode());
|
||||
const js::Shape *previous = lastProperty()->previous();
|
||||
@ -1281,7 +1263,7 @@ inline js::GlobalObject *
|
||||
JSObject::getGlobal() const
|
||||
{
|
||||
JSObject *obj = const_cast<JSObject *>(this);
|
||||
while (JSObject *parent = obj->getParentMaybeScope())
|
||||
while (JSObject *parent = obj->getParent())
|
||||
obj = parent;
|
||||
return obj->asGlobal();
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, JSObject *po
|
||||
|
||||
JSObject *tmp = obj;
|
||||
for (uintN i = 0; i != scopeIndex; i++)
|
||||
tmp = tmp->scopeChain();
|
||||
tmp = tmp->internalScopeChain();
|
||||
|
||||
uintN protoIndex = 0;
|
||||
while (tmp != pobj) {
|
||||
@ -224,7 +224,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
|
||||
|
||||
if (JOF_MODE(cs.format) == JOF_NAME) {
|
||||
while (vindex & (PCINDEX_SCOPEMASK << PCINDEX_PROTOBITS)) {
|
||||
tmp = pobj->scopeChain();
|
||||
tmp = pobj->internalScopeChain();
|
||||
if (!tmp || !tmp->isNative())
|
||||
break;
|
||||
pobj = tmp;
|
||||
|
@ -341,13 +341,18 @@ Shape::getChildBinding(JSContext *cx, const js::Shape &child, Shape **lastBindin
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Shape::replaceLastProperty(JSContext *cx, const js::Shape &child, Shape **lastp)
|
||||
Shape::replaceLastProperty(JSContext *cx, const BaseShape &base, Shape **lastp)
|
||||
{
|
||||
Shape *shape = *lastp;
|
||||
BaseShape *nbase = BaseShape::lookup(cx, base);
|
||||
if (!nbase)
|
||||
return false;
|
||||
|
||||
JS_ASSERT(!child.inDictionary());
|
||||
Shape *shape = *lastp;
|
||||
JS_ASSERT(!shape->inDictionary());
|
||||
|
||||
Shape child(shape);
|
||||
child.base_ = nbase;
|
||||
|
||||
Shape *newShape;
|
||||
if (shape->parent) {
|
||||
newShape = JS_PROPERTY_TREE(cx).getChild(cx, shape->parent, child);
|
||||
@ -645,7 +650,7 @@ JSObject::addPropertyInternal(JSContext *cx, jsid id,
|
||||
/* Find or create a property tree node labeled by our arguments. */
|
||||
Shape *shape;
|
||||
{
|
||||
BaseShape base(getClass(), getParentMaybeScope(), lastProperty()->getObjectFlags(),
|
||||
BaseShape base(getClass(), getParent(), lastProperty()->getObjectFlags(),
|
||||
attrs, getter, setter);
|
||||
BaseShape *nbase = BaseShape::lookup(cx, base);
|
||||
if (!nbase)
|
||||
@ -744,7 +749,7 @@ JSObject::putProperty(JSContext *cx, jsid id,
|
||||
|
||||
UnownedBaseShape *nbase;
|
||||
{
|
||||
BaseShape base(getClass(), getParentMaybeScope(), lastProperty()->getObjectFlags(),
|
||||
BaseShape base(getClass(), getParent(), lastProperty()->getObjectFlags(),
|
||||
attrs, getter, setter);
|
||||
nbase = BaseShape::lookup(cx, base);
|
||||
if (!nbase)
|
||||
@ -824,7 +829,7 @@ JSObject::putProperty(JSContext *cx, jsid id,
|
||||
* If any shape in the tree has a property hashtable, it is shared and
|
||||
* immutable too, therefore we must not update *spp.
|
||||
*/
|
||||
BaseShape base(getClass(), getParentMaybeScope(), lastProperty()->getObjectFlags(),
|
||||
BaseShape base(getClass(), getParent(), lastProperty()->getObjectFlags(),
|
||||
attrs, getter, setter);
|
||||
BaseShape *nbase = BaseShape::lookup(cx, base);
|
||||
if (!nbase)
|
||||
@ -1160,14 +1165,8 @@ Shape::setObjectParent(JSContext *cx, JSObject *parent, Shape **listp)
|
||||
|
||||
BaseShape base(*(*listp)->base()->unowned());
|
||||
base.setParent(parent);
|
||||
BaseShape *nbase = BaseShape::lookup(cx, base);
|
||||
if (!nbase)
|
||||
return false;
|
||||
|
||||
Shape child(*listp);
|
||||
child.base_ = nbase;
|
||||
|
||||
return replaceLastProperty(cx, child, listp);
|
||||
return replaceLastProperty(cx, base, listp);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1219,14 +1218,8 @@ Shape::setObjectFlag(JSContext *cx, BaseShape::Flag flag, Shape **listp)
|
||||
|
||||
BaseShape base(*(*listp)->base()->unowned());
|
||||
base.flags |= flag;
|
||||
BaseShape *nbase = BaseShape::lookup(cx, base);
|
||||
if (!nbase)
|
||||
return false;
|
||||
|
||||
Shape child(*listp);
|
||||
child.base_ = nbase;
|
||||
|
||||
return replaceLastProperty(cx, child, listp);
|
||||
return replaceLastProperty(cx, base, listp);
|
||||
}
|
||||
|
||||
/* static */ inline HashNumber
|
||||
@ -1368,14 +1361,8 @@ Shape::setExtensibleParents(JSContext *cx, Shape **listp)
|
||||
|
||||
BaseShape base(*shape->base()->unowned());
|
||||
base.flags |= BaseShape::EXTENSIBLE_PARENTS;
|
||||
BaseShape *nbase = BaseShape::lookup(cx, base);
|
||||
if (!nbase)
|
||||
return NULL;
|
||||
|
||||
Shape child(shape);
|
||||
child.base_ = nbase;
|
||||
|
||||
return replaceLastProperty(cx, child, listp);
|
||||
return replaceLastProperty(cx, base, listp);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -328,6 +328,16 @@ class PropertyTree;
|
||||
* Unowned Shape, Unowned BaseShape:
|
||||
*
|
||||
* Property in the property tree which does not have a property table.
|
||||
*
|
||||
* BaseShapes additionally encode some information about the referring object
|
||||
* itself. This includes the object's class, parent and various flags that may
|
||||
* be set for the object. Except for the class, this information is mutable and
|
||||
* may change when the object has an established property lineage. On such
|
||||
* changes the entire property lineage is not updated, but rather only the
|
||||
* last property (and its base shape). This works because only the object's
|
||||
* last property is used to query information about the object. Care must be
|
||||
* taken to call JSObject::canRemoveLastProperty when unwinding an object to
|
||||
* an earlier property, however.
|
||||
*/
|
||||
|
||||
class UnownedBaseShape;
|
||||
@ -565,8 +575,8 @@ struct Shape : public js::gc::Cell
|
||||
|
||||
js::Shape *getChildBinding(JSContext *cx, const js::Shape &child, js::Shape **lastBinding);
|
||||
|
||||
/* Replace the last shape in a non-dictionary lineage with child. */
|
||||
static bool replaceLastProperty(JSContext *cx, const js::Shape &child, Shape **lastp);
|
||||
/* Replace the base shape of the last shape in a non-dictionary lineage with base. */
|
||||
static bool replaceLastProperty(JSContext *cx, const BaseShape &base, Shape **lastp);
|
||||
|
||||
bool hashify(JSContext *cx);
|
||||
void handoffTableTo(Shape *newShape);
|
||||
|
@ -175,7 +175,7 @@ BaseShape::adoptUnowned(UnownedBaseShape *other)
|
||||
uint32 span = slotSpan();
|
||||
PropertyTable *table = &this->table();
|
||||
|
||||
*this = *static_cast<BaseShape *>(other);
|
||||
*this = *other;
|
||||
setOwned(other);
|
||||
this->parent = parent;
|
||||
this->flags |= flags;
|
||||
|
@ -7548,7 +7548,7 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
|
||||
return false;
|
||||
|
||||
obj = NULL;
|
||||
for (tmp = scopeChain; tmp; tmp = tmp->getParentOrScopeChain()) {
|
||||
for (tmp = scopeChain; tmp; tmp = tmp->scopeChain()) {
|
||||
Class *clasp = tmp->getClass();
|
||||
if (clasp == &BlockClass || clasp == &WithClass)
|
||||
continue;
|
||||
@ -7746,7 +7746,7 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *i
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
} while ((obj = obj->getParentOrScopeChain()) != NULL);
|
||||
} while ((obj = obj->scopeChain()) != NULL);
|
||||
|
||||
JSAutoByteString printable;
|
||||
JSString *str = ConvertQNameToString(cx, nameobj);
|
||||
|
@ -1377,10 +1377,10 @@ class ScopeNameCompiler : public PICStubCompiler
|
||||
return error();
|
||||
|
||||
/* Load the next link in the scope chain. */
|
||||
Address parent(pic.objReg, JSObject::offsetOfScopeChain());
|
||||
Address parent(pic.objReg, JSObject::offsetOfInternalScopeChain());
|
||||
masm.loadPayload(parent, pic.objReg);
|
||||
|
||||
tobj = tobj->scopeChain();
|
||||
tobj = tobj->internalScopeChain();
|
||||
}
|
||||
|
||||
if (tobj != getprop.holder)
|
||||
@ -1759,7 +1759,7 @@ class BindNameCompiler : public PICStubCompiler
|
||||
|
||||
/* Walk up the scope chain. */
|
||||
JSObject *tobj = scopeChain;
|
||||
Address parent(pic.objReg, JSObject::offsetOfScopeChain());
|
||||
Address parent(pic.objReg, JSObject::offsetOfInternalScopeChain());
|
||||
while (tobj && tobj != obj) {
|
||||
if (!IsCacheableNonGlobalScope(tobj))
|
||||
return disable("non-cacheable obj in scope chain");
|
||||
@ -1769,7 +1769,7 @@ class BindNameCompiler : public PICStubCompiler
|
||||
ImmPtr(tobj->lastProperty()));
|
||||
if (!fails.append(shapeTest))
|
||||
return error();
|
||||
tobj = tobj->scopeChain();
|
||||
tobj = tobj->internalScopeChain();
|
||||
}
|
||||
if (tobj != obj)
|
||||
return disable("indirect hit");
|
||||
|
@ -1859,13 +1859,13 @@ stubs::EnterBlock(VMFrame &f, JSObject *obj)
|
||||
*/
|
||||
JSObject *obj2 = &fp->scopeChain();
|
||||
while (obj2->isWith())
|
||||
obj2 = obj2->scopeChain();
|
||||
obj2 = obj2->internalScopeChain();
|
||||
if (obj2->isBlock() &&
|
||||
obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, fp)) {
|
||||
JSObject *youngestProto = obj2->getProto();
|
||||
JS_ASSERT(youngestProto->isStaticBlock());
|
||||
JSObject *parent = obj;
|
||||
while ((parent = parent->getParentOrScopeChain()) != youngestProto)
|
||||
while ((parent = parent->scopeChain()) != youngestProto)
|
||||
JS_ASSERT(parent);
|
||||
}
|
||||
#endif
|
||||
|
@ -77,8 +77,8 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObje
|
||||
* to be updated dynamically.
|
||||
*/
|
||||
JSObject *global = scopeChain.getGlobal();
|
||||
if (global != obj->getParentMaybeScope()) {
|
||||
JS_ASSERT(obj->getParentMaybeScope() == NULL);
|
||||
if (global != obj->getParent()) {
|
||||
JS_ASSERT(obj->getParent() == NULL);
|
||||
if (!obj->setParent(cx, global))
|
||||
return NULL;
|
||||
}
|
||||
@ -96,7 +96,7 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObje
|
||||
JS_ASSERT(obj->isCall());
|
||||
JS_ASSERT(!obj->inDictionaryMode());
|
||||
|
||||
if (!obj->setScopeChain(cx, &scopeChain))
|
||||
if (!obj->setInternalScopeChain(cx, &scopeChain))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
|
@ -84,7 +84,7 @@ StackFrame::varObj()
|
||||
{
|
||||
JSObject *obj = &scopeChain();
|
||||
while (!obj->isVarObj())
|
||||
obj = obj->getParentOrScopeChain();
|
||||
obj = obj->getParent();
|
||||
return *obj;
|
||||
}
|
||||
|
||||
@ -376,10 +376,10 @@ StackFrame::setScopeChainNoCallObj(JSObject &obj)
|
||||
if (hasCallObj()) {
|
||||
JSObject *pobj = &obj;
|
||||
while (pobj && pobj->getPrivate() != this)
|
||||
pobj = pobj->getParentOrScopeChain();
|
||||
pobj = pobj->scopeChain();
|
||||
JS_ASSERT(pobj);
|
||||
} else {
|
||||
for (JSObject *pobj = &obj; pobj->isScope(); pobj = pobj->getParentOrScopeChain())
|
||||
for (JSObject *pobj = &obj; pobj->isInternalScope(); pobj = pobj->scopeChain())
|
||||
JS_ASSERT_IF(pobj->isCall(), pobj->getPrivate() != this);
|
||||
}
|
||||
}
|
||||
@ -404,7 +404,7 @@ StackFrame::callObj() const
|
||||
|
||||
JSObject *pobj = &scopeChain();
|
||||
while (JS_UNLIKELY(!pobj->isCall()))
|
||||
pobj = pobj->getParentOrScopeChain();
|
||||
pobj = pobj->scopeChain();
|
||||
return pobj->asCall();
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ StackFrame::markFunctionEpilogueDone()
|
||||
*/
|
||||
scopeChain_ = isFunctionFrame()
|
||||
? callee().toFunction()->environment()
|
||||
: scopeChain_->scopeChain();
|
||||
: scopeChain_->internalScopeChain();
|
||||
flags_ &= ~HAS_CALL_OBJ;
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ StackFrame::stealFrameAndSlots(Value *vp, StackFrame *otherfp,
|
||||
obj.setPrivate(this);
|
||||
otherfp->flags_ &= ~HAS_CALL_OBJ;
|
||||
if (js_IsNamedLambda(fun())) {
|
||||
JSObject *env = obj.scopeChain();
|
||||
JSObject *env = obj.internalScopeChain();
|
||||
JS_ASSERT(env->isDeclEnv());
|
||||
env->setPrivate(this);
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ bool
|
||||
ListBase<LC>::instanceIsListObject(JSContext *cx, JSObject *obj, JSObject *callee)
|
||||
{
|
||||
if (XPCWrapper::IsSecurityWrapper(obj)) {
|
||||
if (callee && js::GetObjectGlobal(obj) == js::GetObjectGlobal(callee)) {
|
||||
if (callee && JS_GetGlobalForObject(cx, obj) == JS_GetGlobalForObject(cx, callee)) {
|
||||
obj = js::UnwrapObject(obj);
|
||||
} else {
|
||||
obj = XPCWrapper::Unwrap(cx, obj);
|
||||
|
@ -808,7 +808,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
||||
}
|
||||
|
||||
if(traceKind == JSTRACE_OBJECT) {
|
||||
JSObject *global = js::GetObjectGlobal(static_cast<JSObject*>(p));
|
||||
JSObject *global = JS_GetGlobalForObject(NULL, static_cast<JSObject*>(p));
|
||||
char fullname[100];
|
||||
JS_snprintf(fullname, sizeof(fullname),
|
||||
"%s (global=%p)", name, global);
|
||||
|
Loading…
Reference in New Issue
Block a user