mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 956806 part 2. Share generic getters/setters/methods across all bindings. r=peterv
This commit is contained in:
parent
2292f3d2fe
commit
9ba0ae8d76
@ -89,6 +89,23 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
|
||||
const ErrNum aErrorNumber,
|
||||
prototypes::ID aProtoId)
|
||||
{
|
||||
return ThrowInvalidThis(aCx, aArgs, aErrorNumber,
|
||||
NamesOfInterfacesWithProtos[aProtoId]);
|
||||
}
|
||||
|
||||
bool
|
||||
ThrowNoSetterArg(JSContext* aCx, prototypes::ID aProtoId)
|
||||
{
|
||||
nsPrintfCString errorMessage("%s attribute setter",
|
||||
NamesOfInterfacesWithProtos[aProtoId]);
|
||||
return ThrowErrorMessage(aCx, MSG_MISSING_ARGUMENTS, errorMessage.get());
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
||||
struct ErrorResult::Message {
|
||||
@ -2202,5 +2219,94 @@ EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj)
|
||||
return JS_EnumerateStandardClasses(aCx, aObj);
|
||||
}
|
||||
|
||||
bool
|
||||
GenericBindingGetter(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(args.calleev());
|
||||
prototypes::ID protoID = static_cast<prototypes::ID>(info->protoID);
|
||||
if (!args.thisv().isObject()) {
|
||||
return ThrowInvalidThis(cx, args,
|
||||
MSG_GETTER_THIS_DOES_NOT_IMPLEMENT_INTERFACE,
|
||||
protoID);
|
||||
}
|
||||
JS::Rooted<JSObject*> obj(cx, &args.thisv().toObject());
|
||||
|
||||
void* self;
|
||||
{
|
||||
nsresult rv = UnwrapObject<void>(obj, self, protoID, info->depth);
|
||||
if (NS_FAILED(rv)) {
|
||||
return ThrowInvalidThis(cx, args,
|
||||
GetInvalidThisErrorForGetter(rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO),
|
||||
protoID);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(info->type() == JSJitInfo::Getter);
|
||||
JSJitGetterOp getter = info->getter;
|
||||
return getter(cx, obj, self, JSJitGetterCallArgs(args));
|
||||
}
|
||||
|
||||
bool
|
||||
GenericBindingSetter(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(args.calleev());
|
||||
prototypes::ID protoID = static_cast<prototypes::ID>(info->protoID);
|
||||
if (!args.thisv().isObject()) {
|
||||
return ThrowInvalidThis(cx, args,
|
||||
MSG_SETTER_THIS_DOES_NOT_IMPLEMENT_INTERFACE,
|
||||
protoID);
|
||||
}
|
||||
JS::Rooted<JSObject*> obj(cx, &args.thisv().toObject());
|
||||
|
||||
void* self;
|
||||
{
|
||||
nsresult rv = UnwrapObject<void>(obj, self, protoID, info->depth);
|
||||
if (NS_FAILED(rv)) {
|
||||
return ThrowInvalidThis(cx, args,
|
||||
GetInvalidThisErrorForSetter(rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO),
|
||||
protoID);
|
||||
}
|
||||
}
|
||||
if (args.length() == 0) {
|
||||
return ThrowNoSetterArg(cx, protoID);
|
||||
}
|
||||
MOZ_ASSERT(info->type() == JSJitInfo::Setter);
|
||||
JSJitSetterOp setter = info->setter;
|
||||
if (!setter(cx, obj, self, JSJitSetterCallArgs(args))) {
|
||||
return false;
|
||||
}
|
||||
args.rval().set(JSVAL_VOID);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GenericBindingMethod(JSContext* cx, unsigned argc, JS::Value* vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(args.calleev());
|
||||
prototypes::ID protoID = static_cast<prototypes::ID>(info->protoID);
|
||||
if (!args.thisv().isObject()) {
|
||||
return ThrowInvalidThis(cx, args,
|
||||
MSG_METHOD_THIS_DOES_NOT_IMPLEMENT_INTERFACE,
|
||||
protoID);
|
||||
}
|
||||
JS::Rooted<JSObject*> obj(cx, &args.thisv().toObject());
|
||||
|
||||
void* self;
|
||||
{
|
||||
nsresult rv = UnwrapObject<void>(obj, self, protoID, info->depth);
|
||||
if (NS_FAILED(rv)) {
|
||||
return ThrowInvalidThis(cx, args,
|
||||
GetInvalidThisErrorForMethod(rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO),
|
||||
protoID);
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(info->type() == JSJitInfo::Method);
|
||||
JSJitMethodOp method = info->method;
|
||||
return method(cx, obj, self, JSJitMethodCallArgs(args));
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -93,6 +93,11 @@ ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
|
||||
const ErrNum aErrorNumber,
|
||||
const char* aInterfaceName);
|
||||
|
||||
bool
|
||||
ThrowInvalidThis(JSContext* aCx, const JS::CallArgs& aArgs,
|
||||
const ErrNum aErrorNumber,
|
||||
prototypes::ID aProtoId);
|
||||
|
||||
inline bool
|
||||
ThrowMethodFailedWithDetails(JSContext* cx, ErrorResult& rv,
|
||||
const char* ifaceName,
|
||||
@ -206,9 +211,10 @@ IsDOMObject(JSObject* obj)
|
||||
// (for example, overload resolution uses unwrapping to tell what sort
|
||||
// of thing it's looking at).
|
||||
// U must be something that a T* can be assigned to (e.g. T* or an nsRefPtr<T>).
|
||||
template <prototypes::ID PrototypeID, class T, typename U>
|
||||
template <class T, typename U>
|
||||
MOZ_ALWAYS_INLINE nsresult
|
||||
UnwrapObject(JSObject* obj, U& value)
|
||||
UnwrapObject(JSObject* obj, U& value, prototypes::ID protoID,
|
||||
uint32_t protoDepth)
|
||||
{
|
||||
/* First check to see whether we have a DOM object */
|
||||
const DOMClass* domClass = GetDOMClass(obj);
|
||||
@ -234,8 +240,7 @@ UnwrapObject(JSObject* obj, U& value)
|
||||
/* This object is a DOM object. Double-check that it is safely
|
||||
castable to T by checking whether it claims to inherit from the
|
||||
class identified by protoID. */
|
||||
if (domClass->mInterfaceChain[PrototypeTraits<PrototypeID>::Depth] ==
|
||||
PrototypeID) {
|
||||
if (domClass->mInterfaceChain[protoDepth] == protoID) {
|
||||
value = UnwrapDOMObject<T>(obj);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -244,6 +249,14 @@ UnwrapObject(JSObject* obj, U& value)
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
}
|
||||
|
||||
template <prototypes::ID PrototypeID, class T, typename U>
|
||||
MOZ_ALWAYS_INLINE nsresult
|
||||
UnwrapObject(JSObject* obj, U& value)
|
||||
{
|
||||
return UnwrapObject<T>(obj, value, PrototypeID,
|
||||
PrototypeTraits<PrototypeID>::Depth);
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsNotDateOrRegExp(JSContext* cx, JS::Handle<JSObject*> obj)
|
||||
{
|
||||
@ -2455,6 +2468,15 @@ class InternedStringId
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
GenericBindingGetter(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
GenericBindingSetter(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
GenericBindingMethod(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -1633,8 +1633,10 @@ class MethodDefiner(PropertyDefiner):
|
||||
jitinfo = ("reinterpret_cast<const JSJitInfo*>(&%s_methodinfo)" % accessor)
|
||||
if m.get("allowCrossOriginThis", False):
|
||||
accessor = "genericCrossOriginMethod"
|
||||
else:
|
||||
elif self.descriptor.needsSpecialGenericOps():
|
||||
accessor = "genericMethod"
|
||||
else:
|
||||
accessor = "GenericBindingMethod"
|
||||
else:
|
||||
jitinfo = "nullptr"
|
||||
|
||||
@ -1691,8 +1693,10 @@ class AttrDefiner(PropertyDefiner):
|
||||
accessor = "genericLenientGetter"
|
||||
elif attr.getExtendedAttribute("CrossOriginReadable"):
|
||||
accessor = "genericCrossOriginGetter"
|
||||
else:
|
||||
elif self.descriptor.needsSpecialGenericOps():
|
||||
accessor = "genericGetter"
|
||||
else:
|
||||
accessor = "GenericBindingGetter"
|
||||
jitinfo = "&%s_getterinfo" % attr.identifier.name
|
||||
return "{ { JS_CAST_NATIVE_TO(%s, JSPropertyOp), %s } }" % \
|
||||
(accessor, jitinfo)
|
||||
@ -1710,8 +1714,10 @@ class AttrDefiner(PropertyDefiner):
|
||||
accessor = "genericLenientSetter"
|
||||
elif attr.getExtendedAttribute("CrossOriginWritable"):
|
||||
accessor = "genericCrossOriginSetter"
|
||||
else:
|
||||
elif self.descriptor.needsSpecialGenericOps():
|
||||
accessor = "genericSetter"
|
||||
else:
|
||||
accessor = "GenericBindingSetter"
|
||||
jitinfo = "&%s_setterinfo" % attr.identifier.name
|
||||
return "{ { JS_CAST_NATIVE_TO(%s, JSStrictPropertyOp), %s } }" % \
|
||||
(accessor, jitinfo)
|
||||
@ -8739,7 +8745,7 @@ class CGDescriptor(CGThing):
|
||||
continue
|
||||
if (m.isMethod() and m == descriptor.operations['Jsonifier']):
|
||||
hasJsonifier = True
|
||||
hasMethod = True
|
||||
hasMethod = descriptor.needsSpecialGenericOps()
|
||||
jsonifierMethod = m
|
||||
elif (m.isMethod() and
|
||||
(not m.isIdentifierLess() or m == descriptor.operations['Stringifier'])):
|
||||
@ -8751,7 +8757,7 @@ class CGDescriptor(CGThing):
|
||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||
if m.getExtendedAttribute("CrossOriginCallable"):
|
||||
crossOriginMethods.add(m.identifier.name)
|
||||
else:
|
||||
elif descriptor.needsSpecialGenericOps():
|
||||
hasMethod = True
|
||||
elif m.isAttr():
|
||||
if m.stringifier:
|
||||
@ -8767,7 +8773,7 @@ class CGDescriptor(CGThing):
|
||||
hasLenientGetter = True
|
||||
elif m.getExtendedAttribute("CrossOriginReadable"):
|
||||
crossOriginGetters.add(m.identifier.name)
|
||||
else:
|
||||
elif descriptor.needsSpecialGenericOps():
|
||||
hasGetter = True
|
||||
if not m.readonly:
|
||||
for extAttr in ["PutForwards", "Replaceable"]:
|
||||
@ -8785,17 +8791,18 @@ class CGDescriptor(CGThing):
|
||||
hasLenientSetter = True
|
||||
elif m.getExtendedAttribute("CrossOriginWritable"):
|
||||
crossOriginSetters.add(m.identifier.name)
|
||||
else:
|
||||
elif descriptor.needsSpecialGenericOps():
|
||||
hasSetter = True
|
||||
elif m.getExtendedAttribute("PutForwards"):
|
||||
cgThings.append(CGSpecializedForwardingSetter(descriptor, m))
|
||||
if m.getExtendedAttribute("CrossOriginWritable"):
|
||||
crossOriginSetters.add(m.identifier.name)
|
||||
else:
|
||||
elif descriptor.needsSpecialGenericOps():
|
||||
hasSetter = True
|
||||
elif m.getExtendedAttribute("Replaceable"):
|
||||
cgThings.append(CGSpecializedReplaceableSetter(descriptor, m))
|
||||
hasSetter = True
|
||||
if descriptor.needsSpecialGenericOps():
|
||||
hasSetter = True
|
||||
if (not m.isStatic() and
|
||||
descriptor.interface.hasInterfacePrototypeObject()):
|
||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||
|
@ -507,6 +507,16 @@ class Descriptor(DescriptorProvider):
|
||||
"HTMLEmbedElement",
|
||||
"HTMLAppletElement"])
|
||||
|
||||
def needsSpecialGenericOps(self):
|
||||
"""
|
||||
Returns true if this descriptor requires generic ops other than
|
||||
GenericBindingMethod/GenericBindingGetter/GenericBindingSetter.
|
||||
|
||||
In practice we need to do this if our this value might be an XPConnect
|
||||
object or if we need to coerce null/undefined to the global.
|
||||
"""
|
||||
return self.hasXPConnectImpls or self.interface.isOnGlobalProtoChain()
|
||||
|
||||
# Some utility methods
|
||||
def getTypesFromDescriptor(descriptor):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user