Bug 887558 (part 2) - Move various functions into ProxyObject and FunctionProxyObject. r=jorendorff.

--HG--
extra : rebase_source : 14402b9ab7eda3389eb1b812ee961e46067b5b1d
This commit is contained in:
Nicholas Nethercote 2013-06-20 22:39:22 -07:00
parent 40833186f3
commit 8575db2cf1
19 changed files with 382 additions and 257 deletions

View File

@ -128,8 +128,8 @@ IsDOMIfaceAndProtoClass(const js::Class* clasp)
return IsDOMIfaceAndProtoClass(Jsvalify(clasp));
}
MOZ_STATIC_ASSERT(DOM_OBJECT_SLOT == js::JSSLOT_PROXY_PRIVATE,
"JSSLOT_PROXY_PRIVATE doesn't match DOM_OBJECT_SLOT. "
MOZ_STATIC_ASSERT(DOM_OBJECT_SLOT == js::PROXY_PRIVATE_SLOT,
"js::PROXY_PRIVATE_SLOT doesn't match DOM_OBJECT_SLOT. "
"Expect bad things");
template <class T>
inline T*

View File

@ -63,7 +63,7 @@ struct SetDOMProxyInformation
{
SetDOMProxyInformation() {
js::SetDOMProxyInformation((void*) &HandlerFamily,
js::JSSLOT_PROXY_EXTRA + JSPROXYSLOT_EXPANDO, DOMProxyShadows);
js::PROXY_EXTRA_SLOT + JSPROXYSLOT_EXPANDO, DOMProxyShadows);
}
};

View File

