зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1396613 - Make proxy objects override handler's objectMoved method rather than using class hook r=sfink r=mccr8 r=peterv
This commit is contained in:
Родитель
2a663c4c5a
Коммит
8bd8591183
|
@ -1144,6 +1144,7 @@ public:
|
|||
JS::Handle<JSObject*> wrapper) const override;
|
||||
|
||||
void finalize(JSFreeOp *fop, JSObject *proxy) const override;
|
||||
size_t objectMoved(JSObject* proxy, JSObject* old) const override;
|
||||
|
||||
bool isCallable(JSObject *obj) const override {
|
||||
return false;
|
||||
|
@ -1157,8 +1158,6 @@ public:
|
|||
bool unwatch(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id) const override;
|
||||
|
||||
static size_t ObjectMoved(JSObject *obj, JSObject *old);
|
||||
|
||||
static const nsOuterWindowProxy singleton;
|
||||
|
||||
protected:
|
||||
|
@ -1188,17 +1187,12 @@ protected:
|
|||
JS::AutoIdVector &props) const;
|
||||
};
|
||||
|
||||
static const js::ClassExtension OuterWindowProxyClassExtension = PROXY_MAKE_EXT(
|
||||
nsOuterWindowProxy::ObjectMoved
|
||||
);
|
||||
|
||||
// Give OuterWindowProxyClass 2 reserved slots, like the other wrappers, so
|
||||
// JSObject::swap can swap it with CrossCompartmentWrappers without requiring
|
||||
// malloc.
|
||||
const js::Class OuterWindowProxyClass = PROXY_CLASS_WITH_EXT(
|
||||
const js::Class OuterWindowProxyClass = PROXY_CLASS_DEF(
|
||||
"Proxy",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(2), /* additional class flags */
|
||||
&OuterWindowProxyClassExtension);
|
||||
JSCLASS_HAS_RESERVED_SLOTS(2)); /* additional class flags */
|
||||
|
||||
const char *
|
||||
nsOuterWindowProxy::className(JSContext *cx, JS::Handle<JSObject*> proxy) const
|
||||
|
@ -1527,7 +1521,7 @@ nsOuterWindowProxy::unwatch(JSContext *cx, JS::Handle<JSObject*> proxy,
|
|||
}
|
||||
|
||||
size_t
|
||||
nsOuterWindowProxy::ObjectMoved(JSObject *obj, const JSObject *old)
|
||||
nsOuterWindowProxy::objectMoved(JSObject *obj, JSObject *old) const
|
||||
{
|
||||
nsGlobalWindow* outerWindow = GetOuterWindow(obj);
|
||||
if (outerWindow) {
|
||||
|
|
|
@ -544,23 +544,16 @@ class CGDOMProxyJSClass(CGThing):
|
|||
# HTMLAllCollection. So just hardcode it here.
|
||||
if self.descriptor.interface.identifier.name == "HTMLAllCollection":
|
||||
flags.append("JSCLASS_EMULATES_UNDEFINED")
|
||||
objectMovedHook = OBJECT_MOVED_HOOK_NAME if self.descriptor.wrapperCache else 'nullptr'
|
||||
return fill(
|
||||
"""
|
||||
static const js::ClassExtension sClassExtension = PROXY_MAKE_EXT(
|
||||
${objectMoved}
|
||||
);
|
||||
|
||||
static const DOMJSClass sClass = {
|
||||
PROXY_CLASS_WITH_EXT("${name}",
|
||||
${flags},
|
||||
&sClassExtension),
|
||||
PROXY_CLASS_DEF("${name}",
|
||||
${flags}),
|
||||
$*{descriptor}
|
||||
};
|
||||
""",
|
||||
name=self.descriptor.interface.identifier.name,
|
||||
flags=" | ".join(flags),
|
||||
objectMoved=objectMovedHook,
|
||||
descriptor=DOMClass(self.descriptor))
|
||||
|
||||
|
||||
|
@ -1731,6 +1724,19 @@ class CGClassFinalizeHook(CGAbstractClassHook):
|
|||
self.args[0].name, self.args[1].name).define()
|
||||
|
||||
|
||||
def objectMovedHook(descriptor, hookName, obj, old):
|
||||
assert descriptor.wrapperCache
|
||||
return fill("""
|
||||
if (self) {
|
||||
UpdateWrapper(self, self, ${obj}, ${old});
|
||||
}
|
||||
|
||||
return 0;
|
||||
""",
|
||||
obj=obj,
|
||||
old=old)
|
||||
|
||||
|
||||
class CGClassObjectMovedHook(CGAbstractClassHook):
|
||||
"""
|
||||
A hook for objectMovedOp, used to update the wrapper cache when an object it
|
||||
|
@ -1742,11 +1748,8 @@ class CGClassObjectMovedHook(CGAbstractClassHook):
|
|||
'size_t', args)
|
||||
|
||||
def generate_code(self):
|
||||
assert self.descriptor.wrapperCache
|
||||
return CGList([
|
||||
CGIfWrapper(CGGeneric("UpdateWrapper(self, self, obj, old);\n"),
|
||||
"self"),
|
||||
CGGeneric("return 0;\n")]).define()
|
||||
return objectMovedHook(self.descriptor, self.name,
|
||||
self.args[0].name, self.args[1].name)
|
||||
|
||||
|
||||
def JSNativeArguments():
|
||||
|
@ -12406,6 +12409,20 @@ class CGDOMJSProxyHandler_finalize(ClassMethod):
|
|||
self.args[0].name, self.args[1].name).define())
|
||||
|
||||
|
||||
class CGDOMJSProxyHandler_objectMoved(ClassMethod):
|
||||
def __init__(self, descriptor):
|
||||
args = [Argument('JSObject*', 'obj'), Argument('JSObject*', 'old')]
|
||||
ClassMethod.__init__(self, "objectMoved", "size_t", args,
|
||||
virtual=True, override=True, const=True)
|
||||
self.descriptor = descriptor
|
||||
|
||||
def getBody(self):
|
||||
return (("%s* self = UnwrapPossiblyNotInitializedDOMObject<%s>(obj);\n" %
|
||||
(self.descriptor.nativeType, self.descriptor.nativeType)) +
|
||||
objectMovedHook(self.descriptor, OBJECT_MOVED_HOOK_NAME,
|
||||
self.args[0].name, self.args[1].name))
|
||||
|
||||
|
||||
class CGDOMJSProxyHandler_getElements(ClassMethod):
|
||||
def __init__(self, descriptor):
|
||||
assert descriptor.supportsIndexedProperties()
|
||||
|
@ -12581,6 +12598,8 @@ class CGDOMJSProxyHandler(CGClass):
|
|||
raise TypeError("Need a wrapper cache to support nursery "
|
||||
"allocation of DOM objects")
|
||||
methods.append(CGDOMJSProxyHandler_canNurseryAllocate())
|
||||
if descriptor.wrapperCache:
|
||||
methods.append(CGDOMJSProxyHandler_objectMoved(descriptor))
|
||||
|
||||
if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
|
||||
parentClass = 'ShadowingDOMProxyHandler'
|
||||
|
@ -12837,7 +12856,7 @@ class CGDescriptor(CGThing):
|
|||
# wants a custom hook.
|
||||
cgThings.append(CGClassFinalizeHook(descriptor))
|
||||
|
||||
if descriptor.concrete and descriptor.wrapperCache:
|
||||
if descriptor.concrete and descriptor.wrapperCache and not descriptor.proxy:
|
||||
cgThings.append(CGClassObjectMovedHook(descriptor))
|
||||
|
||||
# Generate the _ClearCachedFooValue methods before the property arrays that use them.
|
||||
|
|
|
@ -232,6 +232,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
void finalize(JSFreeOp* fop, JSObject* proxy) const override;
|
||||
|
||||
size_t objectMoved(JSObject* obj, JSObject* old) const override;
|
||||
};
|
||||
|
||||
const char NPObjWrapperProxyHandler::family = 0;
|
||||
|
@ -241,9 +243,6 @@ static bool
|
|||
NPObjWrapper_Resolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||
bool* resolved, JS::MutableHandle<JSObject*> method);
|
||||
|
||||
static size_t
|
||||
NPObjWrapper_ObjectMoved(JSObject *obj, JSObject *old);
|
||||
|
||||
static bool
|
||||
NPObjWrapper_toPrimitive(JSContext *cx, unsigned argc, JS::Value *vp);
|
||||
|
||||
|
@ -253,14 +252,9 @@ CreateNPObjectMember(NPP npp, JSContext *cx,
|
|||
JS::Handle<jsid> id, NPVariant* getPropertyResult,
|
||||
JS::MutableHandle<JS::Value> vp);
|
||||
|
||||
static const js::ClassExtension sNPObjWrapperProxyClassExtension = PROXY_MAKE_EXT(
|
||||
NPObjWrapper_ObjectMoved
|
||||
);
|
||||
|
||||
const js::Class sNPObjWrapperProxyClass = PROXY_CLASS_WITH_EXT(
|
||||
const js::Class sNPObjWrapperProxyClass = PROXY_CLASS_DEF(
|
||||
NPRUNTIME_JSCLASS_NAME,
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1),
|
||||
&sNPObjWrapperProxyClassExtension);
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1));
|
||||
|
||||
typedef struct NPObjectMemberPrivate {
|
||||
JS::Heap<JSObject *> npobjWrapper;
|
||||
|
@ -1787,8 +1781,8 @@ NPObjWrapperProxyHandler::finalize(JSFreeOp* fop, JSObject* proxy) const
|
|||
sDelayedReleases->AppendElement(npobj);
|
||||
}
|
||||
|
||||
static size_t
|
||||
NPObjWrapper_ObjectMoved(JSObject *obj, JSObject *old)
|
||||
size_t
|
||||
NPObjWrapperProxyHandler::objectMoved(JSObject *obj, JSObject *old) const
|
||||
{
|
||||
// The wrapper JSObject has been moved, so we need to update the entry in the
|
||||
// sNPObjWrappers hash table, if present.
|
||||
|
|
|
@ -684,18 +684,6 @@ extern JS_FRIEND_DATA(const js::ClassOps) ProxyClassOps;
|
|||
extern JS_FRIEND_DATA(const js::ClassExtension) ProxyClassExtension;
|
||||
extern JS_FRIEND_DATA(const js::ObjectOps) ProxyObjectOps;
|
||||
|
||||
/*
|
||||
* Helper Macros for creating JSClasses that function as proxies.
|
||||
*
|
||||
* NB: The macro invocation must be surrounded by braces, so as to
|
||||
* allow for potential JSClass extensions.
|
||||
*/
|
||||
#define PROXY_MAKE_EXT(objectMoved) \
|
||||
{ \
|
||||
js::proxy_WeakmapKeyDelegate, \
|
||||
objectMoved \
|
||||
}
|
||||
|
||||
template <unsigned Flags>
|
||||
constexpr unsigned
|
||||
CheckProxyFlags()
|
||||
|
@ -722,7 +710,7 @@ CheckProxyFlags()
|
|||
return Flags;
|
||||
}
|
||||
|
||||
#define PROXY_CLASS_WITH_EXT(name, flags, extPtr) \
|
||||
#define PROXY_CLASS_DEF(name, flags) \
|
||||
{ \
|
||||
name, \
|
||||
js::Class::NON_NATIVE | \
|
||||
|
@ -731,13 +719,10 @@ CheckProxyFlags()
|
|||
js::CheckProxyFlags<flags>(), \
|
||||
&js::ProxyClassOps, \
|
||||
JS_NULL_CLASS_SPEC, \
|
||||
extPtr, \
|
||||
&js::ProxyClassExtension, \
|
||||
&js::ProxyObjectOps \
|
||||
}
|
||||
|
||||
#define PROXY_CLASS_DEF(name, flags) \
|
||||
PROXY_CLASS_WITH_EXT(name, flags, &js::ProxyClassExtension)
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* js_Proxy_h */
|
||||
|
|
|
@ -2976,17 +2976,9 @@ js::TenuringTracer::moveObjectToTenured(JSObject* dst, JSObject* src, AllocKind
|
|||
// shape list. This is updated in Nursery::sweepDictionaryModeObjects().
|
||||
}
|
||||
|
||||
if (src->is<ProxyObject>()) {
|
||||
// TODO: Push this logic into proxy_ObjectMoved and make all proxies use
|
||||
// this.
|
||||
|
||||
// Objects in the nursery are never swapped so the proxy must have an
|
||||
// inline ProxyValueArray.
|
||||
MOZ_ASSERT(src->as<ProxyObject>().usingInlineValueArray());
|
||||
dst->as<ProxyObject>().setInlineValueArray();
|
||||
if (JSObjectMovedOp op = dst->getClass()->extObjectMovedOp())
|
||||
tenuredSize += op(dst, src);
|
||||
} else if (JSObjectMovedOp op = dst->getClass()->extObjectMovedOp()) {
|
||||
JSObjectMovedOp op = dst->getClass()->extObjectMovedOp();
|
||||
MOZ_ASSERT_IF(src->is<ProxyObject>(), op == proxy_ObjectMoved);
|
||||
if (op) {
|
||||
tenuredSize += op(dst, src);
|
||||
} else {
|
||||
MOZ_ASSERT_IF(src->getClass()->hasFinalize(),
|
||||
|
|
|
@ -14,14 +14,9 @@
|
|||
|
||||
#include "vm/ProxyObject.h"
|
||||
|
||||
static const js::ClassExtension OuterWrapperClassExtension = PROXY_MAKE_EXT(
|
||||
nullptr /* objectMoved */
|
||||
);
|
||||
|
||||
const js::Class OuterWrapperClass = PROXY_CLASS_WITH_EXT(
|
||||
const js::Class OuterWrapperClass = PROXY_CLASS_DEF(
|
||||
"Proxy",
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1), /* additional class flags */
|
||||
&OuterWrapperClassExtension);
|
||||
JSCLASS_HAS_RESERVED_SLOTS(1) /* additional class flags */);
|
||||
|
||||
static JSObject*
|
||||
wrap(JSContext* cx, JS::HandleObject toWrap, JS::HandleObject target)
|
||||
|
|
|
@ -741,11 +741,19 @@ proxy_Finalize(FreeOp* fop, JSObject* obj)
|
|||
js_free(js::detail::GetProxyDataLayout(obj)->values());
|
||||
}
|
||||
|
||||
static size_t
|
||||
proxy_ObjectMoved(JSObject* obj, JSObject* old)
|
||||
size_t
|
||||
js::proxy_ObjectMoved(JSObject* obj, JSObject* old)
|
||||
{
|
||||
MOZ_ASSERT(obj->is<ProxyObject>());
|
||||
return obj->as<ProxyObject>().handler()->objectMoved(obj, old);
|
||||
ProxyObject& proxy = obj->as<ProxyObject>();
|
||||
|
||||
if (IsInsideNursery(old)) {
|
||||
// Objects in the nursery are never swapped so the proxy must have an
|
||||
// inline ProxyValueArray.
|
||||
MOZ_ASSERT(old->as<ProxyObject>().usingInlineValueArray());
|
||||
proxy.setInlineValueArray();
|
||||
}
|
||||
|
||||
return proxy.handler()->objectMoved(obj, old);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -780,9 +788,10 @@ const ClassOps js::ProxyClassOps = {
|
|||
ProxyObject::trace, /* trace */
|
||||
};
|
||||
|
||||
const ClassExtension js::ProxyClassExtension = PROXY_MAKE_EXT(
|
||||
const ClassExtension js::ProxyClassExtension = {
|
||||
proxy_WeakmapKeyDelegate,
|
||||
proxy_ObjectMoved
|
||||
);
|
||||
};
|
||||
|
||||
const ObjectOps js::ProxyObjectOps = {
|
||||
proxy_LookupProperty,
|
||||
|
|
|
@ -80,6 +80,8 @@ bool
|
|||
proxy_Call(JSContext* cx, unsigned argc, Value* vp);
|
||||
bool
|
||||
proxy_Construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
size_t
|
||||
proxy_ObjectMoved(JSObject* obj, JSObject* old);
|
||||
|
||||
// These functions are used by JIT code
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче