mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-10 01:40:50 +09:00
Issue #1322 - Part 3: Remove DOM promise interface gunk
Based on work by Boris Zbarsky
This commit is contained in:
parent
48adbfd454
commit
15672c6231
13 changed files with 287 additions and 314 deletions
|
|
@ -694,10 +694,6 @@ DOMInterfaces = {
|
|||
'headerFile': 'nsGeolocation.h'
|
||||
},
|
||||
|
||||
'Promise': {
|
||||
'implicitJSContext': [ 'then', 'catch' ],
|
||||
},
|
||||
|
||||
'PromiseDebugging': {
|
||||
'concrete': False,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1135,6 +1135,12 @@ class CGHeaders(CGWrapper):
|
|||
declareIncludes.add("mozilla/dom/Date.h")
|
||||
else:
|
||||
bindingHeaders.add("mozilla/dom/Date.h")
|
||||
elif unrolled.isPromise():
|
||||
# See comment in the isInterface() case for why we add
|
||||
# Promise.h to headerSet, not bindingHeaders.
|
||||
headerSet.add("mozilla/dom/Promise.h")
|
||||
# We need ToJSValue to do the Promise to JS conversion.
|
||||
bindingHeaders.add("mozilla/dom/ToJSValue.h")
|
||||
elif unrolled.isInterface():
|
||||
if unrolled.isSpiderMonkeyInterface():
|
||||
bindingHeaders.add("jsfriendapi.h")
|
||||
|
|
@ -1352,7 +1358,11 @@ def UnionTypes(unionTypes, config):
|
|||
headers.add("mozilla/dom/Nullable.h")
|
||||
isSequence = f.isSequence()
|
||||
f = f.unroll()
|
||||
if f.isInterface():
|
||||
if f.isPromise():
|
||||
headers.add("mozilla/dom/Promise.h")
|
||||
# We need ToJSValue to do the Promise to JS conversion.
|
||||
headers.add("mozilla/dom/ToJSValue.h")
|
||||
elif f.isInterface():
|
||||
if f.isSpiderMonkeyInterface():
|
||||
headers.add("jsfriendapi.h")
|
||||
headers.add("mozilla/dom/TypedArray.h")
|
||||
|
|
@ -1434,7 +1444,11 @@ def UnionConversions(unionTypes, config):
|
|||
|
||||
def addHeadersForType(f):
|
||||
f = f.unroll()
|
||||
if f.isInterface():
|
||||
if f.isPromise():
|
||||
headers.add("mozilla/dom/Promise.h")
|
||||
# We need ToJSValue to do the Promise to JS conversion.
|
||||
headers.add("mozilla/dom/ToJSValue.h")
|
||||
elif f.isInterface():
|
||||
if f.isSpiderMonkeyInterface():
|
||||
headers.add("jsfriendapi.h")
|
||||
headers.add("mozilla/dom/TypedArray.h")
|
||||
|
|
@ -5227,6 +5241,139 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
holderArgs=holderArgs,
|
||||
dealWithOptional=isOptional and (not nullable or isOwningUnion))
|
||||
|
||||
if type.isPromise():
|
||||
assert not type.nullable()
|
||||
assert defaultValue is None
|
||||
|
||||
# We always have to hold a strong ref to Promise here, because
|
||||
# Promise::resolve returns an addrefed thing.
|
||||
argIsPointer = isCallbackReturnValue
|
||||
if argIsPointer:
|
||||
declType = CGGeneric("RefPtr<Promise>")
|
||||
else:
|
||||
declType = CGGeneric("OwningNonNull<Promise>")
|
||||
|
||||
# Per spec, what we're supposed to do is take the original
|
||||
# Promise.resolve and call it with the original Promise as this
|
||||
# value to make a Promise out of whatever value we actually have
|
||||
# here. The question is which global we should use. There are
|
||||
# several cases to consider:
|
||||
#
|
||||
# 1) Normal call to API with a Promise argument. This is a case the
|
||||
# spec covers, and we should be using the current Realm's
|
||||
# Promise. That means the current compartment.
|
||||
# 2) Call to API with a Promise argument over Xrays. In practice,
|
||||
# this sort of thing seems to be used for giving an API
|
||||
# implementation a way to wait for conclusion of an asyc
|
||||
# operation, _not_ to expose the Promise to content code. So we
|
||||
# probably want to allow callers to use such an API in a
|
||||
# "natural" way, by passing chrome-side promises; indeed, that
|
||||
# may be all that the caller has to represent their async
|
||||
# operation. That means we really need to do the
|
||||
# Promise.resolve() in the caller (chrome) compartment: if we do
|
||||
# it in the content compartment, we will try to call .then() on
|
||||
# the chrome promise while in the content compartment, which will
|
||||
# throw and we'll just get a rejected Promise. Note that this is
|
||||
# also the reason why a caller who has a chrome Promise
|
||||
# representing an async operation can't itself convert it to a
|
||||
# content-side Promise (at least not without some serious
|
||||
# gyrations).
|
||||
# 3) Promise return value from a callback or callback interface.
|
||||
# Per spec, this should use the Realm of the callback object. In
|
||||
# our case, that's the compartment of the underlying callback,
|
||||
# not the current compartment (which may be the compartment of
|
||||
# some cross-compartment wrapper around said callback).
|
||||
# 4) Return value from a JS-implemented interface. In this case we
|
||||
# have a problem. Our current compartment is the compartment of
|
||||
# the JS implementation. But if the JS implementation returned
|
||||
# a page-side Promise (which is a totally sane thing to do, and
|
||||
# in fact the right thing to do given that this return value is
|
||||
# going right to content script) then we don't want to
|
||||
# Promise.resolve with our current compartment Promise, because
|
||||
# that will wrap it up in a chrome-side Promise, which is
|
||||
# decidedly _not_ what's desired here. So in that case we
|
||||
# should really unwrap the return value and use the global of
|
||||
# the result. CheckedUnwrap should be good enough for that; if
|
||||
# it fails, then we're failing unwrap while in a
|
||||
# system-privileged compartment, so presumably we have a dead
|
||||
# object wrapper. Just error out. Do NOT fall back to using
|
||||
# the current compartment instead: that will return a
|
||||
# system-privileged rejected (because getting .then inside
|
||||
# resolve() failed) Promise to the caller, which they won't be
|
||||
# able to touch. That's not helpful. If we error out, on the
|
||||
# other hand, they will get a content-side rejected promise.
|
||||
# Same thing if the value returned is not even an object.
|
||||
if isCallbackReturnValue == "JSImpl":
|
||||
# Case 4 above. Note that globalObj defaults to the current
|
||||
# compartment global. Note that we don't use $*{exceptionCode}
|
||||
# here because that will try to aRv.Throw(NS_ERROR_UNEXPECTED)
|
||||
# which we don't really want here.
|
||||
assert exceptionCode == "aRv.Throw(NS_ERROR_UNEXPECTED);\nreturn nullptr;\n"
|
||||
getPromiseGlobal = fill(
|
||||
"""
|
||||
if (!$${val}.isObject()) {
|
||||
aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("${sourceDescription}"));
|
||||
return nullptr;
|
||||
}
|
||||
JSObject* unwrappedVal = js::CheckedUnwrap(&$${val}.toObject());
|
||||
if (!unwrappedVal) {
|
||||
// A slight lie, but not much of one, for a dead object wrapper.
|
||||
aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("${sourceDescription}"));
|
||||
return nullptr;
|
||||
}
|
||||
globalObj = js::GetGlobalForObjectCrossCompartment(unwrappedVal);
|
||||
""",
|
||||
sourceDescription=sourceDescription)
|
||||
elif isCallbackReturnValue == "Callback":
|
||||
getPromiseGlobal = dedent(
|
||||
"""
|
||||
// We basically want our entry global here. Play it safe
|
||||
// and use GetEntryGlobal() to get it, with whatever
|
||||
// principal-clamping it ends up doing.
|
||||
globalObj = GetEntryGlobal()->GetGlobalJSObject();
|
||||
""")
|
||||
else:
|
||||
getPromiseGlobal = ""
|
||||
|
||||
templateBody = fill(
|
||||
"""
|
||||
{ // Scope for our GlobalObject, FastErrorResult, JSAutoCompartment,
|
||||
// etc.
|
||||
|
||||
JS::Rooted<JSObject*> globalObj(cx, JS::CurrentGlobalOrNull(cx));
|
||||
$*{getPromiseGlobal}
|
||||
JSAutoCompartment ac(cx, globalObj);
|
||||
GlobalObject promiseGlobal(cx, globalObj);
|
||||
if (promiseGlobal.Failed()) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> valueToResolve(cx, $${val});
|
||||
if (!JS_WrapValue(cx, &valueToResolve)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
binding_detail::FastErrorResult promiseRv;
|
||||
nsCOMPtr<nsIGlobalObject> global =
|
||||
do_QueryInterface(promiseGlobal.GetAsSupports());
|
||||
if (!global) {
|
||||
promiseRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
promiseRv.MaybeSetPendingException(cx);
|
||||
$*{exceptionCode}
|
||||
}
|
||||
$${declName} = Promise::Resolve(global, cx, valueToResolve,
|
||||
promiseRv);
|
||||
if (promiseRv.MaybeSetPendingException(cx)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
}
|
||||
""",
|
||||
getPromiseGlobal=getPromiseGlobal,
|
||||
exceptionCode=exceptionCode)
|
||||
|
||||
return JSToNativeConversionInfo(templateBody,
|
||||
declType=declType,
|
||||
dealWithOptional=isOptional)
|
||||
|
||||
if type.isGeckoInterface():
|
||||
assert not isEnforceRange and not isClamp
|
||||
|
||||
|
|
@ -5265,12 +5412,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
# Also, callback return values always end up addrefing anyway, so there
|
||||
# is no point trying to avoid it here and it makes other things simpler
|
||||
# since we can assume the return value is a strong ref.
|
||||
#
|
||||
# Finally, promises need to hold a strong ref because that's what
|
||||
# Promise.resolve returns.
|
||||
assert not descriptor.interface.isCallback()
|
||||
isPromise = descriptor.interface.identifier.name == "Promise"
|
||||
forceOwningType = isMember or isCallbackReturnValue or isPromise
|
||||
forceOwningType = isMember or isCallbackReturnValue
|
||||
|
||||
typeName = descriptor.nativeType
|
||||
typePtr = typeName + "*"
|
||||
|
|
@ -5298,122 +5441,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
if forceOwningType:
|
||||
templateBody += 'static_assert(IsRefcounted<%s>::value, "We can only store refcounted classes.");' % typeName
|
||||
|
||||
if isPromise:
|
||||
# Per spec, what we're supposed to do is take the original
|
||||
# Promise.resolve and call it with the original Promise as this
|
||||
# value to make a Promise out of whatever value we actually have
|
||||
# here. The question is which global we should use. There are
|
||||
# several cases to consider:
|
||||
#
|
||||
# 1) Normal call to API with a Promise argument. This is a case the
|
||||
# spec covers, and we should be using the current Realm's
|
||||
# Promise. That means the current compartment.
|
||||
# 2) Call to API with a Promise argument over Xrays. In practice,
|
||||
# this sort of thing seems to be used for giving an API
|
||||
# implementation a way to wait for conclusion of an asyc
|
||||
# operation, _not_ to expose the Promise to content code. So we
|
||||
# probably want to allow callers to use such an API in a
|
||||
# "natural" way, by passing chrome-side promises; indeed, that
|
||||
# may be all that the caller has to represent their async
|
||||
# operation. That means we really need to do the
|
||||
# Promise.resolve() in the caller (chrome) compartment: if we do
|
||||
# it in the content compartment, we will try to call .then() on
|
||||
# the chrome promise while in the content compartment, which will
|
||||
# throw and we'll just get a rejected Promise. Note that this is
|
||||
# also the reason why a caller who has a chrome Promise
|
||||
# representing an async operation can't itself convert it to a
|
||||
# content-side Promise (at least not without some serious
|
||||
# gyrations).
|
||||
# 3) Promise return value from a callback or callback interface.
|
||||
# This is in theory a case the spec covers but in practice it
|
||||
# really doesn't define behavior here because it doesn't define
|
||||
# what Realm we're in after the callback returns, which is when
|
||||
# the argument conversion happens. We will use the current
|
||||
# compartment, which is the compartment of the callable (which
|
||||
# may itself be a cross-compartment wrapper itself), which makes
|
||||
# as much sense as anything else. In practice, such an API would
|
||||
# once again be providing a Promise to signal completion of an
|
||||
# operation, which would then not be exposed to anyone other than
|
||||
# our own implementation code.
|
||||
# 4) Return value from a JS-implemented interface. In this case we
|
||||
# have a problem. Our current compartment is the compartment of
|
||||
# the JS implementation. But if the JS implementation returned
|
||||
# a page-side Promise (which is a totally sane thing to do, and
|
||||
# in fact the right thing to do given that this return value is
|
||||
# going right to content script) then we don't want to
|
||||
# Promise.resolve with our current compartment Promise, because
|
||||
# that will wrap it up in a chrome-side Promise, which is
|
||||
# decidedly _not_ what's desired here. So in that case we
|
||||
# should really unwrap the return value and use the global of
|
||||
# the result. CheckedUnwrap should be good enough for that; if
|
||||
# it fails, then we're failing unwrap while in a
|
||||
# system-privileged compartment, so presumably we have a dead
|
||||
# object wrapper. Just error out. Do NOT fall back to using
|
||||
# the current compartment instead: that will return a
|
||||
# system-privileged rejected (because getting .then inside
|
||||
# resolve() failed) Promise to the caller, which they won't be
|
||||
# able to touch. That's not helpful. If we error out, on the
|
||||
# other hand, they will get a content-side rejected promise.
|
||||
# Same thing if the value returned is not even an object.
|
||||
if isCallbackReturnValue == "JSImpl":
|
||||
# Case 4 above. Note that globalObj defaults to the current
|
||||
# compartment global. Note that we don't use $*{exceptionCode}
|
||||
# here because that will try to aRv.Throw(NS_ERROR_UNEXPECTED)
|
||||
# which we don't really want here.
|
||||
assert exceptionCode == "aRv.Throw(NS_ERROR_UNEXPECTED);\nreturn nullptr;\n"
|
||||
getPromiseGlobal = fill(
|
||||
"""
|
||||
if (!$${val}.isObject()) {
|
||||
aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("${sourceDescription}"));
|
||||
return nullptr;
|
||||
}
|
||||
JSObject* unwrappedVal = js::CheckedUnwrap(&$${val}.toObject());
|
||||
if (!unwrappedVal) {
|
||||
// A slight lie, but not much of one, for a dead object wrapper.
|
||||
aRv.ThrowTypeError<MSG_NOT_OBJECT>(NS_LITERAL_STRING("${sourceDescription}"));
|
||||
return nullptr;
|
||||
}
|
||||
globalObj = js::GetGlobalForObjectCrossCompartment(unwrappedVal);
|
||||
""",
|
||||
sourceDescription=sourceDescription)
|
||||
else:
|
||||
getPromiseGlobal = ""
|
||||
|
||||
templateBody = fill(
|
||||
"""
|
||||
{ // Scope for our GlobalObject, FastErrorResult, JSAutoCompartment,
|
||||
// etc.
|
||||
|
||||
JS::Rooted<JSObject*> globalObj(cx, JS::CurrentGlobalOrNull(cx));
|
||||
$*{getPromiseGlobal}
|
||||
JSAutoCompartment ac(cx, globalObj);
|
||||
GlobalObject promiseGlobal(cx, globalObj);
|
||||
if (promiseGlobal.Failed()) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> valueToResolve(cx, $${val});
|
||||
if (!JS_WrapValue(cx, &valueToResolve)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
binding_detail::FastErrorResult promiseRv;
|
||||
nsCOMPtr<nsIGlobalObject> global =
|
||||
do_QueryInterface(promiseGlobal.GetAsSupports());
|
||||
if (!global) {
|
||||
promiseRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
promiseRv.MaybeSetPendingException(cx);
|
||||
$*{exceptionCode}
|
||||
}
|
||||
$${declName} = Promise::Resolve(global, cx, valueToResolve,
|
||||
promiseRv);
|
||||
if (promiseRv.MaybeSetPendingException(cx)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
}
|
||||
""",
|
||||
getPromiseGlobal=getPromiseGlobal,
|
||||
exceptionCode=exceptionCode)
|
||||
elif not descriptor.interface.isConsequential() and not descriptor.interface.isExternal():
|
||||
if (not descriptor.interface.isConsequential() and
|
||||
not descriptor.interface.isExternal()):
|
||||
if failureCode is not None:
|
||||
templateBody += str(CastableObjectUnwrapper(
|
||||
descriptor,
|
||||
|
|
@ -5453,24 +5482,12 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
# And store our value in ${declName}
|
||||
templateBody += "${declName} = ${holderName};\n"
|
||||
|
||||
if isPromise:
|
||||
if type.nullable():
|
||||
codeToSetNull = "${declName} = nullptr;\n"
|
||||
templateBody = CGIfElseWrapper(
|
||||
"${val}.isNullOrUndefined()",
|
||||
CGGeneric(codeToSetNull),
|
||||
CGGeneric(templateBody)).define()
|
||||
if isinstance(defaultValue, IDLNullValue):
|
||||
templateBody = handleDefault(templateBody, codeToSetNull)
|
||||
else:
|
||||
assert defaultValue is None
|
||||
else:
|
||||
# Just pass failureCode, not onFailureBadType, here, so we'll report
|
||||
# the thing as not an object as opposed to not implementing whatever
|
||||
# our interface is.
|
||||
templateBody = wrapObjectTemplate(templateBody, type,
|
||||
"${declName} = nullptr;\n",
|
||||
failureCode)
|
||||
# Just pass failureCode, not onFailureBadType, here, so we'll report
|
||||
# the thing as not an object as opposed to not implementing whatever
|
||||
# our interface is.
|
||||
templateBody = wrapObjectTemplate(templateBody, type,
|
||||
"${declName} = nullptr;\n",
|
||||
failureCode)
|
||||
|
||||
declType = CGGeneric(declType)
|
||||
if holderType is not None:
|
||||
|
|
@ -6537,6 +6554,19 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
|||
|
||||
return (code, False)
|
||||
|
||||
if type.isPromise():
|
||||
assert not type.nullable()
|
||||
# The use of ToJSValue here is a bit annoying because the Promise
|
||||
# version is not inlined, but we can't put an inline version in either
|
||||
# ToJSValue.h or BindingUtils.h, because Promise.h includes ToJSValue.h
|
||||
# and that includes BindingUtils.h, so we'd get an include loop if
|
||||
# either of those headers included Promise.h. Trying to write the
|
||||
# conversion by hand here is annoying because we'd have to handle
|
||||
# the various RefPtr, rawptr, NonNull, etc. cases, which ToJSValue will
|
||||
# already handle for us, so we just use the function call.
|
||||
return (wrapAndSetPtr("ToJSValue(cx, %s, ${jsvalHandle})" % result),
|
||||
False)
|
||||
|
||||
if type.isGeckoInterface() and not type.isCallbackInterface():
|
||||
descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
|
||||
if type.nullable():
|
||||
|
|
@ -6551,14 +6581,6 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
|||
wrapMethod = "GetOrCreateDOMReflector"
|
||||
wrapArgs = "cx, %s, ${jsvalHandle}" % result
|
||||
else:
|
||||
# Hack: the "Promise" interface is OK to return from
|
||||
# non-newobject things even when it's not wrappercached; that
|
||||
# happens when using SpiderMonkey promises, and the WrapObject()
|
||||
# method will just return the existing reflector, which is just
|
||||
# not stored in a wrappercache.
|
||||
if (not returnsNewObject and
|
||||
descriptor.interface.identifier.name != "Promise"):
|
||||
raise MethodNotNewObjectError(descriptor.interface.identifier.name)
|
||||
wrapMethod = "WrapNewBindingNonWrapperCachedObject"
|
||||
wrapArgs = "cx, ${obj}, %s, ${jsvalHandle}" % result
|
||||
if isConstructorRetval:
|
||||
|
|
@ -6874,14 +6896,17 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
|
|||
if returnType.nullable():
|
||||
result = CGTemplatedType("Nullable", result)
|
||||
return result, None, None, None, None
|
||||
if returnType.isGeckoInterface():
|
||||
result = CGGeneric(descriptorProvider.getDescriptor(
|
||||
returnType.unroll().inner.identifier.name).nativeType)
|
||||
conversion = None
|
||||
if isMember:
|
||||
result = CGGeneric("StrongPtrForMember<%s>::Type" % result.define())
|
||||
if returnType.isGeckoInterface() or returnType.isPromise():
|
||||
if returnType.isGeckoInterface():
|
||||
typeName = descriptorProvider.getDescriptor(
|
||||
returnType.unroll().inner.identifier.name).nativeType
|
||||
else:
|
||||
conversion = CGGeneric("StrongOrRawPtr<%s>" % result.define())
|
||||
typeName = "Promise"
|
||||
if isMember:
|
||||
conversion = None
|
||||
result = CGGeneric("StrongPtrForMember<%s>::Type" % typeName)
|
||||
else:
|
||||
conversion = CGGeneric("StrongOrRawPtr<%s>" % typeName)
|
||||
result = CGGeneric("auto")
|
||||
return result, None, None, None, conversion
|
||||
if returnType.isCallback():
|
||||
|
|
@ -7046,7 +7071,9 @@ class CGCallGenerator(CGThing):
|
|||
if needsConst(a):
|
||||
arg = CGWrapper(arg, pre="Constify(", post=")")
|
||||
# And convert NonNull<T> to T&
|
||||
if (((a.type.isGeckoInterface() or a.type.isCallback()) and not a.type.nullable()) or
|
||||
if (((a.type.isGeckoInterface() or a.type.isCallback() or
|
||||
a.type.isPromise()) and
|
||||
not a.type.nullable()) or
|
||||
a.type.isDOMString()):
|
||||
arg = CGWrapper(arg, pre="NonNullHelper(", post=")")
|
||||
args.append(arg)
|
||||
|
|
@ -7170,6 +7197,9 @@ class CGCallGenerator(CGThing):
|
|||
|
||||
|
||||
def getUnionMemberName(type):
|
||||
# Promises can't be in unions, because they're not distinguishable
|
||||
# from anything else.
|
||||
assert not type.isPromise()
|
||||
if type.isGeckoInterface():
|
||||
return type.inner.identifier.name
|
||||
if type.isEnum():
|
||||
|
|
@ -7299,8 +7329,9 @@ def wrapTypeIntoCurrentCompartment(type, value, isMember=True):
|
|||
return CGList(memberWraps, "else ") if len(memberWraps) != 0 else None
|
||||
|
||||
if (type.isString() or type.isPrimitive() or type.isEnum() or
|
||||
type.isGeckoInterface() or type.isCallback() or type.isDate()):
|
||||
# All of these don't need wrapping
|
||||
type.isGeckoInterface() or type.isCallback() or type.isDate() or
|
||||
type.isPromise()):
|
||||
# All of these don't need wrapping.
|
||||
return None
|
||||
|
||||
raise TypeError("Unknown type; we don't know how to wrap it in constructor "
|
||||
|
|
@ -7438,58 +7469,12 @@ class CGPerSignatureCall(CGThing):
|
|||
if needsCx:
|
||||
argsPre.append("cx")
|
||||
|
||||
# Hack for making Promise.prototype.then work well over Xrays.
|
||||
if (not idlNode.isStatic() and
|
||||
descriptor.name == "Promise" and
|
||||
idlNode.isMethod() and
|
||||
idlNode.identifier.name == "then"):
|
||||
cgThings.append(CGGeneric(dedent(
|
||||
"""
|
||||
JS::Rooted<JSObject*> calleeGlobal(cx, xpc::XrayAwareCalleeGlobal(&args.callee()));
|
||||
""")))
|
||||
argsPre.append("calleeGlobal")
|
||||
|
||||
needsUnwrap = False
|
||||
argsPost = []
|
||||
if isConstructor:
|
||||
if descriptor.name == "Promise":
|
||||
# Hack for Promise for now: pass in our desired proto so the
|
||||
# implementation can create the reflector with the right proto.
|
||||
argsPost.append("desiredProto")
|
||||
# Also, we do not want to enter the content compartment when the
|
||||
# Promise constructor is called via Xrays, because we want to
|
||||
# create our callback functions that we will hand to our caller
|
||||
# in the Xray compartment. The reason we want to do that is the
|
||||
# following situation, over Xrays:
|
||||
#
|
||||
# contentWindow.Promise.race([Promise.resolve(5)])
|
||||
#
|
||||
# Ideally this would work. Internally, race() does a
|
||||
# contentWindow.Promise.resolve() on everything in the array.
|
||||
# Per spec, to support subclassing,
|
||||
# contentWindow.Promise.resolve has to do:
|
||||
#
|
||||
# var resolve, reject;
|
||||
# var p = new contentWindow.Promise(function(a, b) {
|
||||
# resolve = a;
|
||||
# reject = b;
|
||||
# });
|
||||
# resolve(arg);
|
||||
# return p;
|
||||
#
|
||||
# where "arg" is, in this case, the chrome-side return value of
|
||||
# Promise.resolve(5). But if the "resolve" function in that
|
||||
# case were created in the content compartment, then calling it
|
||||
# would wrap "arg" in an opaque wrapper, and that function tries
|
||||
# to get .then off the argument, which would throw. So we need
|
||||
# to create the "resolve" function in the chrome compartment,
|
||||
# and hence want to be running the entire Promise constructor
|
||||
# (which creates that function) in the chrome compartment in
|
||||
# this case. So don't set needsUnwrap here.
|
||||
else:
|
||||
needsUnwrap = True
|
||||
needsUnwrappedVar = False
|
||||
unwrappedVar = "obj"
|
||||
needsUnwrap = True
|
||||
needsUnwrappedVar = False
|
||||
unwrappedVar = "obj"
|
||||
elif descriptor.interface.isJSImplemented():
|
||||
if not idlNode.isStatic():
|
||||
needsUnwrap = True
|
||||
|
|
@ -7502,11 +7487,6 @@ class CGPerSignatureCall(CGThing):
|
|||
needsUnwrappedVar = True
|
||||
argsPre.append("unwrappedObj ? *unwrappedObj : obj")
|
||||
|
||||
if idlNode.isStatic() and not isConstructor and descriptor.name == "Promise":
|
||||
# Hack for Promise for now: pass in the "this" value to
|
||||
# Promise static methods.
|
||||
argsPre.append("args.thisv()")
|
||||
|
||||
if needsUnwrap and needsUnwrappedVar:
|
||||
# We cannot assign into obj because it's a Handle, not a
|
||||
# MutableHandle, so we need a separate Rooted.
|
||||
|
|
@ -7649,7 +7629,8 @@ class CGPerSignatureCall(CGThing):
|
|||
|
||||
returnsNewObject = memberReturnsNewObject(self.idlNode)
|
||||
if (returnsNewObject and
|
||||
self.returnType.isGeckoInterface()):
|
||||
(self.returnType.isGeckoInterface() or
|
||||
self.returnType.isPromise())):
|
||||
wrapCode += dedent(
|
||||
"""
|
||||
static_assert(!IsPointer<decltype(result)>::value,
|
||||
|
|
@ -9455,6 +9436,8 @@ class CGMemberJITInfo(CGThing):
|
|||
return "JSVAL_TYPE_OBJECT"
|
||||
if t.isRecord():
|
||||
return "JSVAL_TYPE_OBJECT"
|
||||
if t.isPromise():
|
||||
return "JSVAL_TYPE_OBJECT"
|
||||
if t.isGeckoInterface():
|
||||
return "JSVAL_TYPE_OBJECT"
|
||||
if t.isString():
|
||||
|
|
@ -9528,6 +9511,8 @@ class CGMemberJITInfo(CGThing):
|
|||
return "JSJitInfo::ArgType(JSJitInfo::Null | %s)" % CGMemberJITInfo.getJSArgType(t.inner)
|
||||
if t.isSequence():
|
||||
return "JSJitInfo::Object"
|
||||
if t.isPromise():
|
||||
return "JSJitInfo::Object"
|
||||
if t.isGeckoInterface():
|
||||
return "JSJitInfo::Object"
|
||||
if t.isString():
|
||||
|
|
@ -9714,6 +9699,10 @@ def getUnionAccessorSignatureType(type, descriptorProvider):
|
|||
# Flat member types have already unwrapped nullables.
|
||||
assert not type.nullable()
|
||||
|
||||
# Promise types can never appear in unions, because Promise is not
|
||||
# distinguishable from anything.
|
||||
assert not type.isPromise()
|
||||
|
||||
if type.isSequence() or type.isRecord():
|
||||
if type.isSequence():
|
||||
wrapperType = "Sequence"
|
||||
|
|
@ -13622,6 +13611,8 @@ class ForwardDeclarationBuilder:
|
|||
|
||||
# Note: Spidermonkey interfaces are typedefs, so can't be
|
||||
# forward-declared
|
||||
elif t.isPromise():
|
||||
self.addInMozillaDom("Promise")
|
||||
elif t.isCallback():
|
||||
self.addInMozillaDom(t.callback.identifier.name)
|
||||
elif t.isDictionary():
|
||||
|
|
@ -14076,10 +14067,13 @@ class CGNativeMember(ClassMethod):
|
|||
else:
|
||||
defaultValue = "%s(0)" % enumName
|
||||
return enumName, defaultValue, "return ${declName};\n"
|
||||
if type.isGeckoInterface():
|
||||
iface = type.unroll().inner
|
||||
result = CGGeneric(self.descriptorProvider.getDescriptor(
|
||||
iface.identifier.name).prettyNativeType)
|
||||
if type.isGeckoInterface() or type.isPromise():
|
||||
if type.isGeckoInterface():
|
||||
iface = type.unroll().inner
|
||||
result = CGGeneric(self.descriptorProvider.getDescriptor(
|
||||
iface.identifier.name).prettyNativeType)
|
||||
else:
|
||||
result = CGGeneric("Promise")
|
||||
if self.resultAlreadyAddRefed:
|
||||
if isMember:
|
||||
holder = "RefPtr"
|
||||
|
|
@ -14282,11 +14276,18 @@ class CGNativeMember(ClassMethod):
|
|||
# auto-wrapping in Nullable
|
||||
return CGUnionStruct.unionTypeDecl(type, isMember), True, False
|
||||
|
||||
if type.isPromise():
|
||||
assert not type.nullable()
|
||||
if optional or isMember:
|
||||
typeDecl = "OwningNonNull<Promise>"
|
||||
else:
|
||||
typeDecl = "Promise&"
|
||||
return (typeDecl, False, False)
|
||||
|
||||
if type.isGeckoInterface() and not type.isCallbackInterface():
|
||||
iface = type.unroll().inner
|
||||
argIsPointer = type.nullable() or iface.isExternal()
|
||||
forceOwningType = (iface.isCallback() or isMember or
|
||||
iface.identifier.name == "Promise")
|
||||
forceOwningType = (iface.isCallback() or isMember)
|
||||
if argIsPointer:
|
||||
if (optional or isMember) and forceOwningType:
|
||||
typeDecl = "RefPtr<%s>"
|
||||
|
|
@ -16920,7 +16921,10 @@ class CGEventGetter(CGNativeMember):
|
|||
def getMethodBody(self):
|
||||
type = self.member.type
|
||||
memberName = CGDictionary.makeMemberName(self.member.identifier.name)
|
||||
if (type.isPrimitive() and type.tag() in builtinNames) or type.isEnum() or type.isGeckoInterface():
|
||||
if ((type.isPrimitive() and type.tag() in builtinNames) or
|
||||
type.isEnum() or
|
||||
type.isPromise() or
|
||||
type.isGeckoInterface()):
|
||||
return "return " + memberName + ";\n"
|
||||
if type.isDOMString() or type.isByteString() or type.isUSVString():
|
||||
return "aRetVal = " + memberName + ";\n"
|
||||
|
|
@ -17331,6 +17335,8 @@ class CGEventClass(CGBindingImplClass):
|
|||
nativeType = CGGeneric("nsString")
|
||||
elif type.isByteString():
|
||||
nativeType = CGGeneric("nsCString")
|
||||
elif type.isPromise():
|
||||
nativeType = CGGeneric("RefPtr<Promise>")
|
||||
elif type.isGeckoInterface():
|
||||
iface = type.unroll().inner
|
||||
nativeType = self.descriptor.getDescriptor(
|
||||
|
|
@ -17355,7 +17361,7 @@ class CGEventClass(CGBindingImplClass):
|
|||
innerType = type.inner
|
||||
if (not innerType.isPrimitive() and not innerType.isEnum() and
|
||||
not innerType.isDOMString() and not innerType.isByteString() and
|
||||
not innerType.isGeckoInterface()):
|
||||
not innerType.isPromise() and not innerType.isGeckoInterface()):
|
||||
raise TypeError("Don't know how to properly manage GC/CC for "
|
||||
"event member of type %s" %
|
||||
type)
|
||||
|
|
|
|||
|
|
@ -468,13 +468,6 @@ class Descriptor(DescriptorProvider):
|
|||
self.wrapperCache = (not self.interface.isCallback() and
|
||||
not self.interface.isIteratorInterface() and
|
||||
desc.get('wrapperCache', True))
|
||||
# Nasty temporary hack for supporting both DOM and SpiderMonkey promises
|
||||
# without too much pain
|
||||
if self.interface.identifier.name == "Promise":
|
||||
assert self.wrapperCache
|
||||
# But really, we're only wrappercached if we have an interface
|
||||
# object (that is, when we're not using SpiderMonkey promises).
|
||||
self.wrapperCache = self.interface.hasInterfaceObject()
|
||||
|
||||
self.name = interface.identifier.name
|
||||
|
||||
|
|
|
|||
|
|
@ -84,11 +84,6 @@ MSG_DEF(MSG_NOTIFICATION_PERMISSION_DENIED, 0, JSEXN_TYPEERR, "Permission to sho
|
|||
MSG_DEF(MSG_NOTIFICATION_NO_CONSTRUCTOR_IN_SERVICEWORKER, 0, JSEXN_TYPEERR, "Notification constructor cannot be used in ServiceWorkerGlobalScope. Use registration.showNotification() instead.")
|
||||
MSG_DEF(MSG_INVALID_SCOPE, 2, JSEXN_TYPEERR, "Invalid scope trying to resolve {0} with base URL {1}.")
|
||||
MSG_DEF(MSG_INVALID_KEYFRAME_OFFSETS, 0, JSEXN_TYPEERR, "Keyframes with specified offsets must be in order and all be in the range [0, 1].")
|
||||
MSG_DEF(MSG_ILLEGAL_PROMISE_CONSTRUCTOR, 0, JSEXN_TYPEERR, "Non-constructor value passed to NewPromiseCapability.")
|
||||
MSG_DEF(MSG_PROMISE_CAPABILITY_HAS_SOMETHING_ALREADY, 0, JSEXN_TYPEERR, "GetCapabilitiesExecutor function already invoked with non-undefined values.")
|
||||
MSG_DEF(MSG_PROMISE_RESOLVE_FUNCTION_NOT_CALLABLE, 0, JSEXN_TYPEERR, "A Promise subclass passed a non-callable value as the resolve function.")
|
||||
MSG_DEF(MSG_PROMISE_REJECT_FUNCTION_NOT_CALLABLE, 0, JSEXN_TYPEERR, "A Promise subclass passed a non-callable value as the reject function.")
|
||||
MSG_DEF(MSG_PROMISE_ARG_NOT_ITERABLE, 1, JSEXN_TYPEERR, "{0} is not iterable")
|
||||
MSG_DEF(MSG_IS_NOT_PROMISE, 1, JSEXN_TYPEERR, "{0} is not a Promise")
|
||||
MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} encountered an error during installation.")
|
||||
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ ToJSValue(JSContext* aCx, Promise& aArgument,
|
|||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
aValue.setObject(*aArgument.PromiseObj());
|
||||
return true;
|
||||
return MaybeWrapObjectValue(aCx, aValue);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ typedef TypedArray<uint8_t, js::UnwrapSharedArrayBuffer, JS_GetSharedArrayBuffer
|
|||
// A class for converting an nsTArray to a TypedArray
|
||||
// Note: A TypedArrayCreator must not outlive the nsTArray it was created from.
|
||||
// So this is best used to pass from things that understand nsTArray to
|
||||
// things that understand TypedArray, as with Promise::ArgumentToJSValue.
|
||||
// things that understand TypedArray, as with ToJSValue.
|
||||
template<typename TypedArrayType>
|
||||
class TypedArrayCreator
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1597,11 +1597,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
|||
|
||||
args = attr.args() if attr.hasArgs() else []
|
||||
|
||||
if self.identifier.name == "Promise":
|
||||
promiseType = BuiltinTypes[IDLBuiltinType.Types.any]
|
||||
else:
|
||||
promiseType = None
|
||||
retType = IDLWrapperType(self.location, self, promiseType)
|
||||
retType = IDLWrapperType(self.location, self)
|
||||
|
||||
if identifier == "Constructor" or identifier == "ChromeConstructor":
|
||||
name = "constructor"
|
||||
|
|
@ -1988,7 +1984,8 @@ class IDLType(IDLObject):
|
|||
'callback',
|
||||
'union',
|
||||
'sequence',
|
||||
'record'
|
||||
'record',
|
||||
'promise'
|
||||
)
|
||||
|
||||
def __init__(self, location, name):
|
||||
|
|
@ -2142,9 +2139,8 @@ class IDLUnresolvedType(IDLType):
|
|||
Unresolved types are interface types
|
||||
"""
|
||||
|
||||
def __init__(self, location, name, promiseInnerType=None):
|
||||
def __init__(self, location, name):
|
||||
IDLType.__init__(self, location, name)
|
||||
self._promiseInnerType = promiseInnerType
|
||||
|
||||
def isComplete(self):
|
||||
return False
|
||||
|
|
@ -2171,11 +2167,8 @@ class IDLUnresolvedType(IDLType):
|
|||
assert self.name.name == obj.identifier.name
|
||||
return IDLCallbackType(self.location, obj)
|
||||
|
||||
if self._promiseInnerType and not self._promiseInnerType.isComplete():
|
||||
self._promiseInnerType = self._promiseInnerType.complete(scope)
|
||||
|
||||
name = self.name.resolve(scope, None)
|
||||
return IDLWrapperType(self.location, obj, self._promiseInnerType)
|
||||
return IDLWrapperType(self.location, obj)
|
||||
|
||||
def isDistinguishableFrom(self, other):
|
||||
raise TypeError("Can't tell whether an unresolved type is or is not "
|
||||
|
|
@ -2285,7 +2278,9 @@ class IDLNullableType(IDLParameterizedType):
|
|||
return self.inner.isInterface()
|
||||
|
||||
def isPromise(self):
|
||||
return self.inner.isPromise()
|
||||
# There is no such thing as a nullable Promise.
|
||||
assert not self.inner.isPromise()
|
||||
return False
|
||||
|
||||
def isCallbackInterface(self):
|
||||
return self.inner.isCallbackInterface()
|
||||
|
|
@ -2698,13 +2693,11 @@ class IDLTypedef(IDLObjectWithIdentifier):
|
|||
|
||||
|
||||
class IDLWrapperType(IDLType):
|
||||
def __init__(self, location, inner, promiseInnerType=None):
|
||||
def __init__(self, location, inner):
|
||||
IDLType.__init__(self, location, inner.identifier.name)
|
||||
self.inner = inner
|
||||
self._identifier = inner.identifier
|
||||
self.builtin = False
|
||||
assert not promiseInnerType or inner.identifier.name == "Promise"
|
||||
self._promiseInnerType = promiseInnerType
|
||||
|
||||
def __eq__(self, other):
|
||||
return (isinstance(other, IDLWrapperType) and
|
||||
|
|
@ -2754,14 +2747,6 @@ class IDLWrapperType(IDLType):
|
|||
def isEnum(self):
|
||||
return isinstance(self.inner, IDLEnum)
|
||||
|
||||
def isPromise(self):
|
||||
return (isinstance(self.inner, IDLInterface) and
|
||||
self.inner.identifier.name == "Promise")
|
||||
|
||||
def promiseInnerType(self):
|
||||
assert self.isPromise()
|
||||
return self._promiseInnerType
|
||||
|
||||
def isSerializable(self):
|
||||
if self.isInterface():
|
||||
if self.inner.isExternal():
|
||||
|
|
@ -2793,8 +2778,6 @@ class IDLWrapperType(IDLType):
|
|||
assert False
|
||||
|
||||
def isDistinguishableFrom(self, other):
|
||||
if self.isPromise():
|
||||
return False
|
||||
if other.isPromise():
|
||||
return False
|
||||
if other.isUnion():
|
||||
|
|
@ -2841,10 +2824,6 @@ class IDLWrapperType(IDLType):
|
|||
# Let's say true, though ideally we'd only do this when
|
||||
# exposureSet contains the primary global's name.
|
||||
return True
|
||||
if (self.isPromise() and
|
||||
# Check the internal type
|
||||
not self.promiseInnerType().unroll().isExposedInAllOf(exposureSet)):
|
||||
return False
|
||||
return iface.exposureSet.issuperset(exposureSet)
|
||||
|
||||
def _getDependentObjects(self):
|
||||
|
|
@ -2871,6 +2850,45 @@ class IDLWrapperType(IDLType):
|
|||
return set([self.inner])
|
||||
return set()
|
||||
|
||||
|
||||
class IDLPromiseType(IDLParametrizedType):
|
||||
def __init__(self, location, innerType):
|
||||
IDLParametrizedType.__init__(self, location, "Promise", innerType)
|
||||
|
||||
def __eq__(self, other):
|
||||
return (isinstance(other, IDLPromiseType) and
|
||||
self.promiseInnerType() == other.promiseInnerType())
|
||||
|
||||
def __str__(self):
|
||||
return self.inner.__str__() + "Promise"
|
||||
|
||||
def isPromise(self):
|
||||
return True
|
||||
|
||||
def promiseInnerType(self):
|
||||
return self.inner
|
||||
|
||||
def tag(self):
|
||||
return IDLType.Tags.promise
|
||||
|
||||
def complete(self, scope):
|
||||
self.inner = self.promiseInnerType().complete(scope)
|
||||
return self
|
||||
|
||||
def unroll(self):
|
||||
# We do not unroll our inner. Just stop at ourselves. That
|
||||
# lets us add headers for both ourselves and our inner as
|
||||
# needed.
|
||||
return self
|
||||
|
||||
def isDistinguishableFrom(self, other):
|
||||
# Promises are not distinguishable from anything.
|
||||
return False
|
||||
|
||||
def isExposedInAllOf(self, exposureSet):
|
||||
# Check the internal type
|
||||
return self.promiseInnerType().unroll().isExposedInAllOf(exposureSet)
|
||||
|
||||
|
||||
class IDLBuiltinType(IDLType):
|
||||
|
||||
|
|
@ -3990,7 +4008,9 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
raise WebIDLError("An attribute with [PutForwards] must have an "
|
||||
"interface type as its type", [self.location])
|
||||
|
||||
if not self.type.isInterface() and self.getExtendedAttribute("SameObject"):
|
||||
if (not self.type.isInterface() and
|
||||
not self.type.isPromise() and
|
||||
self.getExtendedAttribute("SameObject")):
|
||||
raise WebIDLError("An attribute with [SameObject] must have an "
|
||||
"interface type as its type", [self.location])
|
||||
|
||||
|
|
@ -6394,17 +6414,13 @@ class Parser(Tokenizer):
|
|||
type = IDLSequenceType(self.getLocation(p, 1), innerType)
|
||||
p[0] = self.handleNullable(type, p[5])
|
||||
|
||||
# Note: Promise<void> is allowed, so we want to parametrize on
|
||||
# ReturnType, not Type. Also, we want this to end up picking up
|
||||
# the Promise interface for now, hence the games with IDLUnresolvedType.
|
||||
# Note: Promise<void> is allowed, so we want to parameterize on
|
||||
# ReturnType, not Type. Promise types can't be null, hence no "Null" in there.
|
||||
def p_NonAnyTypePromiseType(self, p):
|
||||
"""
|
||||
NonAnyType : PROMISE LT ReturnType GT Null
|
||||
NonAnyType : PROMISE LT ReturnType GT
|
||||
"""
|
||||
innerType = p[3]
|
||||
promiseIdent = IDLUnresolvedIdentifier(self.getLocation(p, 1), "Promise")
|
||||
type = IDLUnresolvedType(self.getLocation(p, 1), promiseIdent, p[3])
|
||||
p[0] = self.handleNullable(type, p[5])
|
||||
p[0] = IDLPromiseType(self.getLocation(p, 1), p[3])
|
||||
|
||||
def p_NonAnyTypeRecordType(self, p):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -263,7 +263,6 @@ def WebIDLTest(parser, harness):
|
|||
callback Callback2 = long(short arg);
|
||||
dictionary Dict {};
|
||||
dictionary Dict2 {};
|
||||
interface _Promise {};
|
||||
interface TestInterface {%s
|
||||
};
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ def WebIDLTest(parser, harness):
|
|||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface _Promise {};
|
||||
interface A {
|
||||
legacycaller Promise<any> foo();
|
||||
};
|
||||
|
|
@ -18,7 +17,6 @@ def WebIDLTest(parser, harness):
|
|||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface _Promise {};
|
||||
interface A {
|
||||
Promise<any> foo();
|
||||
long foo(long arg);
|
||||
|
|
@ -35,7 +33,6 @@ def WebIDLTest(parser, harness):
|
|||
threw = False
|
||||
try:
|
||||
parser.parse("""
|
||||
interface _Promise {};
|
||||
interface A {
|
||||
long foo(long arg);
|
||||
Promise<any> foo();
|
||||
|
|
@ -50,7 +47,6 @@ def WebIDLTest(parser, harness):
|
|||
|
||||
parser = parser.reset()
|
||||
parser.parse("""
|
||||
interface _Promise {};
|
||||
interface A {
|
||||
Promise<any> foo();
|
||||
Promise<any> foo(long arg);
|
||||
|
|
|
|||
|
|
@ -87,17 +87,6 @@ Promise::~Promise()
|
|||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
bool
|
||||
Promise::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aWrapper)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
binding_detail::AssertReflectorHasGivenProto(aCx, mPromiseObj, aGivenProto);
|
||||
#endif // DEBUG
|
||||
aWrapper.set(mPromiseObj);
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<Promise>
|
||||
Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv)
|
||||
|
|
|
|||
|
|
@ -120,10 +120,6 @@ public:
|
|||
return mGlobal;
|
||||
}
|
||||
|
||||
bool
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aWrapper);
|
||||
|
||||
// Do the equivalent of Promise.resolve in the compartment of aGlobal. The
|
||||
// compartment of aCx is ignored. Errors are reported on the ErrorResult; if
|
||||
// aRv comes back !Failed(), this function MUST return a non-null value.
|
||||
|
|
|
|||
|
|
@ -3,28 +3,15 @@
|
|||
* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dom.spec.whatwg.org/#promises
|
||||
* This IDL file contains utilities to help connect JS promises to our
|
||||
* Web IDL infrastructure.
|
||||
*/
|
||||
|
||||
// TODO We use object instead Function. There is an open issue on WebIDL to
|
||||
// have different types for "platform-provided function" and "user-provided
|
||||
// function"; for now, we just use "object".
|
||||
callback PromiseInit = void (object resolve, object reject);
|
||||
|
||||
callback PromiseJobCallback = void();
|
||||
|
||||
[TreatNonCallableAsNull]
|
||||
callback AnyCallback = any (any value);
|
||||
|
||||
// Promises are implemented in SpiderMonkey; just define a tiny interface to make
|
||||
// codegen of Promise arguments and return values work.
|
||||
[NoInterfaceObject,
|
||||
Exposed=(Window,Worker,WorkerDebugger,System)]
|
||||
// Need to escape "Promise" so it's treated as an identifier.
|
||||
interface _Promise {
|
||||
};
|
||||
|
||||
// Hack to allow us to have JS owning and properly tracing/CCing/etc a
|
||||
// PromiseNativeHandler.
|
||||
[NoInterfaceObject,
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ interface TestInterfaceJS : EventTarget {
|
|||
|
||||
// Tests for promise-rejection behavior
|
||||
Promise<void> testPromiseWithThrowingChromePromiseInit();
|
||||
Promise<void> testPromiseWithThrowingContentPromiseInit(PromiseInit func);
|
||||
Promise<void> testPromiseWithThrowingContentPromiseInit(Function func);
|
||||
Promise<void> testPromiseWithDOMExceptionThrowingPromiseInit();
|
||||
Promise<void> testPromiseWithThrowingChromeThenFunction();
|
||||
Promise<void> testPromiseWithThrowingContentThenFunction(AnyCallback func);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue