mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 1658946 - Wrap non-wrappercached interfaces more precisely in ToJSValue, r=peterv
This will allow resolving DOM promises with non-wrappercached XPIDL interfaces in a more convenient manner, as the wrapped JS object will have more concrete interface information without needing to invoke QueryInterface. Differential Revision: https://phabricator.services.mozilla.com/D87002
This commit is contained in:
parent
e5976b05e4
commit
b2d811fc35
@ -94,5 +94,27 @@ bool ToJSValue(JSContext* aCx, const WindowProxyHolder& aArgument,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Static assertion tests for the `binding_detail::ScriptableInterfaceType`
|
||||
// helper template, used by `ToJSValue`.
|
||||
namespace binding_detail {
|
||||
static_assert(std::is_same_v<ScriptableInterfaceType<nsISupports>, nsISupports>,
|
||||
"nsISupports works with ScriptableInterfaceType");
|
||||
static_assert(
|
||||
std::is_same_v<ScriptableInterfaceType<nsIGlobalObject>, nsISupports>,
|
||||
"non-scriptable interfaces get a fallback");
|
||||
static_assert(std::is_same_v<ScriptableInterfaceType<nsIObserver>, nsIObserver>,
|
||||
"scriptable interfaces should get the correct type");
|
||||
static_assert(std::is_same_v<ScriptableInterfaceType<nsIRunnable>, nsIRunnable>,
|
||||
"scriptable interfaces should get the correct type");
|
||||
class SingleScriptableInterface : public nsIObserver {};
|
||||
static_assert(
|
||||
std::is_same_v<ScriptableInterfaceType<SingleScriptableInterface>,
|
||||
nsIObserver>,
|
||||
"Concrete type with one scriptable interface picks the correct interface");
|
||||
class MultiScriptableInterface : public nsIObserver, public nsIRunnable {};
|
||||
static_assert(std::is_same_v<ScriptableInterfaceType<MultiScriptableInterface>,
|
||||
nsISupports>,
|
||||
"Concrete type with multiple scriptable interfaces falls back");
|
||||
} // namespace binding_detail
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -191,6 +191,32 @@ MOZ_MUST_USE
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace binding_detail {
|
||||
// Helper type alias for picking a script-exposable non-wrappercached XPIDL
|
||||
// interface to expose to JS code. Falls back to `nsISupports` if the specific
|
||||
// interface type is ambiguous.
|
||||
template <typename T, typename = void>
|
||||
struct GetScriptableInterfaceType {
|
||||
using Type = nsISupports;
|
||||
|
||||
static_assert(std::is_base_of_v<nsISupports, T>,
|
||||
"T must inherit from nsISupports");
|
||||
};
|
||||
template <typename T>
|
||||
struct GetScriptableInterfaceType<
|
||||
T, std::void_t<typename T::ScriptableInterfaceType>> {
|
||||
using Type = typename T::ScriptableInterfaceType;
|
||||
|
||||
static_assert(std::is_base_of_v<Type, T>,
|
||||
"T must inherit from ScriptableInterfaceType");
|
||||
static_assert(std::is_base_of_v<nsISupports, Type>,
|
||||
"ScriptableInterfaceType must inherit from nsISupports");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using ScriptableInterfaceType = typename GetScriptableInterfaceType<T>::Type;
|
||||
} // namespace binding_detail
|
||||
|
||||
// Accept objects that inherit from nsISupports but not nsWrapperCache (e.g.
|
||||
// DOM File).
|
||||
template <class T>
|
||||
@ -204,7 +230,9 @@ ToJSValue(JSContext* aCx, T& aArgument, JS::MutableHandle<JS::Value> aValue) {
|
||||
|
||||
xpcObjectHelper helper(ToSupports(&aArgument));
|
||||
JS::Rooted<JSObject*> scope(aCx, JS::CurrentGlobalOrNull(aCx));
|
||||
return XPCOMObjectToJsval(aCx, scope, helper, nullptr, true, aValue);
|
||||
const nsIID& iid =
|
||||
NS_GET_TEMPLATE_IID(binding_detail::ScriptableInterfaceType<T>);
|
||||
return XPCOMObjectToJsval(aCx, scope, helper, &iid, true, aValue);
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool ToJSValue(JSContext* aCx, const WindowProxyHolder& aArgument,
|
||||
|
@ -348,6 +348,12 @@ iface_prolog = """ {
|
||||
|
||||
"""
|
||||
|
||||
iface_scriptable = """\
|
||||
/* Used by ToJSValue to check which scriptable interface is implemented. */
|
||||
using ScriptableInterfaceType = %(name)s;
|
||||
|
||||
"""
|
||||
|
||||
iface_epilog = """};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(%(name)s, %(defname)s_IID)
|
||||
@ -505,6 +511,9 @@ def write_interface(iface, fd):
|
||||
fd.write(" : public %s" % iface.base)
|
||||
fd.write(iface_prolog % names)
|
||||
|
||||
if iface.attributes.scriptable:
|
||||
fd.write(iface_scriptable % names)
|
||||
|
||||
for key, group in itertools.groupby(iface.members, key=type):
|
||||
if key == xpidl.ConstMember:
|
||||
write_const_decls(group) # iterator of all the consts
|
||||
|
Loading…
Reference in New Issue
Block a user