Bug 887558 (part 1) - Introduce ProxyObject and some sub-classes. r=jorendorff.

--HG--
extra : rebase_source : 33ed2aff35acbe4de8891a9fb34c60e7a314d9c8
This commit is contained in:
Nicholas Nethercote 2013-06-20 21:27:28 -07:00
Родитель e5b78f3048
Коммит ff86dae788
33 изменённых файлов: 194 добавлений и 117 удалений

Просмотреть файл

@ -1350,7 +1350,7 @@ GetXrayExpandoChain(JSObject* obj)
JS::Value v;
if (IsDOMClass(clasp) || IsDOMIfaceAndProtoClass(clasp)) {
v = js::GetReservedSlot(obj, DOM_XRAY_EXPANDO_SLOT);
} else if (js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) {
} else if (js::IsProxyClass(clasp)) {
MOZ_ASSERT(js::GetProxyHandler(obj)->family() == ProxyFamily());
v = js::GetProxyExtra(obj, JSPROXYSLOT_XRAY_EXPANDO);
} else {
@ -1367,7 +1367,7 @@ SetXrayExpandoChain(JSObject* obj, JSObject* chain)
js::Class* clasp = js::GetObjectClass(obj);
if (IsDOMClass(clasp) || IsDOMIfaceAndProtoClass(clasp)) {
js::SetReservedSlot(obj, DOM_XRAY_EXPANDO_SLOT, v);
} else if (js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) {
} else if (js::IsProxyClass(clasp)) {
MOZ_ASSERT(js::GetProxyHandler(obj)->family() == ProxyFamily());
js::SetProxyExtra(obj, JSPROXYSLOT_XRAY_EXPANDO, v);
} else {

Просмотреть файл

@ -150,7 +150,7 @@ GetDOMClass(JSObject* obj)
return &DOMJSClass::FromJSClass(clasp)->mClass;
}
if (js::IsObjectProxyClass(clasp) || js::IsFunctionProxyClass(clasp)) {
if (js::IsProxyClass(clasp)) {
js::BaseProxyHandler* handler = js::GetProxyHandler(obj);
if (handler->family() == ProxyFamily()) {
return &static_cast<DOMProxyHandler*>(handler)->mClass;

Просмотреть файл

@ -420,7 +420,7 @@ obj_lookupGetter(JSContext *cx, unsigned argc, Value *vp)
RootedObject obj(cx, ToObject(cx, args.thisv()));
if (!obj)
return JS_FALSE;
if (obj->isProxy()) {
if (obj->is<ProxyObject>()) {
// The vanilla getter lookup code below requires that the object is
// native. Handle proxies separately.
args.rval().setUndefined();
@ -456,7 +456,7 @@ obj_lookupSetter(JSContext *cx, unsigned argc, Value *vp)
RootedObject obj(cx, ToObject(cx, args.thisv()));
if (!obj)
return JS_FALSE;
if (obj->isProxy()) {
if (obj->is<ProxyObject>()) {
// The vanilla setter lookup code below requires that the object is
// native. Handle proxies separately.
args.rval().setUndefined();
@ -612,7 +612,7 @@ obj_hasOwnProperty(JSContext *cx, unsigned argc, Value *vp)
if (args.thisv().isObject() && ValueToId<NoGC>(cx, idValue, &id)) {
JSObject *obj = &args.thisv().toObject(), *obj2;
Shape *prop;
if (!obj->isProxy() &&
if (!obj->is<ProxyObject>() &&
HasOwnProperty<NoGC>(cx, obj->getOps()->lookupGeneric, obj, id, &obj2, &prop))
{
args.rval().setBoolean(!!prop);
@ -633,7 +633,7 @@ obj_hasOwnProperty(JSContext *cx, unsigned argc, Value *vp)
/* Non-standard code for proxies. */
RootedObject obj2(cx);
RootedShape prop(cx);
if (obj->isProxy()) {
if (obj->is<ProxyObject>()) {
bool has;
if (!Proxy::hasOwn(cx, obj, idRoot, &has))
return false;

Просмотреть файл

@ -331,7 +331,7 @@ IsProxy(JSContext *cx, unsigned argc, jsval *vp)
args.rval().setBoolean(false);
return true;
}
args.rval().setBoolean(args[0].toObject().isProxy());
args.rval().setBoolean(args[0].toObject().is<ProxyObject>());
return true;
}

Просмотреть файл

@ -3066,7 +3066,7 @@ static void GetFixedOrDynamicSlotOffset(HandleObject obj, uint32_t slot,
static bool
IsCacheableDOMProxy(JSObject *obj)
{
if (!obj->isProxy())
if (!obj->is<ProxyObject>())
return false;
BaseProxyHandler *handler = GetProxyHandler(obj);
@ -8570,7 +8570,7 @@ ICGetPropCallDOMProxyNativeCompiler::ICGetPropCallDOMProxyNativeCompiler(JSConte
{
JS_ASSERT(kind == ICStub::GetProp_CallDOMProxyNative ||
kind == ICStub::GetProp_CallDOMProxyWithGenerationNative);
JS_ASSERT(obj_->isProxy());
JS_ASSERT(obj_->is<ProxyObject>());
JS_ASSERT(GetProxyHandler(obj_)->family() == GetDOMProxyHandlerFamily());
}

Просмотреть файл

@ -424,7 +424,7 @@ IonCache::initializeAddCacheState(LInstruction *ins, AddCacheState *addState)
static bool
IsCacheableDOMProxy(JSObject *obj)
{
if (!obj->isProxy())
if (!obj->is<ProxyObject>())
return false;
BaseProxyHandler *handler = GetProxyHandler(obj);
@ -1348,7 +1348,7 @@ DetermineGetPropKind(JSContext *cx, IonCache &cache, JSObject *receiver,
{
// With Proxies, we cannot garantee any property access as the proxy can
// mask any property from the prototype chain.
JS_ASSERT(!checkObj->isProxy());
JS_ASSERT(!checkObj->is<ProxyObject>());
*readSlot = true;
} else if (IsCacheableGetPropCallNative(checkObj, holder, shape) ||
IsCacheableGetPropCallPropertyOp(checkObj, holder, shape))

Просмотреть файл

@ -24,6 +24,7 @@
#include "ion/ParallelFunctions.h"
#include "ion/VMFunctions.h"
#include "vm/ForkJoin.h"
#include "vm/ProxyObject.h"
#include "vm/Shape.h"
#include "vm/TypedArrayObject.h"
@ -753,9 +754,9 @@ class MacroAssembler : public MacroAssemblerSpecific
// of the JSObject::isWrapper test performed in EmulatesUndefined. If none
// of the branches are taken, we can check class flags directly.
loadObjClass(objReg, scratch);
branchPtr(Assembler::Equal, scratch, ImmWord(&ObjectProxyClass), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmWord(&OuterWindowProxyClass), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmWord(&FunctionProxyClass), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmWord(&ObjectProxyObject::class_), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmWord(&OuterWindowProxyObject::class_), slowCheck);
branchPtr(Assembler::Equal, scratch, ImmWord(&FunctionProxyObject::class_), slowCheck);
test32(Address(scratch, Class::offsetOfFlags()), Imm32(JSCLASS_EMULATES_UNDEFINED));
return truthy ? Assembler::Zero : Assembler::NonZero;

Просмотреть файл

@ -114,7 +114,7 @@ JS::detail::CallMethodIfWrapped(JSContext *cx, IsAcceptableThis test, NativeImpl
if (thisv.isObject()) {
JSObject &thisObj = args.thisv().toObject();
if (thisObj.isProxy())
if (thisObj.is<ProxyObject>())
return Proxy::nativeCall(cx, test, impl, args);
}
@ -1779,7 +1779,7 @@ static const JSStdName standard_class_atoms[] = {
#ifdef ENABLE_PARALLEL_JS
{js_InitParallelArrayClass, EAGER_ATOM_AND_OCLASP(ParallelArray)},
#endif
{js_InitProxyClass, EAGER_CLASS_ATOM(Proxy), &js::ObjectProxyClass},
{js_InitProxyClass, EAGER_CLASS_ATOM(Proxy), OCLASP(ObjectProxy)},
#if ENABLE_INTL_API
{js_InitIntlClass, EAGER_ATOM_AND_CLASP(Intl)},
#endif
@ -3483,7 +3483,7 @@ LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, HandleId id,
}
if (!obj2->isNative()) {
if (obj2->isProxy()) {
if (obj2->is<ProxyObject>()) {
AutoPropertyDescriptorRooter desc(cx);
if (!Proxy::getPropertyDescriptor(cx, obj2, id, &desc, 0))
return false;
@ -3994,7 +3994,7 @@ GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id, unsigned
desc->value.setUndefined();
}
} else {
if (obj2->isProxy()) {
if (obj2->is<ProxyObject>()) {
JSAutoResolveFlags rf(cx, flags);
return own
? Proxy::getOwnPropertyDescriptor(cx, obj2, id, desc, 0)

Просмотреть файл

@ -17,6 +17,7 @@
#include "jsobj.h"
#include "vm/GlobalObject.h"
#include "vm/ProxyObject.h"
#include "vm/StringBuffer.h"
#include "jsboolinlines.h"
@ -200,7 +201,7 @@ js::ToBooleanSlow(const Value &v)
bool
js::BooleanGetPrimitiveValueSlow(HandleObject wrappedBool, JSContext *cx)
{
JS_ASSERT(wrappedBool->isProxy());
JS_ASSERT(wrappedBool->is<ProxyObject>());
JSObject *obj = Wrapper::wrappedObject(wrappedBool);
JS_ASSERT(obj);
return obj->as<BooleanObject>().unbox();

Просмотреть файл

@ -278,7 +278,7 @@ CallJSNativeConstructor(JSContext *cx, Native native, const CallArgs &args)
*
* - (new Object(Object)) returns the callee.
*/
JS_ASSERT_IF(native != FunctionProxyClass.construct &&
JS_ASSERT_IF(native != FunctionProxyObject::class_.construct &&
native != js::CallOrConstructBoundFunction &&
native != js::IteratorConstructor &&
(!callee->is<JSFunction>() || callee->as<JSFunction>().native() != obj_construct),

Просмотреть файл

@ -312,7 +312,8 @@ JSCompartment::wrap(JSContext *cx, MutableHandleValue vp, HandleObject existingA
if (existing) {
/* Is it possible to reuse |existing|? */
if (!existing->getTaggedProto().isLazy() ||
existing->getClass() != &ObjectProxyClass ||
// Note: don't use is<ObjectProxyObject>() here -- it also matches subclasses!
existing->getClass() != &ObjectProxyObject::class_ ||
existing->getParent() != global ||
obj->isCallable())
{

Просмотреть файл

@ -574,7 +574,7 @@ JS_GetCustomIteratorCount(JSContext *cx)
JS_FRIEND_API(JSBool)
JS_IsDeadWrapper(JSObject *obj)
{
if (!IsProxy(obj)) {
if (!obj->is<ProxyObject>()) {
return false;
}

Просмотреть файл

@ -387,9 +387,12 @@ struct Atom {
} /* namespace shadow */
extern JS_FRIEND_DATA(js::Class) FunctionProxyClass;
extern JS_FRIEND_DATA(js::Class) OuterWindowProxyClass;
extern JS_FRIEND_DATA(js::Class) ObjectProxyClass;
// These are equal to |&{Function,Object,OuterWindow}ProxyObject::class_|. Use
// them in places where you don't want to #include vm/ProxyObject.h.
extern JS_FRIEND_DATA(js::Class*) FunctionProxyClassPtr;
extern JS_FRIEND_DATA(js::Class*) ObjectProxyClassPtr;
extern JS_FRIEND_DATA(js::Class*) OuterWindowProxyClassPtr;
extern JS_FRIEND_DATA(js::Class) ObjectClass;
inline js::Class *
@ -492,9 +495,9 @@ inline bool
GetObjectProto(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JSObject*> proto)
{
js::Class *clasp = GetObjectClass(obj);
if (clasp == &js::ObjectProxyClass ||
clasp == &js::OuterWindowProxyClass ||
clasp == &js::FunctionProxyClass)
if (clasp == js::ObjectProxyClassPtr ||
clasp == js::OuterWindowProxyClassPtr ||
clasp == js::FunctionProxyClassPtr)
{
return JS_GetPrototype(cx, obj, proto.address());
}

Просмотреть файл

@ -746,7 +746,7 @@ JSString *
fun_toStringHelper(JSContext *cx, HandleObject obj, unsigned indent)
{
if (!obj->is<JSFunction>()) {
if (IsFunctionProxy(obj))
if (obj->is<FunctionProxyObject>())
return Proxy::fun_toString(cx, obj, indent);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_INCOMPATIBLE_PROTO,

Просмотреть файл

@ -106,7 +106,7 @@ Enumerate(JSContext *cx, HandleObject pobj, jsid id,
if (JS_UNLIKELY(!pobj->getTaggedProto().isObject() && JSID_IS_ATOM(id, cx->names().proto)))
return true;
if (!(flags & JSITER_OWNONLY) || pobj->isProxy() || pobj->getOps()->enumerate) {
if (!(flags & JSITER_OWNONLY) || pobj->is<ProxyObject>() || pobj->getOps()->enumerate) {
/* If we've already seen this, we definitely won't add it. */
IdSet::AddPtr p = ht.lookupForAdd(id);
if (JS_UNLIKELY(!!p))
@ -117,7 +117,7 @@ Enumerate(JSContext *cx, HandleObject pobj, jsid id,
* the prototype chain, but custom enumeration behaviors might return
* duplicated properties, so always add in such cases.
*/
if ((pobj->isProxy() || pobj->getProto() || pobj->getOps()->enumerate) && !ht.add(p, id))
if ((pobj->is<ProxyObject>() || pobj->getProto() || pobj->getOps()->enumerate) && !ht.add(p, id))
return false;
}
@ -206,7 +206,7 @@ Snapshot(JSContext *cx, JSObject *pobj_, unsigned flags, AutoIdVector *props)
if (!EnumerateNativeProperties(cx, pobj, flags, ht, props))
return false;
} else {
if (pobj->isProxy()) {
if (pobj->is<ProxyObject>()) {
AutoIdVector proxyProps(cx);
if (flags & JSITER_OWNONLY) {
if (flags & JSITER_HIDDEN) {
@ -682,7 +682,7 @@ js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleVa
}
miss:
if (obj->isProxy()) {
if (obj->is<ProxyObject>()) {
types::MarkIteratorUnknown(cx);
return Proxy::iterate(cx, obj, flags, vp);
}

Просмотреть файл

@ -267,7 +267,7 @@ js::GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id,
PropertyDescriptor *desc)
{
// FIXME: Call TrapGetOwnProperty directly once ScriptedIndirectProxies is removed
if (obj->isProxy())
if (obj->is<ProxyObject>())
return Proxy::getOwnPropertyDescriptor(cx, obj, id, desc, 0);
RootedObject pobj(cx);
@ -990,7 +990,7 @@ js::DefineProperty(JSContext *cx, HandleObject obj, HandleId id, const PropDesc
* FIXME: Once ScriptedIndirectProxies are removed, this code should call
* TrapDefineOwnProperty directly
*/
if (obj->isProxy()) {
if (obj->is<ProxyObject>()) {
RootedValue pd(cx, desc.pd());
return Proxy::defineProperty(cx, obj, id, pd);
}
@ -1080,7 +1080,7 @@ js::DefineProperties(JSContext *cx, HandleObject obj, HandleObject props)
* FIXME: Once ScriptedIndirectProxies are removed, this code should call
* TrapDefineOwnProperty directly
*/
if (obj->isProxy()) {
if (obj->is<ProxyObject>()) {
for (size_t i = 0, len = ids.length(); i < len; i++) {
RootedValue pd(cx, descs[i].pd());
if (!Proxy::defineProperty(cx, obj, ids.handleAt(i), pd))
@ -1270,7 +1270,7 @@ JSObject::className(JSContext *cx, HandleObject obj)
{
assertSameCompartment(cx, obj);
if (obj->isProxy())
if (obj->is<ProxyObject>())
return Proxy::className(cx, obj);
return obj->getClass()->name;
@ -1842,7 +1842,7 @@ CopySlots(JSContext *cx, HandleObject from, HandleObject to)
JSObject *
js::CloneObject(JSContext *cx, HandleObject obj, Handle<js::TaggedProto> proto, HandleObject parent)
{
if (!obj->isNative() && !obj->isProxy()) {
if (!obj->isNative() && !obj->is<ProxyObject>()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CANT_CLONE_OBJECT);
return NULL;
@ -1860,7 +1860,7 @@ js::CloneObject(JSContext *cx, HandleObject obj, Handle<js::TaggedProto> proto,
if (obj->hasPrivate())
clone->setPrivate(obj->getPrivate());
} else {
JS_ASSERT(obj->isProxy());
JS_ASSERT(obj->is<ProxyObject>());
if (!CopySlots(cx, obj, clone))
return NULL;
}
@ -4154,7 +4154,7 @@ GetPropertyHelperInline(JSContext *cx,
HandleObject receiverHandle = MaybeRooted<JSObject*, allowGC>::toHandle(receiver);
HandleId idHandle = MaybeRooted<jsid, allowGC>::toHandle(id);
MutableHandleValue vpHandle = MaybeRooted<Value, allowGC>::toMutableHandle(vp);
return obj2->isProxy()
return obj2->template is<ProxyObject>()
? Proxy::get(cx, obj2Handle, receiverHandle, idHandle, vpHandle)
: JSObject::getGeneric(cx, obj2Handle, obj2Handle, idHandle, vpHandle);
}
@ -4515,7 +4515,7 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive
return false;
if (shape) {
if (!pobj->isNative()) {
if (pobj->isProxy()) {
if (pobj->is<ProxyObject>()) {
AutoPropertyDescriptorRooter pd(cx);
if (!Proxy::getPropertyDescriptor(cx, pobj, id, &pd, JSRESOLVE_ASSIGNING))
return false;
@ -5375,7 +5375,7 @@ DumpProperty(JSObject *obj, Shape &shape)
bool
JSObject::uninlinedIsProxy() const
{
return isProxy();
return is<ProxyObject>();
}
void
@ -5388,7 +5388,7 @@ JSObject::dump()
fprintf(stderr, "flags:");
if (obj->isDelegate()) fprintf(stderr, " delegate");
if (!obj->isProxy() && !obj->nonProxyIsExtensible()) fprintf(stderr, " not_extensible");
if (!obj->is<ProxyObject>() && !obj->nonProxyIsExtensible()) fprintf(stderr, " not_extensible");
if (obj->isIndexed()) fprintf(stderr, " indexed");
if (obj->isNative()) {

Просмотреть файл

@ -993,11 +993,6 @@ class JSObject : public js::ObjectImpl
* Note that X represents a low-level representation and does not query the
* [[Class]] property of object defined by the spec (for this, see
* js::ObjectClassIs).
*
* SpiderMonkey has not been completely switched to the is/as/XObject
* pattern so in some cases there is no XObject class and the engine
* instead pokes directly at reserved slots and getPrivate. In such cases,
* consider adding the missing XObject class.
*/
template <class T>
@ -1017,11 +1012,9 @@ class JSObject : public js::ObjectImpl
/* Direct subtypes of JSObject: */
inline bool isObject() const { return hasClass(&js::ObjectClass); }
using js::ObjectImpl::isProxy;
/* Subtypes of Proxy. */
inline bool isWrapper() const;
inline bool isFunctionProxy() const { return hasClass(&js::FunctionProxyClass); }
inline bool isCrossCompartmentWrapper() const;
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; }

Просмотреть файл

@ -538,7 +538,7 @@ JSObject::setType(js::types::TypeObject *newType)
JSObject::getProto(JSContext *cx, js::HandleObject obj, js::MutableHandleObject protop)
{
if (obj->getTaggedProto().isLazy()) {
JS_ASSERT(obj->isProxy());
JS_ASSERT(obj->is<js::ProxyObject>());
return js::Proxy::getPrototypeOf(cx, obj, protop);
} else {
protop.set(obj->js::ObjectImpl::getProto());
@ -850,7 +850,7 @@ IsNativeFunction(const js::Value &v, JSNative native)
static JS_ALWAYS_INLINE bool
ClassMethodIsNative(JSContext *cx, JSObject *obj, Class *clasp, jsid methodid, JSNative native)
{
JS_ASSERT(!obj->isProxy());
JS_ASSERT(!obj->is<ProxyObject>());
JS_ASSERT(obj->getClass() == clasp);
Value v;
@ -1157,7 +1157,7 @@ DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
inline bool
ObjectClassIs(HandleObject obj, ESClassValue classValue, JSContext *cx)
{
if (JS_UNLIKELY(obj->isProxy()))
if (JS_UNLIKELY(obj->is<ProxyObject>()))
return Proxy::objectClassIs(obj, classValue, cx);
switch (classValue) {

Просмотреть файл

@ -672,7 +672,7 @@ Walk(JSContext *cx, HandleObject holder, HandleId name, HandleValue reviver, Mut
RootedObject obj(cx, &val.toObject());
/* 'val' must have been produced by the JSON parser, so not a proxy. */
JS_ASSERT(!obj->isProxy());
JS_ASSERT(!obj->is<ProxyObject>());
if (obj->is<ArrayObject>()) {
/* Step 2a(ii). */
uint32_t length = obj->as<ArrayObject>().length();

Просмотреть файл

@ -29,7 +29,7 @@ using mozilla::ArrayLength;
static inline HeapSlot &
GetCall(JSObject *proxy)
{
JS_ASSERT(IsFunctionProxy(proxy));
JS_ASSERT(proxy->is<FunctionProxyObject>());
return proxy->getSlotRef(JSSLOT_PROXY_CALL);
}
@ -44,7 +44,7 @@ GetConstruct(JSObject *proxy)
static inline HeapSlot &
GetFunctionProxyConstruct(JSObject *proxy)
{
JS_ASSERT(IsFunctionProxy(proxy));
JS_ASSERT(proxy->is<FunctionProxyObject>());
JS_ASSERT(proxy->slotSpan() > JSSLOT_PROXY_CONSTRUCT);
return proxy->getSlotRef(JSSLOT_PROXY_CONSTRUCT);
}
@ -88,7 +88,7 @@ js::AutoEnterPolicy::recordLeave()
JS_FRIEND_API(void)
js::assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id)
{
MOZ_ASSERT(proxy->isProxy());
MOZ_ASSERT(proxy->is<ProxyObject>());
MOZ_ASSERT(cx->runtime()->enteredPolicy);
MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredProxy.ref().get() == proxy);
MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredId.ref().get() == id);
@ -211,7 +211,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->isProxy() || GetProxyHandler(proxy) != this)
if (!proxy->is<ProxyObject>() || GetProxyHandler(proxy) != this)
return true;
if (desc.attrs & JSPROP_SHARED)
return true;
@ -238,7 +238,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->isProxy() || GetProxyHandler(proxy) != this)
if (!proxy->is<ProxyObject>() || GetProxyHandler(proxy) != this)
return true;
if (desc.attrs & JSPROP_SHARED)
return true;
@ -320,7 +320,7 @@ BaseProxyHandler::construct(JSContext *cx, HandleObject proxy, const CallArgs &a
const char *
BaseProxyHandler::className(JSContext *cx, HandleObject proxy)
{
return IsFunctionProxy(proxy) ? "Function" : "Object";
return proxy->is<FunctionProxyObject>() ? "Function" : "Object";
}
JSString *
@ -402,7 +402,7 @@ GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, unsigned
{
// If obj is a proxy, we can do better than just guessing. This is
// important for certain types of wrappers that wrap other wrappers.
if (obj->isProxy())
if (obj->is<ProxyObject>())
return Proxy::getOwnPropertyDescriptor(cx, obj, id, desc, flags);
if (!JS_GetPropertyDescriptorById(cx, obj, id, flags, desc))
@ -1039,7 +1039,7 @@ ScriptedIndirectProxyHandler::fun_toString(JSContext *cx, HandleObject proxy, un
{
assertEnteredPolicy(cx, proxy, JSID_VOID);
Value fval = GetCall(proxy);
if (IsFunctionProxy(proxy) &&
if (proxy->is<FunctionProxyObject>() &&
(fval.isPrimitive() || !fval.toObject().is<JSFunction>())) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_INCOMPATIBLE_PROTO,
@ -3052,21 +3052,21 @@ proxy_TraceFunction(JSTracer *trc, JSObject *obj)
static JSObject *
proxy_WeakmapKeyDelegate(JSObject *obj)
{
JS_ASSERT(obj->isProxy());
JS_ASSERT(obj->is<ProxyObject>());
return GetProxyHandler(obj)->weakmapKeyDelegate(obj);
}
static JSBool
proxy_Convert(JSContext *cx, HandleObject proxy, JSType hint, MutableHandleValue vp)
{
JS_ASSERT(proxy->isProxy());
JS_ASSERT(proxy->is<ProxyObject>());
return Proxy::defaultValue(cx, proxy, hint, vp);
}
static void
proxy_Finalize(FreeOp *fop, JSObject *obj)
{
JS_ASSERT(obj->isProxy());
JS_ASSERT(obj->is<ProxyObject>());
GetProxyHandler(obj)->finalize(fop, obj);
}
@ -3089,7 +3089,7 @@ proxy_HasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, JSBoo
proxy_WeakmapKeyDelegate \
}
JS_FRIEND_DATA(Class) js::ObjectProxyClass = {
Class js::ObjectProxyObject::class_ = {
"Proxy",
Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(4) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy),
@ -3141,7 +3141,9 @@ JS_FRIEND_DATA(Class) js::ObjectProxyClass = {
}
};
JS_FRIEND_DATA(Class) js::OuterWindowProxyClass = {
JS_FRIEND_DATA(Class*) js::ObjectProxyClassPtr = &ObjectProxyObject::class_;
Class js::OuterWindowProxyObject::class_ = {
"Proxy",
Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(4),
JS_PropertyStub, /* addProperty */
@ -3198,12 +3200,14 @@ JS_FRIEND_DATA(Class) js::OuterWindowProxyClass = {
}
};
JS_FRIEND_DATA(Class*) js::OuterWindowProxyClassPtr = &OuterWindowProxyObject::class_;
static JSBool
proxy_Call(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject proxy(cx, &args.callee());
JS_ASSERT(proxy->isProxy());
JS_ASSERT(proxy->is<ProxyObject>());
return Proxy::call(cx, proxy, args);
}
@ -3212,11 +3216,11 @@ proxy_Construct(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
RootedObject proxy(cx, &args.callee());
JS_ASSERT(proxy->isProxy());
JS_ASSERT(proxy->is<ProxyObject>());
return Proxy::construct(cx, proxy, args);
}
JS_FRIEND_DATA(Class) js::FunctionProxyClass = {
Class js::FunctionProxyObject::class_ = {
"Proxy",
Class::NON_NATIVE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(6),
JS_PropertyStub, /* addProperty */
@ -3267,6 +3271,8 @@ JS_FRIEND_DATA(Class) js::FunctionProxyClass = {
}
};
JS_FRIEND_DATA(Class*) js::FunctionProxyClassPtr = &FunctionProxyObject::class_;
static JSObject *
NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, TaggedProto proto_,
JSObject *parent_, ProxyCallable callable)
@ -3278,9 +3284,10 @@ NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, Tagge
JS_ASSERT_IF(parent, cx->compartment() == parent->compartment());
Class *clasp;
if (callable)
clasp = &FunctionProxyClass;
clasp = &FunctionProxyObject::class_;
else
clasp = handler->isOuterWindow() ? &OuterWindowProxyClass : &ObjectProxyClass;
clasp = handler->isOuterWindow() ? &OuterWindowProxyObject::class_
: &ObjectProxyObject::class_;
/*
* Eagerly mark properties unknown for proxies, so we don't try to track
@ -3293,7 +3300,8 @@ NewProxyObject(JSContext *cx, BaseProxyHandler *handler, HandleValue priv, Tagge
return NULL;
}
NewObjectKind newKind = clasp == &OuterWindowProxyClass ? SingletonObject : GenericObject;
NewObjectKind newKind =
clasp == &OuterWindowProxyObject::class_ ? SingletonObject : GenericObject;
gc::AllocKind allocKind = gc::GetGCObjectKind(clasp);
if (handler->finalizeInBackground(priv))
allocKind = GetBackgroundAllocKind(allocKind);
@ -3346,7 +3354,7 @@ js::RenewProxyObject(JSContext *cx, JSObject *obj,
{
JS_ASSERT_IF(IsCrossCompartmentWrapper(obj), IsDeadProxyObject(obj));
JS_ASSERT(obj->getParent() == cx->global());
JS_ASSERT(obj->getClass() == &ObjectProxyClass);
JS_ASSERT(obj->getClass() == &ObjectProxyObject::class_);
JS_ASSERT(obj->getTaggedProto().isLazy());
#ifdef DEBUG
AutoSuppressGC suppressGC(cx);
@ -3482,6 +3490,6 @@ js_InitProxyClass(JSContext *cx, HandleObject obj)
return NULL;
}
MarkStandardClassInitializedNoProto(obj, &ObjectProxyClass);
MarkStandardClassInitializedNoProto(obj, &ObjectProxyObject::class_);
return ctor;
}

Просмотреть файл

@ -259,12 +259,17 @@ class Proxy
inline bool IsObjectProxyClass(const Class *clasp)
{
return clasp == &js::ObjectProxyClass || clasp == &js::OuterWindowProxyClass;
return clasp == js::ObjectProxyClassPtr || clasp == js::OuterWindowProxyClassPtr;
}
inline bool IsFunctionProxyClass(const Class *clasp)
{
return clasp == &js::FunctionProxyClass;
return clasp == js::FunctionProxyClassPtr;
}
inline bool IsProxyClass(const Class *clasp)
{
return IsObjectProxyClass(clasp) || IsFunctionProxyClass(clasp);
}
inline bool IsObjectProxy(JSObject *obj)
@ -279,8 +284,7 @@ inline bool IsFunctionProxy(JSObject *obj)
inline bool IsProxy(JSObject *obj)
{
Class *clasp = GetObjectClass(obj);
return IsObjectProxyClass(clasp) || IsFunctionProxyClass(clasp);
return IsProxyClass(GetObjectClass(obj));
}
/* Shared between object and function proxies. */

Просмотреть файл

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

Просмотреть файл

@ -836,7 +836,7 @@ js::NewDeadProxyObject(JSContext *cx, JSObject *parent)
bool
js::IsDeadProxyObject(JSObject *obj)
{
return IsProxy(obj) && GetProxyHandler(obj) == &DeadObjectProxy::singleton;
return obj->is<ProxyObject>() && GetProxyHandler(obj) == &DeadObjectProxy::singleton;
}
static void
@ -862,7 +862,7 @@ js::NukeCrossCompartmentWrapper(JSContext *cx, JSObject *wrapper)
NukeSlot(wrapper, JSSLOT_PROXY_PRIVATE, NullValue());
SetProxyHandler(wrapper, &DeadObjectProxy::singleton);
if (IsFunctionProxy(wrapper)) {
if (wrapper->is<FunctionProxyObject>()) {
NukeSlot(wrapper, JSSLOT_PROXY_CALL, NullValue());
NukeSlot(wrapper, JSSLOT_PROXY_CONSTRUCT, NullValue());
}

Просмотреть файл

@ -2685,7 +2685,7 @@ CopyProperty(JSContext *cx, HandleObject obj, HandleObject referent, HandleId id
desc.setter = JS_StrictPropertyStub;
desc.shortid = shape->shortid();
propFlags = shape->getFlags();
} else if (IsProxy(referent)) {
} else if (referent->is<ProxyObject>()) {
if (!Proxy::getOwnPropertyDescriptor(cx, referent, id, &desc, 0))
return false;
if (!desc.obj)

Просмотреть файл

@ -101,7 +101,7 @@ TestProtoSetterThis(const Value &v)
return true;
/* Otherwise, only accept non-proxies. */
return !v.toObject().isProxy();
return !v.toObject().is<ProxyObject>();
}
static bool
@ -138,10 +138,10 @@ ProtoSetterImpl(JSContext *cx, CallArgs args)
* which due to their complicated delegate-object shenanigans can't easily
* have a mutable [[Prototype]].
*/
if (obj->isProxy() || obj->is<ArrayBufferObject>()) {
if (obj->is<ProxyObject>() || obj->is<ArrayBufferObject>()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
"Object", "__proto__ setter",
obj->isProxy() ? "Proxy" : "ArrayBuffer");
obj->is<ProxyObject>() ? "Proxy" : "ArrayBuffer");
return false;
}

Просмотреть файл

@ -19,6 +19,9 @@
#include "vm/ObjectImpl.h"
#include "gc/Barrier-inl.h"
#include "vm/Interpreter.h"
#include "vm/ObjectImpl.h"
#include "vm/ProxyObject.h"
inline JSCompartment *
js::ObjectImpl::compartment() const
@ -41,7 +44,7 @@ js::ObjectImpl::nativeContainsPure(Shape *shape)
inline bool
js::ObjectImpl::nonProxyIsExtensible() const
{
MOZ_ASSERT(!isProxy());
MOZ_ASSERT(!asObjectPtr()->is<ProxyObject>());
// [[Extensible]] for ordinary non-proxy objects is an object flag.
return !lastProperty()->hasObjectFlag(BaseShape::NOT_EXTENSIBLE);
@ -50,7 +53,7 @@ js::ObjectImpl::nonProxyIsExtensible() const
/* static */ inline bool
js::ObjectImpl::isExtensible(ExclusiveContext *cx, js::Handle<ObjectImpl*> obj, bool *extensible)
{
if (obj->isProxy()) {
if (obj->asObjectPtr()->is<ProxyObject>()) {
HandleObject h =
HandleObject::fromMarkedLocation(reinterpret_cast<JSObject* const*>(obj.address()));
return Proxy::isExtensible(cx->asJSContext(), h, extensible);
@ -66,12 +69,6 @@ js::ObjectImpl::isNative() const
return lastProperty()->isNative();
}
inline bool
js::ObjectImpl::isProxy() const
{
return js::IsProxy(const_cast<JSObject*>(this->asObjectPtr()));
}
#ifdef DEBUG
inline bool
IsObjectValueInCompartment(js::Value v, JSCompartment *comp)

Просмотреть файл

@ -156,7 +156,7 @@ PropDesc::wrapInto(JSContext *cx, HandleObject obj, const jsid &id, jsid *wrappe
desc->value_ = value;
desc->get_ = get;
desc->set_ = set;
return !obj->isProxy() || desc->makeObject(cx);
return !obj->is<ProxyObject>() || desc->makeObject(cx);
}
static ObjectElements emptyElementsHeader(0, 0);
@ -568,9 +568,8 @@ js::GetOwnProperty(JSContext *cx, Handle<ObjectImpl*> obj, PropertyId pid_, unsi
Rooted<PropertyId> pid(cx, pid_);
if (static_cast<JSObject *>(obj.get())->isProxy()) {
if (Downcast(obj)->is<ProxyObject>())
MOZ_ASSUME_UNREACHABLE("NYI: proxy [[GetOwnProperty]]");
}
RootedShape shape(cx, obj->nativeLookup(cx, pid));
if (!shape) {
@ -662,9 +661,8 @@ js::GetProperty(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> rece
do {
MOZ_ASSERT(obj);
if (Downcast(current)->isProxy()) {
if (Downcast(current)->is<ProxyObject>())
MOZ_ASSUME_UNREACHABLE("NYI: proxy [[GetP]]");
}
AutoPropDescRooter desc(cx);
if (!GetOwnProperty(cx, current, pid, resolveFlags, &desc.getPropDesc()))
@ -725,9 +723,8 @@ js::GetElement(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> recei
do {
MOZ_ASSERT(current);
if (Downcast(current)->isProxy()) {
if (Downcast(current)->is<ProxyObject>())
MOZ_ASSUME_UNREACHABLE("NYI: proxy [[GetP]]");
}
PropDesc desc;
if (!GetOwnElement(cx, current, index, resolveFlags, &desc))
@ -788,9 +785,8 @@ js::HasElement(JSContext *cx, Handle<ObjectImpl*> obj, uint32_t index, unsigned
do {
MOZ_ASSERT(current);
if (Downcast(current)->isProxy()) {
if (Downcast(current)->is<ProxyObject>())
MOZ_ASSUME_UNREACHABLE("NYI: proxy [[HasProperty]]");
}
PropDesc prop;
if (!GetOwnElement(cx, current, index, resolveFlags, &prop))
@ -952,9 +948,8 @@ js::SetElement(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> recei
do {
MOZ_ASSERT(current);
if (Downcast(current)->isProxy()) {
if (Downcast(current)->is<ProxyObject>())
MOZ_ASSUME_UNREACHABLE("NYI: proxy [[SetP]]");
}
PropDesc ownDesc;
if (!GetOwnElement(cx, current, index, resolveFlags, &ownDesc))

Просмотреть файл

@ -1282,8 +1282,6 @@ class ObjectImpl : public gc::Cell
MOZ_ASSUME_UNREACHABLE("NYI");
}
inline bool isProxy() const;
protected:
#ifdef DEBUG
void checkShapeConsistency();

71
js/src/vm/ProxyObject.h Normal file
Просмотреть файл

@ -0,0 +1,71 @@
/* -*- 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/. */
#ifndef vm_ProxyObject_h
#define vm_ProxyObject_h
#include "jsobj.h"
#include "jsproxy.h"
namespace js {
// This is the base class for the various kinds of proxy objects. It's never
// instantiated.
class ProxyObject : public JSObject
{
};
class FunctionProxyObject : public ProxyObject
{
public:
static Class class_;
};
class ObjectProxyObject : public ProxyObject
{
public:
static Class class_;
};
class OuterWindowProxyObject : public ObjectProxyObject
{
public:
static Class class_;
};
} // namespace js
// Note: the following |JSObject::is<T>| methods are implemented in terms of
// the Is*Proxy() friend API functions to ensure the implementations are tied
// together. The exception is |JSObject::is<js::OuterWindowProxyObject>()
// const|, which uses the standard template definition, because there is no
// IsOuterWindowProxy() function in the friend API.
template<>
inline bool
JSObject::is<js::ProxyObject>() const
{
return js::IsProxy(const_cast<JSObject*>(this));
}
template<>
inline bool
JSObject::is<js::FunctionProxyObject>() const
{
return js::IsFunctionProxy(const_cast<JSObject*>(this));
}
// WARNING: This function succeeds for ObjectProxyObject *and*
// OuterWindowProxyObject (which is a sub-class). If you want a test that only
// succeeds for ObjectProxyObject, use |hasClass(&ObjectProxyObject::class_)|.
template<>
inline bool
JSObject::is<js::ObjectProxyObject>() const
{
return js::IsObjectProxy(const_cast<JSObject*>(this));
}
#endif /* vm_ProxyObject_h */

Просмотреть файл

@ -10,6 +10,7 @@
#include "jsiter.h"
#include "vm/GlobalObject.h"
#include "vm/ProxyObject.h"
#include "vm/ScopeObject.h"
#include "vm/Shape.h"
#include "vm/Xdr.h"
@ -1588,10 +1589,10 @@ DebugScopeObject::isForDeclarative() const
}
bool
js_IsDebugScopeSlow(JSObject *obj)
js_IsDebugScopeSlow(ObjectProxyObject *proxy)
{
return obj->getClass() == &ObjectProxyClass &&
GetProxyHandler(obj) == &DebugScopeProxy::singleton;
JS_ASSERT(proxy->hasClass(&ObjectProxyObject::class_));
return GetProxyHandler(proxy) == &DebugScopeProxy::singleton;
}
/*****************************************************************************/

Просмотреть файл

@ -12,6 +12,7 @@
#include "jsweakmap.h"
#include "gc/Barrier.h"
#include "vm/ProxyObject.h"
namespace js {
@ -587,7 +588,7 @@ extern JSObject *
GetDebugScopeForFrame(JSContext *cx, AbstractFramePtr frame);
/* Provides debugger access to a scope. */
class DebugScopeObject : public JSObject
class DebugScopeObject : public ObjectProxyObject
{
/*
* The enclosing scope on the dynamic scope chain. This slot is analogous
@ -699,8 +700,11 @@ template<>
inline bool
JSObject::is<js::DebugScopeObject>() const
{
extern bool js_IsDebugScopeSlow(JSObject *obj);
return getClass() == &js::ObjectProxyClass && js_IsDebugScopeSlow(const_cast<JSObject*>(this));
extern bool js_IsDebugScopeSlow(js::ObjectProxyObject *proxy);
// Note: don't use is<ObjectProxyObject>() here -- it also matches subclasses!
return hasClass(&js::ObjectProxyObject::class_) &&
js_IsDebugScopeSlow(&const_cast<JSObject*>(this)->as<js::ObjectProxyObject>());
}
template<>

Просмотреть файл

@ -1093,7 +1093,7 @@ js::ObjectImpl::preventExtensions(JSContext *cx, Handle<ObjectImpl*> obj)
"preventExtensions");
#endif
if (obj->isProxy()) {
if (Downcast(obj)->is<ProxyObject>()) {
RootedObject object(cx, obj->asObjectPtr());
return js::Proxy::preventExtensions(cx, object);
}

Просмотреть файл

@ -2140,8 +2140,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject
return NULL; // must be arrayBuffer
}
JS_ASSERT(bufobj->is<ArrayBufferObject>() || bufobj->isProxy());
if (bufobj->isProxy()) {
JS_ASSERT(bufobj->is<ArrayBufferObject>() || bufobj->is<ProxyObject>());
if (bufobj->is<ProxyObject>()) {
/*
* Normally, NonGenericMethodGuard handles the case of transparent
* wrappers. However, we have a peculiar situation: we want to