Bug 1618011 part 5. Use a BindingCallContext for Web IDL callback guts. r=peterv

We basically need this because some of the type conversions those guts need to
do may need a BindingCallContext.

We could probably do more optimization here to only generate the
BindingCallContext bits if we will really need them, more or less based on our
return type.  But for now that doesn't seem worthwhile.

Differential Revision: https://phabricator.services.mozilla.com/D64886

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Boris Zbarsky 2020-03-06 23:05:16 +00:00
Родитель e322a9eb2f
Коммит 8a18c1c3ae
5 изменённых файлов: 27 добавлений и 12 удалений

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

@ -14,7 +14,7 @@ namespace mozilla {
namespace dom {
bool CallbackInterface::GetCallableProperty(
JSContext* cx, JS::Handle<jsid> aPropId,
BindingCallContext& cx, JS::Handle<jsid> aPropId,
JS::MutableHandle<JS::Value> aCallable) {
if (!JS_GetPropertyById(cx, CallbackKnownNotGray(), aPropId, aCallable)) {
return false;

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

@ -37,7 +37,7 @@ class CallbackInterface : public CallbackObject {
aIncumbentGlobal) {}
protected:
bool GetCallableProperty(JSContext* cx, JS::Handle<jsid> aPropId,
bool GetCallableProperty(BindingCallContext& cx, JS::Handle<jsid> aPropId,
JS::MutableHandle<JS::Value> aCallable);
// See CallbackObject for an explanation of the arguments.

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

@ -311,6 +311,10 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
// And now we're ready to go.
mCx = cx;
// We don't really have a good error message prefix to use for the
// BindingCallContext.
mCallContext.emplace(cx, nullptr);
}
bool CallbackObject::CallSetup::ShouldRethrowException(

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

@ -27,6 +27,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/OwningNonNull.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/BindingCallContext.h"
#include "nsWrapperCache.h"
#include "nsJSEnvironment.h"
#include "xpcpublic.h"
@ -349,6 +350,10 @@ class CallbackObject : public nsISupports {
JSContext* GetContext() const { return mCx; }
// Safe to call this after the constructor has run without throwing on the
// ErrorResult it was handed.
BindingCallContext& GetCallContext() { return *mCallContext; }
private:
// We better not get copy-constructed
CallSetup(const CallSetup&) = delete;
@ -380,6 +385,10 @@ class CallbackObject : public nsISupports {
// order those two things.
Maybe<JSAutoRealm> mAr;
// Our BindingCallContext. This is a Maybe so we can avoid constructing it
// until after we have a JSContext to construct it with.
Maybe<BindingCallContext> mCallContext;
// An ErrorResult to possibly re-throw exceptions on and whether
// we should re-throw them.
ErrorResult& mErrorResult;

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

@ -17023,9 +17023,9 @@ class CGCallback(CGClass):
def getMethodImpls(self, method):
assert method.needThisHandling
args = list(method.args)
# Strip out the JSContext*/JSObject* args
# Strip out the BindingCallContext&/JSObject* args
# that got added.
assert args[0].name == "cx" and args[0].argType == "JSContext*"
assert args[0].name == "cx" and args[0].argType == "BindingCallContext&"
assert args[1].name == "aThisVal" and args[1].argType == "JS::Handle<JS::Value>"
args = args[2:]
@ -17038,8 +17038,8 @@ class CGCallback(CGClass):
# Record the names of all the arguments, so we can use them when we call
# the private method.
argnames = [arg.name for arg in args]
argnamesWithThis = ["s.GetContext()", "thisValJS"] + argnames
argnamesWithoutThis = ["s.GetContext()", "JS::UndefinedHandleValue"] + argnames
argnamesWithThis = ["s.GetCallContext()", "thisValJS"] + argnames
argnamesWithoutThis = ["s.GetCallContext()", "JS::UndefinedHandleValue"] + argnames
# Now that we've recorded the argnames for our call to our private
# method, insert our optional argument for the execution reason.
args.append(Argument("const char*", "aExecutionReason",
@ -17357,7 +17357,8 @@ class CallbackMember(CGNativeMember):
"""
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(${argCount})) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
// That threw an exception on the JSContext, and our CallSetup will do
// the right thing with that.
return${errorReturn};
}
""",
@ -17509,8 +17510,8 @@ class CallbackMember(CGNativeMember):
args.append(Argument("JS::Realm*", "aRealm", "nullptr"))
return args
# We want to allow the caller to pass in a "this" value, as
# well as a JSContext.
return [Argument("JSContext*", "cx"),
# well as a BindingCallContext.
return [Argument("BindingCallContext&", "cx"),
Argument("JS::Handle<JS::Value>", "aThisVal")] + args
def getCallSetup(self):
@ -17529,11 +17530,12 @@ class CallbackMember(CGNativeMember):
return fill(
"""
$*{callSetup}
JSContext* cx = s.GetContext();
if (!cx) {
MOZ_ASSERT(aRv.Failed());
if (aRv.Failed()) {
return${errorReturn};
}
MOZ_ASSERT(s.GetContext());
BindingCallContext& cx = s.GetCallContext();
""",
callSetup=callSetup,
errorReturn=self.getDefaultRetval())