@ -15,7 +15,7 @@
#include "xpcpublic.h"
#include "nsStringGlue.h"
#define DOM_PROXY_OBJECT_SLOT js::JSSLOT_PROXY_PRIVATE
#define DOM_PROXY_OBJECT_SLOT js::PROXY_PRIVATE_SLOT
namespace mozilla {
namespace dom {

View File

@ -3069,7 +3069,7 @@ IsCacheableDOMProxy(JSObject *obj)
if (!obj->is<ProxyObject>())
return false;
BaseProxyHandler *handler = GetProxyHandler(obj);
BaseProxyHandler *handler = obj->as<ProxyObject>().handler();
if (handler->family() != GetDOMProxyHandlerFamily())
return false;
@ -3101,7 +3101,7 @@ GenerateDOMProxyChecks(JSContext *cx, MacroAssembler &masm, Register object,
// 1. The object is a DOMProxy.
// 2. The object does not have expando properties, or has an expando
// which is known to not have the desired property.
Address handlerAddr(object, JSObject::getFixedSlotOffset(JSSLOT_PROXY_HANDLER));
Address handlerAddr(object, ProxyObject::offsetOfHandler());
Address expandoAddr(object, JSObject::getFixedSlotOffset(GetDOMProxyExpandoSlot()));
// Check that object is a DOMProxy.
@ -5330,8 +5330,9 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
} else {
kind = ICStub::GetProp_CallDOMProxyNative;
}
ICGetPropCallDOMProxyNativeCompiler compiler(cx, kind, monitorStub, obj, holder, callee,
pc - script->code);
Rooted<ProxyObject*> proxy(cx, &obj->as<ProxyObject>());
ICGetPropCallDOMProxyNativeCompiler
compiler(cx, kind, monitorStub, proxy, holder, callee, pc - script->code);
newStub = compiler.getStub(compiler.getStubSpace(script));
} else {
ICGetProp_CallNative::Compiler compiler(cx, monitorStub, obj, holder, callee,
@ -5350,7 +5351,8 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
JS_ASSERT(obj == holder);
IonSpew(IonSpew_BaselineIC, " Generating GetProp(DOMProxyProxy) stub");
ICGetProp_DOMProxyShadowed::Compiler compiler(cx, monitorStub, obj, name,
Rooted<ProxyObject*> proxy(cx, &obj->as<ProxyObject>());
ICGetProp_DOMProxyShadowed::Compiler compiler(cx, monitorStub, proxy, name,
pc - script->code);
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
@ -5956,10 +5958,10 @@ ICGetPropCallDOMProxyNativeCompiler::generateStubCode(MacroAssembler &masm)
ICStub *
ICGetPropCallDOMProxyNativeCompiler::getStub(ICStubSpace *space)
{
RootedShape shape(cx, obj_->lastProperty());
RootedShape shape(cx, proxy_->lastProperty());
RootedShape holderShape(cx, holder_->lastProperty());
Value expandoSlot = obj_->getFixedSlot(GetDOMProxyExpandoSlot());
Value expandoSlot = proxy_->getFixedSlot(GetDOMProxyExpandoSlot());
RootedShape expandoShape(cx, NULL);
ExpandoAndGeneration *expandoAndGeneration;
int32_t generation;
@ -5979,12 +5981,12 @@ ICGetPropCallDOMProxyNativeCompiler::getStub(ICStubSpace *space)
if (kind == ICStub::GetProp_CallDOMProxyNative) {
return ICGetProp_CallDOMProxyNative::New(
space, getStubCode(), firstMonitorStub_, shape, GetProxyHandler(obj_),
space, getStubCode(), firstMonitorStub_, shape, proxy_->handler(),
expandoShape, holder_, holderShape, getter_, pcOffset_);
}
return ICGetProp_CallDOMProxyWithGenerationNative::New(
space, getStubCode(), firstMonitorStub_, shape, GetProxyHandler(obj_),
space, getStubCode(), firstMonitorStub_, shape, proxy_->handler(),
expandoAndGeneration, generation, expandoShape, holder_, holderShape, getter_,
pcOffset_);
}
@ -5992,9 +5994,9 @@ ICGetPropCallDOMProxyNativeCompiler::getStub(ICStubSpace *space)
ICStub *
ICGetProp_DOMProxyShadowed::Compiler::getStub(ICStubSpace *space)
{
RootedShape shape(cx, obj_->lastProperty());
return ICGetProp_DOMProxyShadowed::New(space, getStubCode(), firstMonitorStub_,
shape, GetProxyHandler(obj_), name_, pcOffset_);
RootedShape shape(cx, proxy_->lastProperty());
return ICGetProp_DOMProxyShadowed::New(space, getStubCode(), firstMonitorStub_, shape,
proxy_->handler(), name_, pcOffset_);
}
static bool
@ -8557,21 +8559,20 @@ ICGetPropCallDOMProxyNativeStub::ICGetPropCallDOMProxyNativeStub(Kind kind, IonC
ICGetPropCallDOMProxyNativeCompiler::ICGetPropCallDOMProxyNativeCompiler(JSContext *cx,
ICStub::Kind kind,
ICStub *firstMonitorStub,
HandleObject obj,
Handle<ProxyObject*> proxy,
HandleObject holder,
HandleFunction getter,
uint32_t pcOffset)
: ICStubCompiler(cx, kind),
firstMonitorStub_(firstMonitorStub),
obj_(cx, obj),
proxy_(cx, proxy),
holder_(cx, holder),
getter_(cx, getter),
pcOffset_(pcOffset)
{
JS_ASSERT(kind == ICStub::GetProp_CallDOMProxyNative ||
kind == ICStub::GetProp_CallDOMProxyWithGenerationNative);
JS_ASSERT(obj_->is<ProxyObject>());
JS_ASSERT(GetProxyHandler(obj_)->family() == GetDOMProxyHandlerFamily());
JS_ASSERT(proxy_->handler()->family() == GetDOMProxyHandlerFamily());
}
ICGetProp_DOMProxyShadowed::ICGetProp_DOMProxyShadowed(IonCode *stubCode,

View File

@ -4379,7 +4379,7 @@ class ICGetProp_CallDOMProxyWithGenerationNative : public ICGetPropCallDOMProxyN
class ICGetPropCallDOMProxyNativeCompiler : public ICStubCompiler {
ICStub *firstMonitorStub_;
RootedObject obj_;
Rooted<ProxyObject*> proxy_;
RootedObject holder_;
RootedFunction getter_;
uint32_t pcOffset_;
@ -4390,7 +4390,7 @@ class ICGetPropCallDOMProxyNativeCompiler : public ICStubCompiler {
public:
ICGetPropCallDOMProxyNativeCompiler(JSContext *cx, ICStub::Kind kind,
ICStub *firstMonitorStub, HandleObject obj,
ICStub *firstMonitorStub, Handle<ProxyObject*> proxy,
HandleObject holder, HandleFunction getter,
uint32_t pcOffset);
@ -4444,18 +4444,18 @@ class ICGetProp_DOMProxyShadowed : public ICMonitoredStub
class Compiler : public ICStubCompiler {
ICStub *firstMonitorStub_;
RootedObject obj_;
Rooted<ProxyObject*> proxy_;
RootedPropertyName name_;
uint32_t pcOffset_;
bool generateStubCode(MacroAssembler &masm);
public:
Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj, HandlePropertyName name,
uint32_t pcOffset)
Compiler(JSContext *cx, ICStub *firstMonitorStub, Handle<ProxyObject*> proxy,
HandlePropertyName name, uint32_t pcOffset)
: ICStubCompiler(cx, ICStub::GetProp_CallNative),
firstMonitorStub_(firstMonitorStub),
obj_(cx, obj),
proxy_(cx, proxy),
name_(cx, name),
pcOffset_(pcOffset)
{}

View File

@ -427,7 +427,7 @@ IsCacheableDOMProxy(JSObject *obj)
if (!obj->is<ProxyObject>())
return false;
BaseProxyHandler *handler = GetProxyHandler(obj);
BaseProxyHandler *handler = obj->as<ProxyObject>().handler();
if (handler->family() != GetDOMProxyHandlerFamily())
return false;
@ -637,11 +637,12 @@ GenerateDOMProxyChecks(JSContext *cx, MacroAssembler &masm, JSObject *obj,
// 1. The object is a DOMProxy.
// 2. The object does not have expando properties, or has an expando
// which is known to not have the desired property.
Address handlerAddr(object, JSObject::getFixedSlotOffset(JSSLOT_PROXY_HANDLER));
Address handlerAddr(object, ProxyObject::offsetOfHandler());
Address expandoSlotAddr(object, JSObject::getFixedSlotOffset(GetDOMProxyExpandoSlot()));
// Check that object is a DOMProxy.
masm.branchPrivatePtr(Assembler::NotEqual, handlerAddr, ImmWord(GetProxyHandler(obj)), stubFailure);
masm.branchPrivatePtr(Assembler::NotEqual, handlerAddr,
ImmWord(obj->as<ProxyObject>().handler()), stubFailure);
if (skipExpandoCheck)
return;

View File

@ -72,15 +72,15 @@ BEGIN_TEST(testBug604087)
JS::RootedObject c2wrapper(cx, wrap(cx, outerObj, compartment2));
CHECK(c2wrapper);
js::SetProxyExtra(c2wrapper, 0, js::Int32Value(2));
c2wrapper->as<js::ProxyObject>().setExtra(0, js::Int32Value(2));
JS::RootedObject c3wrapper(cx, wrap(cx, outerObj, compartment3));
CHECK(c3wrapper);
js::SetProxyExtra(c3wrapper, 0, js::Int32Value(3));
c3wrapper->as<js::ProxyObject>().setExtra(0, js::Int32Value(3));
JS::RootedObject c4wrapper(cx, wrap(cx, outerObj, compartment4));
CHECK(c4wrapper);
js::SetProxyExtra(c4wrapper, 0, js::Int32Value(4));
c4wrapper->as<js::ProxyObject>().setExtra(0, js::Int32Value(4));
compartment4 = c4wrapper = NULL;
JS::RootedObject next(cx);

View File

@ -456,15 +456,15 @@ JSCompartment::markCrossCompartmentWrappers(JSTracer *trc)
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
Value v = e.front().value;
if (e.front().key.kind == CrossCompartmentKey::ObjectWrapper) {
JSObject *wrapper = &v.toObject();
ProxyObject *wrapper = &v.toObject().as<ProxyObject>();
/*
* We have a cross-compartment wrapper. Its private pointer may
* point into the compartment being collected, so we should mark it.
*/
Value referent = GetProxyPrivate(wrapper);
Value referent = wrapper->private_();
MarkValueRoot(trc, &referent, "cross-compartment wrapper");
JS_ASSERT(referent == GetProxyPrivate(wrapper));
JS_ASSERT(referent == wrapper->private_());
}
}
}

View File

@ -578,8 +578,7 @@ JS_IsDeadWrapper(JSObject *obj)
return false;
}
BaseProxyHandler *handler = GetProxyHandler(obj);
return handler->family() == &DeadObjectProxy::sDeadObjectFamily;
return obj->as<ProxyObject>().handler()->family() == &DeadObjectProxy::sDeadObjectFamily;
}
void

View File

@ -65,6 +65,7 @@ using mozilla::Swap;
#include "gc/Marking.h"
#include "gc/Memory.h"
#include "vm/Debugger.h"
#include "vm/ProxyObject.h"
#include "vm/Shape.h"
#include "vm/String.h"
#include "vm/ForkJoin.h"
@ -3365,20 +3366,19 @@ IsGrayListObject(JSObject *obj)
return IsCrossCompartmentWrapper(obj) && !IsDeadProxyObject(obj);
}
const unsigned JSSLOT_GC_GRAY_LINK = JSSLOT_PROXY_EXTRA + 1;
static unsigned
GrayLinkSlot(JSObject *obj)
/* static */ unsigned
ProxyObject::grayLinkSlot(JSObject *obj)
{
JS_ASSERT(IsGrayListObject(obj));
return JSSLOT_GC_GRAY_LINK;
return ProxyObject::EXTRA_SLOT + 1;
}
#ifdef DEBUG
static void
AssertNotOnGrayList(JSObject *obj)
{
JS_ASSERT_IF(IsGrayListObject(obj), obj->getReservedSlot(GrayLinkSlot(obj)).isUndefined());
JS_ASSERT_IF(IsGrayListObject(obj),
obj->getReservedSlot(ProxyObject::grayLinkSlot(obj)).isUndefined());
}
#endif
@ -3386,13 +3386,13 @@ static JSObject *
CrossCompartmentPointerReferent(JSObject *obj)
{
JS_ASSERT(IsGrayListObject(obj));
return &GetProxyPrivate(obj).toObject();
return &obj->as<ProxyObject>().private_().toObject();
}
static JSObject *
NextIncomingCrossCompartmentPointer(JSObject *prev, bool unlink)
{
unsigned slot = GrayLinkSlot(prev);
unsigned slot = ProxyObject::grayLinkSlot(prev);
JSObject *next = prev->getReservedSlot(slot).toObjectOrNull();
JS_ASSERT_IF(next, IsGrayListObject(next));
@ -3408,7 +3408,7 @@ js::DelayCrossCompartmentGrayMarking(JSObject *src)
JS_ASSERT(IsGrayListObject(src));
/* Called from MarkCrossCompartmentXXX functions. */
unsigned slot = GrayLinkSlot(src);
unsigned slot = ProxyObject::grayLinkSlot(src);
JSObject *dest = CrossCompartmentPointerReferent(src);
JSCompartment *comp = dest->compartment();
@ -3486,7 +3486,7 @@ RemoveFromGrayList(JSObject *wrapper)
if (!IsGrayListObject(wrapper))
return false;
unsigned slot = GrayLinkSlot(wrapper);
unsigned slot = ProxyObject::grayLinkSlot(wrapper);
if (wrapper->getReservedSlot(slot).isUndefined())
return false; /* Not on our list. */
@ -3501,7 +3501,7 @@ RemoveFromGrayList(JSObject *wrapper)
}
while (obj) {
unsigned slot = GrayLinkSlot(obj);
unsigned slot = ProxyObject::grayLinkSlot(obj);
JSObject *next = obj->getReservedSlot(slot).toObjectOrNull();
if (next == wrapper) {
obj->setCrossCompartmentSlot(slot, ObjectOrNullValue(tail));

View File

@ -26,29 +26,6 @@ using namespace js;
using namespace js::gc;
using mozilla::ArrayLength;
static inline HeapSlot &
GetCall(JSObject *proxy)
{
JS_ASSERT(proxy->is<FunctionProxyObject>());
return proxy->getSlotRef(JSSLOT_PROXY_CALL);
}
static inline Value
GetConstruct(JSObject *proxy)
{
if (proxy->slotSpan() <= JSSLOT_PROXY_CONSTRUCT)
return UndefinedValue();
return proxy->getSlot(JSSLOT_PROXY_CONSTRUCT);
}
static inline HeapSlot &
GetFunctionProxyConstruct(JSObject *proxy)
{
JS_ASSERT(proxy->is<FunctionProxyObject>());
JS_ASSERT(proxy->slotSpan() > JSSLOT_PROXY_CONSTRUCT);
return proxy->getSlotRef(JSSLOT_PROXY_CONSTRUCT);
}
void
js::AutoEnterPolicy::reportError(JSContext *cx, jsid id)
{
@ -211,7 +188,7 @@ BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
} else if ((desc.attrs & JSPROP_SETTER) || desc.setter != JS_StrictPropertyStub) {
if (!CallSetter(cx, receiver, id, desc.setter, desc.attrs, desc.shortid, strict, vp))
return false;
if (!proxy->is<ProxyObject>() || GetProxyHandler(proxy) != this)
if (!proxy->is<ProxyObject>() || proxy->as<ProxyObject>().handler() != this)
return true;
if (desc.attrs & JSPROP_SHARED)
return true;
@ -238,7 +215,7 @@ BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
} else if ((desc.attrs & JSPROP_SETTER) || desc.setter != JS_StrictPropertyStub) {
if (!CallSetter(cx, receiver, id, desc.setter, desc.attrs, desc.shortid, strict, vp))
return false;
if (!proxy->is<ProxyObject>() || GetProxyHandler(proxy) != this)
if (!proxy->is<ProxyObject>() || proxy->as<ProxyObject>().handler() != this)
return true;
if (desc.attrs & JSPROP_SHARED)
return true;
@ -392,7 +369,7 @@ DirectProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, Han
{
assertEnteredPolicy(cx, proxy, id);
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return JS_GetPropertyDescriptorById(cx, target, id, 0, desc);
}
@ -417,7 +394,7 @@ DirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
HandleId id, PropertyDescriptor *desc, unsigned flags)
{
assertEnteredPolicy(cx, proxy, id);
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return GetOwnPropertyDescriptor(cx, target, id, 0, desc);
}
@ -426,7 +403,7 @@ DirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId i
PropertyDescriptor *desc)
{
assertEnteredPolicy(cx, proxy, id);
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
RootedValue v(cx, desc->value);
return CheckDefineProperty(cx, target, id, v, desc->getter, desc->setter, desc->attrs) &&
JS_DefinePropertyById(cx, target, id, v, desc->getter, desc->setter, desc->attrs);
@ -437,7 +414,7 @@ DirectProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject proxy,
AutoIdVector &props)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return GetPropertyNames(cx, target, JSITER_OWNONLY | JSITER_HIDDEN, &props);
}
@ -445,7 +422,7 @@ bool
DirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
{
assertEnteredPolicy(cx, proxy, id);
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
RootedValue v(cx);
if (!JS_DeletePropertyById2(cx, target, id, v.address()))
return false;
@ -462,7 +439,7 @@ DirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy,
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return GetPropertyNames(cx, target, 0, &props);
}
@ -470,7 +447,7 @@ bool
DirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedValue target(cx, GetProxyPrivate(proxy));
RootedValue target(cx, proxy->as<ProxyObject>().private_());
return Invoke(cx, args.thisv(), target, args.length(), args.array(), args.rval());
}
@ -478,7 +455,7 @@ bool
DirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const CallArgs &args)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedValue target(cx, GetProxyPrivate(proxy));
RootedValue target(cx, proxy->as<ProxyObject>().private_());
return InvokeConstructor(cx, target, args.length(), args.array(), args.rval().address());
}
@ -486,7 +463,7 @@ bool
DirectProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl,
CallArgs args)
{
args.setThis(ObjectValue(*GetProxyTargetObject(&args.thisv().toObject())));
args.setThis(ObjectValue(*args.thisv().toObject().as<ProxyObject>().target()));
if (!test(args.thisv())) {
ReportIncompatible(cx, args);
return false;
@ -501,7 +478,7 @@ DirectProxyHandler::hasInstance(JSContext *cx, HandleObject proxy, MutableHandle
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
JSBool b;
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
if (!JS_HasInstance(cx, target, v, &b))
return false;
*bp = !!b;
@ -513,15 +490,15 @@ bool
DirectProxyHandler::objectClassIs(HandleObject proxy, ESClassValue classValue,
JSContext *cx)
{
RootedObject obj(cx, GetProxyTargetObject(proxy));
return ObjectClassIs(obj, classValue, cx);
RootedObject target(cx, proxy->as<ProxyObject>().target());
return ObjectClassIs(target, classValue, cx);
}
const char *
DirectProxyHandler::className(JSContext *cx, HandleObject proxy)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return JSObject::className(cx, target);
}
@ -530,7 +507,7 @@ DirectProxyHandler::fun_toString(JSContext *cx, HandleObject proxy,
unsigned indent)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return fun_toStringHelper(cx, target, indent);
}
@ -538,7 +515,7 @@ bool
DirectProxyHandler::regexp_toShared(JSContext *cx, HandleObject proxy,
RegExpGuard *g)
{
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return RegExpToShared(cx, target, g);
}
@ -546,7 +523,7 @@ bool
DirectProxyHandler::defaultValue(JSContext *cx, HandleObject proxy, JSType hint,
MutableHandleValue vp)
{
vp.set(ObjectValue(*GetProxyTargetObject(proxy)));
vp.set(ObjectValue(*proxy->as<ProxyObject>().target()));
if (hint == JSTYPE_VOID)
return ToPrimitive(cx, vp);
return ToPrimitive(cx, hint, vp);
@ -569,7 +546,7 @@ DirectProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp
assertEnteredPolicy(cx, proxy, id);
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
JSBool found;
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
if (!JS_HasPropertyById(cx, target, id, &found))
return false;
*bp = !!found;
@ -580,7 +557,7 @@ bool
DirectProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
{
assertEnteredPolicy(cx, proxy, id);
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
AutoPropertyDescriptorRooter desc(cx);
if (!JS_GetPropertyDescriptorById(cx, target, id, 0, &desc))
return false;
@ -593,7 +570,7 @@ DirectProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver
HandleId id, MutableHandleValue vp)
{
assertEnteredPolicy(cx, proxy, id);
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return JSObject::getGeneric(cx, target, receiver, id, vp);
}
@ -602,7 +579,7 @@ DirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver
HandleId id, bool strict, MutableHandleValue vp)
{
assertEnteredPolicy(cx, proxy, id);
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return JSObject::setGeneric(cx, target, receiver, id, vp, strict);
}
@ -610,7 +587,7 @@ bool
DirectProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return GetPropertyNames(cx, target, JSITER_OWNONLY, &props);
}
@ -620,21 +597,21 @@ DirectProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags,
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return GetIterator(cx, target, flags, vp);
}
bool
DirectProxyHandler::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
{
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return JSObject::isExtensible(cx, target, extensible);
}
bool
DirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
{
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
return JSObject::preventExtensions(cx, target);
}
@ -757,6 +734,21 @@ ArrayToIdVector(JSContext *cx, const Value &array, AutoIdVector &props)
return true;
}
inline HeapSlot &
FunctionProxyObject::construct()
{
JS_ASSERT(slotSpan() > CONSTRUCT_SLOT);
return getSlotRef(CONSTRUCT_SLOT);
}
inline Value
FunctionProxyObject::constructOrUndefined() const
{
if (slotSpan() <= CONSTRUCT_SLOT)
return UndefinedValue();
return getSlot(CONSTRUCT_SLOT);
}
/* Derived class for all scripted indirect proxy handlers. */
class ScriptedIndirectProxyHandler : public BaseProxyHandler
{
@ -845,7 +837,7 @@ ReturnedValueMustNotBePrimitive(JSContext *cx, HandleObject proxy, JSAtom *atom,
static JSObject *
GetIndirectProxyHandlerObject(JSObject *proxy)
{
return GetProxyPrivate(proxy).toObjectOrNull();
return proxy->as<ProxyObject>().private_().toObjectOrNull();
}
bool
@ -1013,7 +1005,7 @@ bool
ScriptedIndirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedValue call(cx, GetCall(proxy));
RootedValue call(cx, proxy->as<FunctionProxyObject>().call());
return Invoke(cx, args.thisv(), call, args.length(), args.array(), args.rval());
}
@ -1021,9 +1013,9 @@ bool
ScriptedIndirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const CallArgs &args)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
RootedValue fval(cx, GetConstruct(proxy));
RootedValue fval(cx, proxy->as<FunctionProxyObject>().constructOrUndefined());
if (fval.isUndefined())
fval = GetCall(proxy);
fval = proxy->as<FunctionProxyObject>().call();
return InvokeConstructor(cx, fval, args.length(), args.array(), args.rval().address());
}
@ -1038,9 +1030,8 @@ JSString *
ScriptedIndirectProxyHandler::fun_toString(JSContext *cx, HandleObject proxy, unsigned indent)
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
Value fval = GetCall(proxy);
if (proxy->is<FunctionProxyObject>() &&
(fval.isPrimitive() || !fval.toObject().is<JSFunction>())) {
Value fval = proxy->as<FunctionProxyObject>().call();
if (fval.isPrimitive() || !fval.toObject().is<JSFunction>()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_INCOMPATIBLE_PROTO,
js_Function_str, js_toString_str,
@ -1067,7 +1058,7 @@ ScriptedIndirectProxyHandler ScriptedIndirectProxyHandler::singleton;
static JSObject *
GetDirectProxyHandlerObject(JSObject *proxy)
{
return GetProxyExtra(proxy, 0).toObjectOrNull();
return proxy->as<ProxyObject>().extra(0).toObjectOrNull();
}
/* Derived class for all scripted direct proxy handlers. */
@ -1355,7 +1346,7 @@ TrapGetOwnProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHandle
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step 3
RootedValue trap(cx);
@ -1463,7 +1454,7 @@ TrapDefineOwnProperty(JSContext *cx, HandleObject proxy, HandleId id, MutableHan
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step 3
RootedValue trap(cx);
@ -1668,7 +1659,7 @@ ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, HandleObject proxy)
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step b
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step c
RootedValue trap(cx);
@ -1770,7 +1761,7 @@ ScriptedDirectProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject prox
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step b
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step c
RootedValue trap(cx);
@ -1808,7 +1799,7 @@ ScriptedDirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step 3
RootedValue trap(cx);
@ -1860,7 +1851,7 @@ ScriptedDirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy, AutoIdV
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step b
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step c
RootedValue trap(cx);
@ -1903,7 +1894,7 @@ ScriptedDirectProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id,
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step 3
RootedValue trap(cx);
@ -1966,7 +1957,7 @@ ScriptedDirectProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId i
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step 3
RootedValue trap(cx);
@ -2043,7 +2034,7 @@ ScriptedDirectProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step 3
RootedValue trap(cx);
@ -2112,7 +2103,7 @@ ScriptedDirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step 3
RootedValue trap(cx);
@ -2180,7 +2171,7 @@ ScriptedDirectProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step b
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step c
RootedValue trap(cx);
@ -2229,7 +2220,7 @@ ScriptedDirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallAr
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
/*
* NB: Remember to throw a TypeError here if we change NewProxyObject so that this trap can get
@ -2267,7 +2258,7 @@ ScriptedDirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const C
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 2
RootedObject target(cx, GetProxyTargetObject(proxy));
RootedObject target(cx, proxy->as<ProxyObject>().target());
/*
* NB: Remember to throw a TypeError here if we change NewProxyObject so that this trap can get
@ -2315,7 +2306,7 @@ Proxy::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
PropertyDescriptor *desc, unsigned flags)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
desc->obj = NULL; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
@ -2348,7 +2339,7 @@ Proxy::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
desc->obj = NULL; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
@ -2372,11 +2363,11 @@ bool
Proxy::defineProperty(JSContext *cx, HandleObject proxy, HandleId id, PropertyDescriptor *desc)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true);
if (!policy.allowed())
return policy.returnValue();
return GetProxyHandler(proxy)->defineProperty(cx, proxy, id, desc);
return proxy->as<ProxyObject>().handler()->defineProperty(cx, proxy, id, desc);
}
bool
@ -2392,23 +2383,23 @@ bool
Proxy::getOwnPropertyNames(JSContext *cx, HandleObject proxy, AutoIdVector &props)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
return GetProxyHandler(proxy)->getOwnPropertyNames(cx, proxy, props);
return proxy->as<ProxyObject>().handler()->getOwnPropertyNames(cx, proxy, props);
}
bool
Proxy::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
*bp = true; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true);
if (!policy.allowed())
return policy.returnValue();
return GetProxyHandler(proxy)->delete_(cx, proxy, id, bp);
return proxy->as<ProxyObject>().handler()->delete_(cx, proxy, id, bp);
}
JS_FRIEND_API(bool)
@ -2435,12 +2426,12 @@ bool
Proxy::enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
if (!handler->hasPrototype())
return GetProxyHandler(proxy)->enumerate(cx, proxy, props);
return proxy->as<ProxyObject>().handler()->enumerate(cx, proxy, props);
if (!handler->keys(cx, proxy, props))
return false;
AutoIdVector protoProps(cx);
@ -2453,7 +2444,7 @@ bool
Proxy::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
*bp = false; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
@ -2474,7 +2465,7 @@ bool
Proxy::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
*bp = false; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
@ -2487,7 +2478,7 @@ Proxy::get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id
MutableHandleValue vp)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
vp.setUndefined(); // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
@ -2514,7 +2505,7 @@ Proxy::getElementIfPresent(JSContext *cx, HandleObject proxy, HandleObject recei
if (!IndexToId(cx, index, &id))
return false;
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
@ -2530,7 +2521,7 @@ Proxy::getElementIfPresent(JSContext *cx, HandleObject proxy, HandleObject recei
if (hasOwn) {
*present = true;
return GetProxyHandler(proxy)->get(cx, proxy, receiver, id, vp);
return proxy->as<ProxyObject>().handler()->get(cx, proxy, receiver, id, vp);
}
*present = false;
@ -2543,7 +2534,7 @@ Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id
MutableHandleValue vp)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true);
if (!policy.allowed())
return policy.returnValue();
@ -2573,7 +2564,7 @@ bool
Proxy::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
@ -2584,7 +2575,7 @@ bool
Proxy::iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
vp.setUndefined(); // default result if we refuse to perform this action
if (!handler->hasPrototype()) {
AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE,
@ -2612,14 +2603,14 @@ bool
Proxy::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
{
JS_CHECK_RECURSION(cx, return false);
return GetProxyHandler(proxy)->isExtensible(cx, proxy, extensible);
return proxy->as<ProxyObject>().handler()->isExtensible(cx, proxy, extensible);
}
bool
Proxy::preventExtensions(JSContext *cx, HandleObject proxy)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
return handler->preventExtensions(cx, proxy);
}
@ -2627,7 +2618,7 @@ bool
Proxy::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
// Because vp[0] is JS_CALLEE on the way in and JS_RVAL on the way out, we
// can only set our default value once we're sure that we're not calling the
@ -2646,7 +2637,7 @@ bool
Proxy::construct(JSContext *cx, HandleObject proxy, const CallArgs &args)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
// Because vp[0] is JS_CALLEE on the way in and JS_RVAL on the way out, we
// can only set our default value once we're sure that we're not calling the
@ -2669,33 +2660,33 @@ Proxy::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArg
// Note - we don't enter a policy here because our security architecture
// guards against nativeCall by overriding the trap itself in the right
// circumstances.
return GetProxyHandler(proxy)->nativeCall(cx, test, impl, args);
return proxy->as<ProxyObject>().handler()->nativeCall(cx, test, impl, args);
}
bool
Proxy::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp)
{
JS_CHECK_RECURSION(cx, return false);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
*bp = false; // default result if we refuse to perform this action
AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE, BaseProxyHandler::GET, true);
if (!policy.allowed())
return policy.returnValue();
return GetProxyHandler(proxy)->hasInstance(cx, proxy, v, bp);
return proxy->as<ProxyObject>().handler()->hasInstance(cx, proxy, v, bp);
}
bool
Proxy::objectClassIs(HandleObject proxy, ESClassValue classValue, JSContext *cx)
{
JS_CHECK_RECURSION(cx, return false);
return GetProxyHandler(proxy)->objectClassIs(proxy, classValue, cx);
return proxy->as<ProxyObject>().handler()->objectClassIs(proxy, classValue, cx);
}
const char *
Proxy::className(JSContext *cx, HandleObject proxy)
{
JS_CHECK_RECURSION(cx, return NULL);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE,
BaseProxyHandler::GET, /* mayThrow = */ false);
// Do the safe thing if the policy rejects.
@ -2709,7 +2700,7 @@ JSString *
Proxy::fun_toString(JSContext *cx, HandleObject proxy, unsigned indent)
{
JS_CHECK_RECURSION(cx, return NULL);
BaseProxyHandler *handler = GetProxyHandler(proxy);
BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
AutoEnterPolicy policy(cx, handler, proxy, JS::JSID_VOIDHANDLE,
BaseProxyHandler::GET, /* mayThrow = */ false);
// Do the safe thing if the policy rejects.
@ -2726,21 +2717,21 @@ bool
Proxy::regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g)
{
JS_CHECK_RECURSION(cx, return false);
return GetProxyHandler(proxy)->regexp_toShared(cx, proxy, g);
return proxy->as<ProxyObject>().handler()->regexp_toShared(cx, proxy, g);
}
bool
Proxy::defaultValue(JSContext *cx, HandleObject proxy, JSType hint, MutableHandleValue vp)
{
JS_CHECK_RECURSION(cx, return false);
return GetProxyHandler(proxy)->defaultValue(cx, proxy, hint, vp);
return proxy->as<ProxyObject>().handler()->defaultValue(cx, proxy, hint, vp);
}
bool
Proxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject proto)
{
JS_CHECK_RECURSION(cx, return false);
return GetProxyHandler(proxy)->getPrototypeOf(cx, proxy, proto);
return proxy->as<ProxyObject>().handler()->getPrototypeOf(cx, proxy, proto);
}
JSObject * const Proxy::LazyProto = reinterpret_cast<JSObject *>(0x1);
@ -2748,7 +2739,7 @@ JSObject * const Proxy::LazyProto = reinterpret_cast<JSObject *>(0x1);
static JSObject *
proxy_innerObject(JSContext *cx, HandleObject obj)
{
return GetProxyPrivate(obj).toObjectOrNull();
return obj->as<ProxyObject>().private_().toObjectOrNull();
}
static JSBool
@ -3008,52 +2999,55 @@ proxy_DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, JSBool
return proxy_DeleteGeneric(cx, obj, id, succeeded);
}
static void
proxy_TraceObject(JSTracer *trc, JSObject *obj)
/* static */ void
ProxyObject::trace(JSTracer *trc, JSObject *obj)
{
ProxyObject *proxy = &obj->as<ProxyObject>();
#ifdef DEBUG
if (!trc->runtime->gcDisableStrictProxyCheckingCount && obj->isWrapper()) {
JSObject *referent = &GetProxyPrivate(obj).toObject();
if (referent->compartment() != obj->compartment()) {
if (!trc->runtime->gcDisableStrictProxyCheckingCount && proxy->isWrapper()) {
JSObject *referent = &proxy->private_().toObject();
if (referent->compartment() != proxy->compartment()) {
/*
* Assert that this proxy is tracked in the wrapper map. We maintain
* the invariant that the wrapped object is the key in the wrapper map.
*/
Value key = ObjectValue(*referent);
WrapperMap::Ptr p = obj->compartment()->lookupWrapper(key);
JS_ASSERT(*p->value.unsafeGet() == ObjectValue(*obj));
WrapperMap::Ptr p = proxy->compartment()->lookupWrapper(key);
JS_ASSERT(*p->value.unsafeGet() == ObjectValue(*proxy));
}
}
#endif
// NB: If you add new slots here, make sure to change
// js::NukeChromeCrossCompartmentWrappers to cope.
MarkCrossCompartmentSlot(trc, obj, &obj->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "private");
MarkSlot(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 0), "extra0");
// Note: If you add new slots here, make sure to change
// nuke() to cope.
MarkCrossCompartmentSlot(trc, obj, proxy->slotOfPrivate(), "private");
MarkSlot(trc, proxy->slotOfExtra(0), "extra0");
/*
* The GC can use the second reserved slot to link the cross compartment
* wrappers into a linked list, in which case we don't want to trace it.
*/
if (!IsCrossCompartmentWrapper(obj))
MarkSlot(trc, &obj->getReservedSlotRef(JSSLOT_PROXY_EXTRA + 1), "extra1");
if (!IsCrossCompartmentWrapper(proxy))
MarkSlot(trc, proxy->slotOfExtra(1), "extra1");
}
static void
proxy_TraceFunction(JSTracer *trc, JSObject *obj)
{
// NB: If you add new slots here, make sure to change
// js::NukeChromeCrossCompartmentWrappers to cope.
MarkCrossCompartmentSlot(trc, obj, &GetCall(obj), "call");
MarkSlot(trc, &GetFunctionProxyConstruct(obj), "construct");
proxy_TraceObject(trc, obj);
// nuke() to cope.
FunctionProxyObject *proxy = &obj->as<FunctionProxyObject>();
MarkCrossCompartmentSlot(trc, proxy, &proxy->call(), "call");
MarkSlot(trc, &proxy->construct(), "construct");
ProxyObject::trace(trc, proxy);
}
static JSObject *
proxy_WeakmapKeyDelegate(JSObject *obj)
{
JS_ASSERT(obj->is<ProxyObject>());
return GetProxyHandler(obj)->weakmapKeyDelegate(obj);
return obj->as<ProxyObject>().handler()->weakmapKeyDelegate(obj);
}
static JSBool
@ -3067,7 +3061,7 @@ static void
proxy_Finalize(FreeOp *fop, JSObject *obj)
{
JS_ASSERT(obj->is<ProxyObject>());
GetProxyHandler(obj)->finalize(fop, obj);
obj->as<ProxyObject>().handler()->finalize(fop, obj);
}
static JSBool
@ -3105,7 +3099,7 @@ Class js::ObjectProxyObject::class_ = {
NULL, /* call */
proxy_HasInstance, /* hasInstance */
NULL, /* construct */
proxy_TraceObject, /* trace */
ProxyObject::trace, /* trace */
PROXY_CLASS_EXT,
{
proxy_LookupGeneric,
@ -3158,7 +3152,7 @@ Class js::OuterWindowProxyObject::class_ = {
NULL, /* call */
NULL, /* hasInstance */
NULL, /* construct */
proxy_TraceObject, /* trace */
ProxyObject::trace, /* trace */
{
NULL, /* outerObject */
proxy_innerObject,
@ -3273,9 +3267,9 @@ Class js::FunctionProxyObject::class_ = {
JS_FRIEND_DATA(Class*) js::FunctionProxyClassPtr = &FunctionProxyObject::class_;
static JSObject *
NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, TaggedProto proto_,
JSObject *parent_, ProxyCallable callable)
/* static */ ProxyObject *
ProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, TaggedProto proto_,
JSObject *parent_, ProxyCallable callable)
{
Rooted<TaggedProto> proto(cx, proto_);
RootedObject parent(cx, parent_);
@ -3308,65 +3302,77 @@ NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, Tagge
RootedObject obj(cx, NewObjectWithGivenProto(cx, clasp, proto, parent, allocKind, newKind));
if (!obj)
return NULL;
obj->initSlot(JSSLOT_PROXY_HANDLER, PrivateValue(handler));
obj->initCrossCompartmentSlot(JSSLOT_PROXY_PRIVATE, priv);
Rooted<ProxyObject*> proxy(cx, &obj->as<ProxyObject>());
proxy->initHandler(handler);
proxy->initCrossCompartmentPrivate(priv);
/* Don't track types of properties of proxies. */
if (newKind != SingletonObject)
MarkTypeObjectUnknownProperties(cx, obj->type());
MarkTypeObjectUnknownProperties(cx, proxy->type());
return obj;
return proxy;
}
JS_FRIEND_API(JSObject *)
js::NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, JSObject *proto_,
JSObject *parent_, ProxyCallable callable)
{
return NewProxyObject(cx, handler, priv, TaggedProto(proto_), parent_, callable);
return ProxyObject::New(cx, handler, priv, TaggedProto(proto_), parent_, callable);
}
static JSObject *
NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, JSObject *proto_,
JSObject *parent_, JSObject *call_, JSObject *construct_)
static ProxyObject *
NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, JSObject *proto,
JSObject *parent, JSObject *call, JSObject *construct)
{
RootedObject call(cx, call_);
RootedObject construct(cx, construct_);
if (!call && !construct)
return ProxyObject::New(cx, handler, priv, TaggedProto(proto), parent, ProxyNotCallable);
return FunctionProxyObject::New(cx, handler, priv, proto, parent, call, construct);
}
/* static */ FunctionProxyObject *
FunctionProxyObject::New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv,
JSObject *proto, JSObject *parent, JSObject *callArg,
JSObject *constructArg)
{
RootedObject call(cx, callArg);
RootedObject construct(cx, constructArg);
JS_ASSERT(call || construct);
JS_ASSERT_IF(construct, cx->compartment() == construct->compartment());
JS_ASSERT_IF(call && cx->compartment() != call->compartment(), priv == ObjectValue(*call));
JSObject *proxy = NewProxyObject(cx, handler, priv, TaggedProto(proto_), parent_,
call || construct ? ProxyIsCallable : ProxyNotCallable);
if (!proxy)
ProxyObject *obj = ProxyObject::New(cx, handler, priv, TaggedProto(proto), parent,
ProxyIsCallable);
if (!obj)
return NULL;
FunctionProxyObject *proxy = &obj->as<FunctionProxyObject>();
if (call)
proxy->initCrossCompartmentSlot(JSSLOT_PROXY_CALL, ObjectValue(*call));
proxy->initCrossCompartmentSlot(CALL_SLOT, ObjectValue(*call));
if (construct)
proxy->initCrossCompartmentSlot(JSSLOT_PROXY_CONSTRUCT, ObjectValue(*construct));
proxy->initCrossCompartmentSlot(CONSTRUCT_SLOT, ObjectValue(*construct));
return proxy;
}
JSObject *
js::RenewProxyObject(JSContext *cx, JSObject *obj,
BaseProxyHandler *handler, Value priv)
void
ProxyObject::renew(JSContext *cx, BaseProxyHandler *handler, Value priv)
{
JS_ASSERT_IF(IsCrossCompartmentWrapper(obj), IsDeadProxyObject(obj));
JS_ASSERT(obj->getParent() == cx->global());
JS_ASSERT(obj->getClass() == &ObjectProxyObject::class_);
JS_ASSERT(obj->getTaggedProto().isLazy());
JS_ASSERT_IF(IsCrossCompartmentWrapper(this), IsDeadProxyObject(this));
JS_ASSERT(getParent() == cx->global());
JS_ASSERT(getClass() == &ObjectProxyObject::class_);
JS_ASSERT(getTaggedProto().isLazy());
#ifdef DEBUG
AutoSuppressGC suppressGC(cx);
JS_ASSERT(!handler->isOuterWindow());
#endif
obj->setSlot(JSSLOT_PROXY_HANDLER, PrivateValue(handler));
obj->setCrossCompartmentSlot(JSSLOT_PROXY_PRIVATE, priv);
obj->setSlot(JSSLOT_PROXY_EXTRA + 0, UndefinedValue());
obj->setSlot(JSSLOT_PROXY_EXTRA + 1, UndefinedValue());
return obj;
setSlot(HANDLER_SLOT, PrivateValue(handler));
setCrossCompartmentSlot(PRIVATE_SLOT, priv);
setSlot(EXTRA_SLOT + 0, UndefinedValue());
setSlot(EXTRA_SLOT + 1, UndefinedValue());
}
static JSBool
@ -3389,12 +3395,11 @@ proxy(JSContext *cx, unsigned argc, jsval *vp)
return false;
RootedObject fun(cx, target->isCallable() ? target.get() : (JSObject *) NULL);
RootedValue priv(cx, ObjectValue(*target));
JSObject *proxy = NewProxyObject(cx, &ScriptedDirectProxyHandler::singleton,
priv, proto, cx->global(),
fun, fun);
ProxyObject *proxy = NewProxyObject(cx, &ScriptedDirectProxyHandler::singleton,
priv, proto, cx->global(), fun, fun);
if (!proxy)
return false;
SetProxyExtra(proxy, 0, ObjectOrNullValue(handler));
proxy->setExtra(0, ObjectOrNullValue(handler));
vp->setObject(*proxy);
return true;
}

View File

@ -287,32 +287,30 @@ inline bool IsProxy(JSObject *obj)
return IsProxyClass(GetObjectClass(obj));
}
/* Shared between object and function proxies. */
/*
* NOTE: JSSLOT_PROXY_PRIVATE is 0, because that way slot 0 is usable by API
* These are part of the API.
*
* NOTE: PROXY_PRIVATE_SLOT is 0 because that way slot 0 is usable by API
* clients for both proxy and non-proxy objects. So an API client that only
* needs to store one slot's worth of data doesn't need to branch on what sort
* of object it has.
*/
const uint32_t JSSLOT_PROXY_PRIVATE = 0;
const uint32_t JSSLOT_PROXY_HANDLER = 1;
const uint32_t JSSLOT_PROXY_EXTRA = 2;
/* Function proxies only. */
const uint32_t JSSLOT_PROXY_CALL = 4;
const uint32_t JSSLOT_PROXY_CONSTRUCT = 5;
const uint32_t PROXY_PRIVATE_SLOT = 0;
const uint32_t PROXY_HANDLER_SLOT = 1;
const uint32_t PROXY_EXTRA_SLOT = 2;
inline BaseProxyHandler *
GetProxyHandler(JSObject *obj)
{
JS_ASSERT(IsProxy(obj));
return (BaseProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate();
return (BaseProxyHandler *) GetReservedSlot(obj, PROXY_HANDLER_SLOT).toPrivate();
}
inline const Value &
GetProxyPrivate(JSObject *obj)
{
JS_ASSERT(IsProxy(obj));
return GetReservedSlot(obj, JSSLOT_PROXY_PRIVATE);
return GetReservedSlot(obj, PROXY_PRIVATE_SLOT);
}
inline JSObject *
@ -326,14 +324,14 @@ inline const Value &
GetProxyExtra(JSObject *obj, size_t n)
{
JS_ASSERT(IsProxy(obj));
return GetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n);
return GetReservedSlot(obj, PROXY_EXTRA_SLOT + n);
}
inline void
SetProxyHandler(JSObject *obj, BaseProxyHandler *handler)
{
JS_ASSERT(IsProxy(obj));
SetReservedSlot(obj, JSSLOT_PROXY_HANDLER, PrivateValue(handler));
SetReservedSlot(obj, PROXY_HANDLER_SLOT, PrivateValue(handler));
}
inline void
@ -341,7 +339,7 @@ SetProxyExtra(JSObject *obj, size_t n, const Value &extra)
{
JS_ASSERT(IsProxy(obj));
JS_ASSERT(n <= 1);
SetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n, extra);
SetReservedSlot(obj, PROXY_EXTRA_SLOT + n, extra);
}
enum ProxyCallable {

View File

@ -258,7 +258,8 @@ TryPreserveReflector(JSContext *cx, HandleObject obj)
{
if (obj->getClass()->ext.isWrappedNative ||
(obj->getClass()->flags & JSCLASS_IS_DOMJSCLASS) ||
(obj->is<ProxyObject>() && GetProxyHandler(obj)->family() == GetDOMProxyHandlerFamily()))
(obj->is<ProxyObject>() &&
obj->as<ProxyObject>().handler()->family() == GetDOMProxyHandlerFamily()))
{
JS_ASSERT(cx->runtime()->preserveWrapperCallback);
if (!cx->runtime()->preserveWrapperCallback(cx, obj)) {

View File

@ -47,21 +47,22 @@ JSObject *
Wrapper::Renew(JSContext *cx, JSObject *existing, JSObject *obj, Wrapper *handler)
{
JS_ASSERT(!obj->isCallable());
return RenewProxyObject(cx, existing, handler, ObjectValue(*obj));
existing->as<ProxyObject>().renew(cx, handler, ObjectValue(*obj));
return existing;
}
Wrapper *
Wrapper::wrapperHandler(JSObject *wrapper)
{
JS_ASSERT(wrapper->isWrapper());
return static_cast<Wrapper*>(GetProxyHandler(wrapper));
return static_cast<Wrapper*>(wrapper->as<ProxyObject>().handler());
}
JSObject *
Wrapper::wrappedObject(JSObject *wrapper)
{
JS_ASSERT(wrapper->isWrapper());
return GetProxyTargetObject(wrapper);
return wrapper->as<ProxyObject>().target();
}
JS_FRIEND_API(JSObject *)
@ -71,7 +72,7 @@ js::UncheckedUnwrap(JSObject *wrapped, bool stopAtOuter, unsigned *flagsp)
while (wrapped->isWrapper() &&
!JS_UNLIKELY(stopAtOuter && wrapped->getClass()->ext.innerObject)) {
flags |= Wrapper::wrapperHandler(wrapped)->flags();
wrapped = GetProxyPrivate(wrapped).toObjectOrNull();
wrapped = wrapped->as<ProxyObject>().private_().toObjectOrNull();
}
if (flagsp)
*flagsp = flags;
@ -836,20 +837,8 @@ js::NewDeadProxyObject(JSContext *cx, JSObject *parent)
bool
js::IsDeadProxyObject(JSObject *obj)
{
return obj->is<ProxyObject>() && GetProxyHandler(obj) == &DeadObjectProxy::singleton;
}
static void
NukeSlot(JSObject *wrapper, uint32_t slot, Value v)
{
Value old = wrapper->getSlot(slot);
if (old.isMarkable()) {
Zone *zone = ZoneOfValue(old);
AutoMarkInDeadZone amd(zone);
wrapper->setReservedSlot(slot, v);
} else {
wrapper->setReservedSlot(slot, v);
}
return obj->is<ProxyObject>() &&
obj->as<ProxyObject>().handler() == &DeadObjectProxy::singleton;
}
void
@ -859,16 +848,7 @@ js::NukeCrossCompartmentWrapper(JSContext *cx, JSObject *wrapper)
NotifyGCNukeWrapper(wrapper);
NukeSlot(wrapper, JSSLOT_PROXY_PRIVATE, NullValue());
SetProxyHandler(wrapper, &DeadObjectProxy::singleton);
if (wrapper->is<FunctionProxyObject>()) {
NukeSlot(wrapper, JSSLOT_PROXY_CALL, NullValue());
NukeSlot(wrapper, JSSLOT_PROXY_CONSTRUCT, NullValue());
}
NukeSlot(wrapper, JSSLOT_PROXY_EXTRA + 0, NullValue());
NukeSlot(wrapper, JSSLOT_PROXY_EXTRA + 1, NullValue());
wrapper->as<ProxyObject>().nuke(&DeadObjectProxy::singleton);
JS_ASSERT(IsDeadProxyObject(wrapper));
}

View File

@ -112,6 +112,7 @@ CPP_SOURCES += [
'Probes.cpp',
'Profilers.cpp',
'PropertyKey.cpp',
'ProxyObject.cpp',
'RegExp.cpp',
'RegExpObject.cpp',
'RegExpStatics.cpp',

View File

@ -2099,7 +2099,8 @@ Debugger::construct(JSContext *cx, unsigned argc, Value *vp)
/* Add the initial debuggees, if any. */
for (unsigned i = 0; i < argc; i++) {
Rooted<GlobalObject*> debuggee(cx, &GetProxyPrivate(&args[i].toObject()).toObject().global());
Rooted<GlobalObject*>
debuggee(cx, &args[i].toObject().as<ProxyObject>().private_().toObject().global());
if (!dbg->addDebuggeeGlobal(cx, debuggee))
return false;
}

60
js/src/vm/ProxyObject.cpp Normal file
View File

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "vm/ProxyObject.h"
#include "jsgcinlines.h"
#include "jsobjinlines.h"
#include "gc/Barrier-inl.h"
#include "vm/ObjectImpl-inl.h"
using namespace js;
void
ProxyObject::initCrossCompartmentPrivate(HandleValue priv)
{
initCrossCompartmentSlot(PRIVATE_SLOT, priv);
}
void
ProxyObject::initHandler(BaseProxyHandler *handler)
{
initSlot(HANDLER_SLOT, PrivateValue(handler));
}
static void
NukeSlot(ProxyObject *proxy, uint32_t slot)
{
Value old = proxy->getSlot(slot);
if (old.isMarkable()) {
Zone *zone = ZoneOfValue(old);
AutoMarkInDeadZone amd(zone);
proxy->setReservedSlot(slot, NullValue());
} else {
proxy->setReservedSlot(slot, NullValue());
}
}
void
ProxyObject::nuke(BaseProxyHandler *handler)
{
NukeSlot(this, PRIVATE_SLOT);
setHandler(handler);
NukeSlot(this, EXTRA_SLOT + 0);
NukeSlot(this, EXTRA_SLOT + 1);
if (is<FunctionProxyObject>())
as<FunctionProxyObject>().nukeExtra();
}
void
FunctionProxyObject::nukeExtra()
{
NukeSlot(this, CALL_SLOT);
NukeSlot(this, CONSTRUCT_SLOT);
}

View File

@ -16,12 +16,88 @@ namespace js {
// instantiated.
class ProxyObject : public JSObject
{
// These are just local renamings of the slot constants that are part of
// the API in jsproxy.h.
static const uint32_t PRIVATE_SLOT = PROXY_PRIVATE_SLOT;
static const uint32_t HANDLER_SLOT = PROXY_HANDLER_SLOT;
static const uint32_t EXTRA_SLOT = PROXY_EXTRA_SLOT;
public:
static ProxyObject *New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv,
TaggedProto proto_, JSObject *parent_, ProxyCallable callable);
const Value &private_() {
return GetReservedSlot(this, PRIVATE_SLOT);
}
void initCrossCompartmentPrivate(HandleValue priv);
HeapSlot *slotOfPrivate() {
return &getReservedSlotRef(PRIVATE_SLOT);
}
JSObject *target() const {
return const_cast<ProxyObject*>(this)->private_().toObjectOrNull();
}
BaseProxyHandler *handler() {
return static_cast<BaseProxyHandler*>(GetReservedSlot(this, HANDLER_SLOT).toPrivate());
}
void initHandler(BaseProxyHandler *handler);
void setHandler(BaseProxyHandler *handler) {
SetReservedSlot(this, HANDLER_SLOT, PrivateValue(handler));
}
static size_t offsetOfHandler() {
return getFixedSlotOffset(HANDLER_SLOT);
}
const Value &extra(size_t n) const {
JS_ASSERT(n == 0 || n == 1);
return GetReservedSlot(const_cast<ProxyObject*>(this), EXTRA_SLOT + n);
}
void setExtra(size_t n, const Value &extra) {
JS_ASSERT(n == 0 || n == 1);
SetReservedSlot(this, EXTRA_SLOT + n, extra);
}
private:
HeapSlot *slotOfExtra(size_t n) {
JS_ASSERT(n == 0 || n == 1);
return &getReservedSlotRef(EXTRA_SLOT + n);
}
public:
static unsigned grayLinkSlot(JSObject *obj);
void renew(JSContext *cx, BaseProxyHandler *handler, Value priv);
static void trace(JSTracer *trc, JSObject *obj);
void nuke(BaseProxyHandler *handler);
};
class FunctionProxyObject : public ProxyObject
{
static const uint32_t CALL_SLOT = 4;
static const uint32_t CONSTRUCT_SLOT = 5;
public:
static Class class_;
static FunctionProxyObject *New(JSContext *cx, BaseProxyHandler *handler, HandleValue priv,
JSObject *proto, JSObject *parent, JSObject *call,
JSObject *construct);
HeapSlot &call() { return getSlotRef(CALL_SLOT); }
inline HeapSlot &construct();
inline Value constructOrUndefined() const;
void nukeExtra();
};
class ObjectProxyObject : public ProxyObject

View File

@ -1549,36 +1549,38 @@ DebugScopeObject::create(JSContext *cx, ScopeObject &scope, HandleObject enclosi
return NULL;
JS_ASSERT(!enclosing->is<ScopeObject>());
SetProxyExtra(obj, ENCLOSING_EXTRA, ObjectValue(*enclosing));
SetProxyExtra(obj, SNAPSHOT_EXTRA, NullValue());
return &obj->as<DebugScopeObject>();
DebugScopeObject *debugScope = &obj->as<DebugScopeObject>();
debugScope->setExtra(ENCLOSING_EXTRA, ObjectValue(*enclosing));
debugScope->setExtra(SNAPSHOT_EXTRA, NullValue());
return debugScope;
}
ScopeObject &
DebugScopeObject::scope() const
{
return GetProxyTargetObject(const_cast<DebugScopeObject*>(this))->as<ScopeObject>();
return target()->as<ScopeObject>();
}
JSObject &
DebugScopeObject::enclosingScope() const
{
return GetProxyExtra(const_cast<DebugScopeObject*>(this), ENCLOSING_EXTRA).toObject();
return extra(ENCLOSING_EXTRA).toObject();
}
JSObject *
DebugScopeObject::maybeSnapshot() const
{
JS_ASSERT(!scope().as<CallObject>().isForEval());
return GetProxyExtra(const_cast<DebugScopeObject*>(this), SNAPSHOT_EXTRA).toObjectOrNull();
return extra(SNAPSHOT_EXTRA).toObjectOrNull();
}
void
DebugScopeObject::initSnapshot(JSObject &o)
{
JS_ASSERT(maybeSnapshot() == NULL);
SetProxyExtra(this, SNAPSHOT_EXTRA, ObjectValue(o));
setExtra(SNAPSHOT_EXTRA, ObjectValue(o));
}
bool
@ -1592,7 +1594,7 @@ bool
js_IsDebugScopeSlow(ObjectProxyObject *proxy)
{
JS_ASSERT(proxy->hasClass(&ObjectProxyObject::class_));
return GetProxyHandler(proxy) == &DebugScopeProxy::singleton;
return proxy->handler() == &DebugScopeProxy::singleton;
}
/*****************************************************************************/