Remove DOM promise implementation.
This commit is contained in:
parent
4134276c53
commit
11183f4c98
|
@ -136,14 +136,6 @@ release_or_beta
|
||||||
|
|
||||||
Always defined.
|
Always defined.
|
||||||
|
|
||||||
sm_promise
|
|
||||||
Whether spidermonkey promises have been enabled or not. This is set
|
|
||||||
by adding --enable-sm-promise to the mozconfig file.
|
|
||||||
|
|
||||||
Values are ``true`` and ``false``.
|
|
||||||
|
|
||||||
Always defined.
|
|
||||||
|
|
||||||
tests_enabled
|
tests_enabled
|
||||||
Whether tests are enabled for this build.
|
Whether tests are enabled for this build.
|
||||||
|
|
||||||
|
|
|
@ -2976,42 +2976,6 @@ ConvertExceptionToPromise(JSContext* cx,
|
||||||
JSObject* promiseScope,
|
JSObject* promiseScope,
|
||||||
JS::MutableHandle<JS::Value> rval)
|
JS::MutableHandle<JS::Value> rval)
|
||||||
{
|
{
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
GlobalObject global(cx, promiseScope);
|
|
||||||
if (global.Failed()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::Rooted<JS::Value> exn(cx);
|
|
||||||
if (!JS_GetPendingException(cx, &exn)) {
|
|
||||||
// This is very important: if there is no pending exception here but we're
|
|
||||||
// ending up in this code, that means the callee threw an uncatchable
|
|
||||||
// exception. Just propagate that out as-is.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_ClearPendingException(cx);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIGlobalObject> globalObj =
|
|
||||||
do_QueryInterface(global.GetAsSupports());
|
|
||||||
if (!globalObj) {
|
|
||||||
ErrorResult rv;
|
|
||||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
|
||||||
return !rv.MaybeSetPendingException(cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorResult rv;
|
|
||||||
RefPtr<Promise> promise = Promise::Reject(globalObj, cx, exn, rv);
|
|
||||||
if (rv.MaybeSetPendingException(cx)) {
|
|
||||||
// We just give up. We put the exception from the ErrorResult on
|
|
||||||
// the JSContext just to make sure to not leak memory on the
|
|
||||||
// ErrorResult, but now just put the original exception back.
|
|
||||||
JS_SetPendingException(cx, exn);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetOrCreateDOMReflector(cx, promise, rval);
|
|
||||||
#else // SPIDERMONKEY_PROMISE
|
|
||||||
{
|
{
|
||||||
JSAutoCompartment ac(cx, promiseScope);
|
JSAutoCompartment ac(cx, promiseScope);
|
||||||
|
|
||||||
|
@ -3037,7 +3001,6 @@ ConvertExceptionToPromise(JSContext* cx,
|
||||||
|
|
||||||
// Now make sure we rewrap promise back into the compartment we want
|
// Now make sure we rewrap promise back into the compartment we want
|
||||||
return JS_WrapValue(cx, rval);
|
return JS_WrapValue(cx, rval);
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
|
|
|
@ -694,10 +694,6 @@ DOMInterfaces = {
|
||||||
'headerFile': 'nsGeolocation.h'
|
'headerFile': 'nsGeolocation.h'
|
||||||
},
|
},
|
||||||
|
|
||||||
'Promise': {
|
|
||||||
'implicitJSContext': [ 'then', 'catch' ],
|
|
||||||
},
|
|
||||||
|
|
||||||
'PromiseDebugging': {
|
'PromiseDebugging': {
|
||||||
'concrete': False,
|
'concrete': False,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1135,6 +1135,12 @@ class CGHeaders(CGWrapper):
|
||||||
declareIncludes.add("mozilla/dom/Date.h")
|
declareIncludes.add("mozilla/dom/Date.h")
|
||||||
else:
|
else:
|
||||||
bindingHeaders.add("mozilla/dom/Date.h")
|
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():
|
elif unrolled.isInterface():
|
||||||
if unrolled.isSpiderMonkeyInterface():
|
if unrolled.isSpiderMonkeyInterface():
|
||||||
bindingHeaders.add("jsfriendapi.h")
|
bindingHeaders.add("jsfriendapi.h")
|
||||||
|
@ -1352,7 +1358,11 @@ def UnionTypes(unionTypes, config):
|
||||||
headers.add("mozilla/dom/Nullable.h")
|
headers.add("mozilla/dom/Nullable.h")
|
||||||
isSequence = f.isSequence()
|
isSequence = f.isSequence()
|
||||||
f = f.unroll()
|
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():
|
if f.isSpiderMonkeyInterface():
|
||||||
headers.add("jsfriendapi.h")
|
headers.add("jsfriendapi.h")
|
||||||
headers.add("mozilla/dom/TypedArray.h")
|
headers.add("mozilla/dom/TypedArray.h")
|
||||||
|
@ -1434,7 +1444,11 @@ def UnionConversions(unionTypes, config):
|
||||||
|
|
||||||
def addHeadersForType(f):
|
def addHeadersForType(f):
|
||||||
f = f.unroll()
|
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():
|
if f.isSpiderMonkeyInterface():
|
||||||
headers.add("jsfriendapi.h")
|
headers.add("jsfriendapi.h")
|
||||||
headers.add("mozilla/dom/TypedArray.h")
|
headers.add("mozilla/dom/TypedArray.h")
|
||||||
|
@ -3052,23 +3066,6 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||||
else:
|
else:
|
||||||
unforgeableHolderSetup = None
|
unforgeableHolderSetup = None
|
||||||
|
|
||||||
if self.descriptor.name == "Promise":
|
|
||||||
speciesSetup = CGGeneric(fill(
|
|
||||||
"""
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
JS::Rooted<JSObject*> promiseConstructor(aCx, *interfaceCache);
|
|
||||||
JS::Rooted<jsid> species(aCx,
|
|
||||||
SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::species)));
|
|
||||||
if (!JS_DefinePropertyById(aCx, promiseConstructor, species, JS::UndefinedHandleValue,
|
|
||||||
JSPROP_SHARED, Promise::PromiseSpecies, nullptr)) {
|
|
||||||
$*{failureCode}
|
|
||||||
}
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
""",
|
|
||||||
failureCode=failureCode))
|
|
||||||
else:
|
|
||||||
speciesSetup = None
|
|
||||||
|
|
||||||
if (self.descriptor.interface.isOnGlobalProtoChain() and
|
if (self.descriptor.interface.isOnGlobalProtoChain() and
|
||||||
needInterfacePrototypeObject):
|
needInterfacePrototypeObject):
|
||||||
makeProtoPrototypeImmutable = CGGeneric(fill(
|
makeProtoPrototypeImmutable = CGGeneric(fill(
|
||||||
|
@ -3094,7 +3091,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
||||||
return CGList(
|
return CGList(
|
||||||
[getParentProto, getConstructorProto, initIds,
|
[getParentProto, getConstructorProto, initIds,
|
||||||
prefCache, CGGeneric(call), defineAliases, unforgeableHolderSetup,
|
prefCache, CGGeneric(call), defineAliases, unforgeableHolderSetup,
|
||||||
speciesSetup, makeProtoPrototypeImmutable],
|
makeProtoPrototypeImmutable],
|
||||||
"\n").define()
|
"\n").define()
|
||||||
|
|
||||||
|
|
||||||
|
@ -5244,6 +5241,139 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||||
holderArgs=holderArgs,
|
holderArgs=holderArgs,
|
||||||
dealWithOptional=isOptional and (not nullable or isOwningUnion))
|
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():
|
if type.isGeckoInterface():
|
||||||
assert not isEnforceRange and not isClamp
|
assert not isEnforceRange and not isClamp
|
||||||
|
|
||||||
|
@ -5282,12 +5412,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||||
# Also, callback return values always end up addrefing anyway, so there
|
# 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
|
# 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.
|
# 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()
|
assert not descriptor.interface.isCallback()
|
||||||
isPromise = descriptor.interface.identifier.name == "Promise"
|
forceOwningType = isMember or isCallbackReturnValue
|
||||||
forceOwningType = isMember or isCallbackReturnValue or isPromise
|
|
||||||
|
|
||||||
typeName = descriptor.nativeType
|
typeName = descriptor.nativeType
|
||||||
typePtr = typeName + "*"
|
typePtr = typeName + "*"
|
||||||
|
@ -5315,143 +5441,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||||
if forceOwningType:
|
if forceOwningType:
|
||||||
templateBody += 'static_assert(IsRefcounted<%s>::value, "We can only store refcounted classes.");' % typeName
|
templateBody += 'static_assert(IsRefcounted<%s>::value, "We can only store refcounted classes.");' % typeName
|
||||||
|
|
||||||
if isPromise:
|
if (not descriptor.interface.isConsequential() and
|
||||||
# Per spec, what we're supposed to do is take the original
|
not descriptor.interface.isExternal()):
|
||||||
# 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;
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
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}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
JS::Handle<JSObject*> promiseCtor =
|
|
||||||
PromiseBinding::GetConstructorObjectHandle(cx);
|
|
||||||
if (!promiseCtor) {
|
|
||||||
$*{exceptionCode}
|
|
||||||
}
|
|
||||||
JS::Rooted<JS::Value> resolveThisv(cx, JS::ObjectValue(*promiseCtor));
|
|
||||||
JS::Rooted<JS::Value> resolveResult(cx);
|
|
||||||
Promise::Resolve(promiseGlobal, resolveThisv, valueToResolve,
|
|
||||||
&resolveResult, promiseRv);
|
|
||||||
if (promiseRv.MaybeSetPendingException(cx)) {
|
|
||||||
$*{exceptionCode}
|
|
||||||
}
|
|
||||||
nsresult unwrapRv = UNWRAP_OBJECT(Promise, &resolveResult.toObject(), $${declName});
|
|
||||||
if (NS_FAILED(unwrapRv)) { // Quite odd
|
|
||||||
promiseRv.Throw(unwrapRv);
|
|
||||||
promiseRv.MaybeSetPendingException(cx);
|
|
||||||
$*{exceptionCode}
|
|
||||||
}
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
}
|
|
||||||
""",
|
|
||||||
getPromiseGlobal=getPromiseGlobal,
|
|
||||||
exceptionCode=exceptionCode)
|
|
||||||
elif not descriptor.interface.isConsequential() and not descriptor.interface.isExternal():
|
|
||||||
if failureCode is not None:
|
if failureCode is not None:
|
||||||
templateBody += str(CastableObjectUnwrapper(
|
templateBody += str(CastableObjectUnwrapper(
|
||||||
descriptor,
|
descriptor,
|
||||||
|
@ -5491,24 +5482,12 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||||
# And store our value in ${declName}
|
# And store our value in ${declName}
|
||||||
templateBody += "${declName} = ${holderName};\n"
|
templateBody += "${declName} = ${holderName};\n"
|
||||||
|
|
||||||
if isPromise:
|
# Just pass failureCode, not onFailureBadType, here, so we'll report
|
||||||
if type.nullable():
|
# the thing as not an object as opposed to not implementing whatever
|
||||||
codeToSetNull = "${declName} = nullptr;\n"
|
# our interface is.
|
||||||
templateBody = CGIfElseWrapper(
|
templateBody = wrapObjectTemplate(templateBody, type,
|
||||||
"${val}.isNullOrUndefined()",
|
"${declName} = nullptr;\n",
|
||||||
CGGeneric(codeToSetNull),
|
failureCode)
|
||||||
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)
|
|
||||||
|
|
||||||
declType = CGGeneric(declType)
|
declType = CGGeneric(declType)
|
||||||
if holderType is not None:
|
if holderType is not None:
|
||||||
|
@ -6575,6 +6554,19 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
||||||
|
|
||||||
return (code, False)
|
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():
|
if type.isGeckoInterface() and not type.isCallbackInterface():
|
||||||
descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
|
descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
|
||||||
if type.nullable():
|
if type.nullable():
|
||||||
|
@ -6589,14 +6581,6 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
|
||||||
wrapMethod = "GetOrCreateDOMReflector"
|
wrapMethod = "GetOrCreateDOMReflector"
|
||||||
wrapArgs = "cx, %s, ${jsvalHandle}" % result
|
wrapArgs = "cx, %s, ${jsvalHandle}" % result
|
||||||
else:
|
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"
|
wrapMethod = "WrapNewBindingNonWrapperCachedObject"
|
||||||
wrapArgs = "cx, ${obj}, %s, ${jsvalHandle}" % result
|
wrapArgs = "cx, ${obj}, %s, ${jsvalHandle}" % result
|
||||||
if isConstructorRetval:
|
if isConstructorRetval:
|
||||||
|
@ -6912,14 +6896,17 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
|
||||||
if returnType.nullable():
|
if returnType.nullable():
|
||||||
result = CGTemplatedType("Nullable", result)
|
result = CGTemplatedType("Nullable", result)
|
||||||
return result, None, None, None, None
|
return result, None, None, None, None
|
||||||
if returnType.isGeckoInterface():
|
if returnType.isGeckoInterface() or returnType.isPromise():
|
||||||
result = CGGeneric(descriptorProvider.getDescriptor(
|
if returnType.isGeckoInterface():
|
||||||
returnType.unroll().inner.identifier.name).nativeType)
|
typeName = descriptorProvider.getDescriptor(
|
||||||
conversion = None
|
returnType.unroll().inner.identifier.name).nativeType
|
||||||
if isMember:
|
|
||||||
result = CGGeneric("StrongPtrForMember<%s>::Type" % result.define())
|
|
||||||
else:
|
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")
|
result = CGGeneric("auto")
|
||||||
return result, None, None, None, conversion
|
return result, None, None, None, conversion
|
||||||
if returnType.isCallback():
|
if returnType.isCallback():
|
||||||
|
@ -7084,7 +7071,9 @@ class CGCallGenerator(CGThing):
|
||||||
if needsConst(a):
|
if needsConst(a):
|
||||||
arg = CGWrapper(arg, pre="Constify(", post=")")
|
arg = CGWrapper(arg, pre="Constify(", post=")")
|
||||||
# And convert NonNull<T> to T&
|
# 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()):
|
a.type.isDOMString()):
|
||||||
arg = CGWrapper(arg, pre="NonNullHelper(", post=")")
|
arg = CGWrapper(arg, pre="NonNullHelper(", post=")")
|
||||||
args.append(arg)
|
args.append(arg)
|
||||||
|
@ -7208,6 +7197,9 @@ class CGCallGenerator(CGThing):
|
||||||
|
|
||||||
|
|
||||||
def getUnionMemberName(type):
|
def getUnionMemberName(type):
|
||||||
|
# Promises can't be in unions, because they're not distinguishable
|
||||||
|
# from anything else.
|
||||||
|
assert not type.isPromise()
|
||||||
if type.isGeckoInterface():
|
if type.isGeckoInterface():
|
||||||
return type.inner.identifier.name
|
return type.inner.identifier.name
|
||||||
if type.isEnum():
|
if type.isEnum():
|
||||||
|
@ -7337,8 +7329,9 @@ def wrapTypeIntoCurrentCompartment(type, value, isMember=True):
|
||||||
return CGList(memberWraps, "else ") if len(memberWraps) != 0 else None
|
return CGList(memberWraps, "else ") if len(memberWraps) != 0 else None
|
||||||
|
|
||||||
if (type.isString() or type.isPrimitive() or type.isEnum() or
|
if (type.isString() or type.isPrimitive() or type.isEnum() or
|
||||||
type.isGeckoInterface() or type.isCallback() or type.isDate()):
|
type.isGeckoInterface() or type.isCallback() or type.isDate() or
|
||||||
# All of these don't need wrapping
|
type.isPromise()):
|
||||||
|
# All of these don't need wrapping.
|
||||||
return None
|
return None
|
||||||
|
|
||||||
raise TypeError("Unknown type; we don't know how to wrap it in constructor "
|
raise TypeError("Unknown type; we don't know how to wrap it in constructor "
|
||||||
|
@ -7476,58 +7469,12 @@ class CGPerSignatureCall(CGThing):
|
||||||
if needsCx:
|
if needsCx:
|
||||||
argsPre.append("cx")
|
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
|
needsUnwrap = False
|
||||||
argsPost = []
|
argsPost = []
|
||||||
if isConstructor:
|
if isConstructor:
|
||||||
if descriptor.name == "Promise":
|
needsUnwrap = True
|
||||||
# Hack for Promise for now: pass in our desired proto so the
|
needsUnwrappedVar = False
|
||||||
# implementation can create the reflector with the right proto.
|
unwrappedVar = "obj"
|
||||||
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"
|
|
||||||
elif descriptor.interface.isJSImplemented():
|
elif descriptor.interface.isJSImplemented():
|
||||||
if not idlNode.isStatic():
|
if not idlNode.isStatic():
|
||||||
needsUnwrap = True
|
needsUnwrap = True
|
||||||
|
@ -7540,11 +7487,6 @@ class CGPerSignatureCall(CGThing):
|
||||||
needsUnwrappedVar = True
|
needsUnwrappedVar = True
|
||||||
argsPre.append("unwrappedObj ? *unwrappedObj : obj")
|
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:
|
if needsUnwrap and needsUnwrappedVar:
|
||||||
# We cannot assign into obj because it's a Handle, not a
|
# We cannot assign into obj because it's a Handle, not a
|
||||||
# MutableHandle, so we need a separate Rooted.
|
# MutableHandle, so we need a separate Rooted.
|
||||||
|
@ -7687,7 +7629,8 @@ class CGPerSignatureCall(CGThing):
|
||||||
|
|
||||||
returnsNewObject = memberReturnsNewObject(self.idlNode)
|
returnsNewObject = memberReturnsNewObject(self.idlNode)
|
||||||
if (returnsNewObject and
|
if (returnsNewObject and
|
||||||
self.returnType.isGeckoInterface()):
|
(self.returnType.isGeckoInterface() or
|
||||||
|
self.returnType.isPromise())):
|
||||||
wrapCode += dedent(
|
wrapCode += dedent(
|
||||||
"""
|
"""
|
||||||
static_assert(!IsPointer<decltype(result)>::value,
|
static_assert(!IsPointer<decltype(result)>::value,
|
||||||
|
@ -9493,6 +9436,8 @@ class CGMemberJITInfo(CGThing):
|
||||||
return "JSVAL_TYPE_OBJECT"
|
return "JSVAL_TYPE_OBJECT"
|
||||||
if t.isRecord():
|
if t.isRecord():
|
||||||
return "JSVAL_TYPE_OBJECT"
|
return "JSVAL_TYPE_OBJECT"
|
||||||
|
if t.isPromise():
|
||||||
|
return "JSVAL_TYPE_OBJECT"
|
||||||
if t.isGeckoInterface():
|
if t.isGeckoInterface():
|
||||||
return "JSVAL_TYPE_OBJECT"
|
return "JSVAL_TYPE_OBJECT"
|
||||||
if t.isString():
|
if t.isString():
|
||||||
|
@ -9566,6 +9511,8 @@ class CGMemberJITInfo(CGThing):
|
||||||
return "JSJitInfo::ArgType(JSJitInfo::Null | %s)" % CGMemberJITInfo.getJSArgType(t.inner)
|
return "JSJitInfo::ArgType(JSJitInfo::Null | %s)" % CGMemberJITInfo.getJSArgType(t.inner)
|
||||||
if t.isSequence():
|
if t.isSequence():
|
||||||
return "JSJitInfo::Object"
|
return "JSJitInfo::Object"
|
||||||
|
if t.isPromise():
|
||||||
|
return "JSJitInfo::Object"
|
||||||
if t.isGeckoInterface():
|
if t.isGeckoInterface():
|
||||||
return "JSJitInfo::Object"
|
return "JSJitInfo::Object"
|
||||||
if t.isString():
|
if t.isString():
|
||||||
|
@ -9752,6 +9699,10 @@ def getUnionAccessorSignatureType(type, descriptorProvider):
|
||||||
# Flat member types have already unwrapped nullables.
|
# Flat member types have already unwrapped nullables.
|
||||||
assert not type.nullable()
|
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() or type.isRecord():
|
||||||
if type.isSequence():
|
if type.isSequence():
|
||||||
wrapperType = "Sequence"
|
wrapperType = "Sequence"
|
||||||
|
@ -13660,6 +13611,8 @@ class ForwardDeclarationBuilder:
|
||||||
|
|
||||||
# Note: Spidermonkey interfaces are typedefs, so can't be
|
# Note: Spidermonkey interfaces are typedefs, so can't be
|
||||||
# forward-declared
|
# forward-declared
|
||||||
|
elif t.isPromise():
|
||||||
|
self.addInMozillaDom("Promise")
|
||||||
elif t.isCallback():
|
elif t.isCallback():
|
||||||
self.addInMozillaDom(t.callback.identifier.name)
|
self.addInMozillaDom(t.callback.identifier.name)
|
||||||
elif t.isDictionary():
|
elif t.isDictionary():
|
||||||
|
@ -14114,10 +14067,13 @@ class CGNativeMember(ClassMethod):
|
||||||
else:
|
else:
|
||||||
defaultValue = "%s(0)" % enumName
|
defaultValue = "%s(0)" % enumName
|
||||||
return enumName, defaultValue, "return ${declName};\n"
|
return enumName, defaultValue, "return ${declName};\n"
|
||||||
if type.isGeckoInterface():
|
if type.isGeckoInterface() or type.isPromise():
|
||||||
iface = type.unroll().inner
|
if type.isGeckoInterface():
|
||||||
result = CGGeneric(self.descriptorProvider.getDescriptor(
|
iface = type.unroll().inner
|
||||||
iface.identifier.name).prettyNativeType)
|
result = CGGeneric(self.descriptorProvider.getDescriptor(
|
||||||
|
iface.identifier.name).prettyNativeType)
|
||||||
|
else:
|
||||||
|
result = CGGeneric("Promise")
|
||||||
if self.resultAlreadyAddRefed:
|
if self.resultAlreadyAddRefed:
|
||||||
if isMember:
|
if isMember:
|
||||||
holder = "RefPtr"
|
holder = "RefPtr"
|
||||||
|
@ -14320,11 +14276,18 @@ class CGNativeMember(ClassMethod):
|
||||||
# auto-wrapping in Nullable
|
# auto-wrapping in Nullable
|
||||||
return CGUnionStruct.unionTypeDecl(type, isMember), True, False
|
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():
|
if type.isGeckoInterface() and not type.isCallbackInterface():
|
||||||
iface = type.unroll().inner
|
iface = type.unroll().inner
|
||||||
argIsPointer = type.nullable() or iface.isExternal()
|
argIsPointer = type.nullable() or iface.isExternal()
|
||||||
forceOwningType = (iface.isCallback() or isMember or
|
forceOwningType = (iface.isCallback() or isMember)
|
||||||
iface.identifier.name == "Promise")
|
|
||||||
if argIsPointer:
|
if argIsPointer:
|
||||||
if (optional or isMember) and forceOwningType:
|
if (optional or isMember) and forceOwningType:
|
||||||
typeDecl = "RefPtr<%s>"
|
typeDecl = "RefPtr<%s>"
|
||||||
|
@ -16958,7 +16921,10 @@ class CGEventGetter(CGNativeMember):
|
||||||
def getMethodBody(self):
|
def getMethodBody(self):
|
||||||
type = self.member.type
|
type = self.member.type
|
||||||
memberName = CGDictionary.makeMemberName(self.member.identifier.name)
|
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"
|
return "return " + memberName + ";\n"
|
||||||
if type.isDOMString() or type.isByteString() or type.isUSVString():
|
if type.isDOMString() or type.isByteString() or type.isUSVString():
|
||||||
return "aRetVal = " + memberName + ";\n"
|
return "aRetVal = " + memberName + ";\n"
|
||||||
|
@ -17369,6 +17335,8 @@ class CGEventClass(CGBindingImplClass):
|
||||||
nativeType = CGGeneric("nsString")
|
nativeType = CGGeneric("nsString")
|
||||||
elif type.isByteString():
|
elif type.isByteString():
|
||||||
nativeType = CGGeneric("nsCString")
|
nativeType = CGGeneric("nsCString")
|
||||||
|
elif type.isPromise():
|
||||||
|
nativeType = CGGeneric("RefPtr<Promise>")
|
||||||
elif type.isGeckoInterface():
|
elif type.isGeckoInterface():
|
||||||
iface = type.unroll().inner
|
iface = type.unroll().inner
|
||||||
nativeType = self.descriptor.getDescriptor(
|
nativeType = self.descriptor.getDescriptor(
|
||||||
|
@ -17393,7 +17361,7 @@ class CGEventClass(CGBindingImplClass):
|
||||||
innerType = type.inner
|
innerType = type.inner
|
||||||
if (not innerType.isPrimitive() and not innerType.isEnum() and
|
if (not innerType.isPrimitive() and not innerType.isEnum() and
|
||||||
not innerType.isDOMString() and not innerType.isByteString() 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 "
|
raise TypeError("Don't know how to properly manage GC/CC for "
|
||||||
"event member of type %s" %
|
"event member of type %s" %
|
||||||
type)
|
type)
|
||||||
|
|
|
@ -468,13 +468,6 @@ class Descriptor(DescriptorProvider):
|
||||||
self.wrapperCache = (not self.interface.isCallback() and
|
self.wrapperCache = (not self.interface.isCallback() and
|
||||||
not self.interface.isIteratorInterface() and
|
not self.interface.isIteratorInterface() and
|
||||||
desc.get('wrapperCache', True))
|
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
|
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_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_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_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_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_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.")
|
MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
|
||||||
|
|
|
@ -7,9 +7,7 @@
|
||||||
#include "mozilla/dom/ToJSValue.h"
|
#include "mozilla/dom/ToJSValue.h"
|
||||||
#include "mozilla/dom/DOMException.h"
|
#include "mozilla/dom/DOMException.h"
|
||||||
#include "mozilla/dom/Exceptions.h"
|
#include "mozilla/dom/Exceptions.h"
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
#include "nsAString.h"
|
#include "nsAString.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsStringBuffer.h"
|
#include "nsStringBuffer.h"
|
||||||
|
@ -66,15 +64,13 @@ ToJSValue(JSContext* aCx,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
bool
|
bool
|
||||||
ToJSValue(JSContext* aCx, Promise& aArgument,
|
ToJSValue(JSContext* aCx, Promise& aArgument,
|
||||||
JS::MutableHandle<JS::Value> aValue)
|
JS::MutableHandle<JS::Value> aValue)
|
||||||
{
|
{
|
||||||
aValue.setObject(*aArgument.PromiseObj());
|
aValue.setObject(*aArgument.PromiseObj());
|
||||||
return true;
|
return MaybeWrapObjectValue(aCx, aValue);
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -306,13 +306,11 @@ ToJSValue(JSContext* aCx,
|
||||||
return ToJSValue(aCx, *aArgument, aValue);
|
return ToJSValue(aCx, *aArgument, aValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
// Accept Promise objects, which need special handling.
|
// Accept Promise objects, which need special handling.
|
||||||
MOZ_MUST_USE bool
|
MOZ_MUST_USE bool
|
||||||
ToJSValue(JSContext* aCx,
|
ToJSValue(JSContext* aCx,
|
||||||
Promise& aArgument,
|
Promise& aArgument,
|
||||||
JS::MutableHandle<JS::Value> aValue);
|
JS::MutableHandle<JS::Value> aValue);
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
// Accept arrays of other things we accept
|
// Accept arrays of other things we accept
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -344,7 +344,7 @@ typedef TypedArray<uint8_t, js::UnwrapSharedArrayBuffer, JS_GetSharedArrayBuffer
|
||||||
// A class for converting an nsTArray to a TypedArray
|
// A class for converting an nsTArray to a TypedArray
|
||||||
// Note: A TypedArrayCreator must not outlive the nsTArray it was created from.
|
// 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
|
// 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>
|
template<typename TypedArrayType>
|
||||||
class TypedArrayCreator
|
class TypedArrayCreator
|
||||||
{
|
{
|
||||||
|
|
|
@ -1597,11 +1597,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
|
||||||
|
|
||||||
args = attr.args() if attr.hasArgs() else []
|
args = attr.args() if attr.hasArgs() else []
|
||||||
|
|
||||||
if self.identifier.name == "Promise":
|
retType = IDLWrapperType(self.location, self)
|
||||||
promiseType = BuiltinTypes[IDLBuiltinType.Types.any]
|
|
||||||
else:
|
|
||||||
promiseType = None
|
|
||||||
retType = IDLWrapperType(self.location, self, promiseType)
|
|
||||||
|
|
||||||
if identifier == "Constructor" or identifier == "ChromeConstructor":
|
if identifier == "Constructor" or identifier == "ChromeConstructor":
|
||||||
name = "constructor"
|
name = "constructor"
|
||||||
|
@ -1988,7 +1984,8 @@ class IDLType(IDLObject):
|
||||||
'callback',
|
'callback',
|
||||||
'union',
|
'union',
|
||||||
'sequence',
|
'sequence',
|
||||||
'record'
|
'record',
|
||||||
|
'promise'
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, location, name):
|
def __init__(self, location, name):
|
||||||
|
@ -2142,9 +2139,8 @@ class IDLUnresolvedType(IDLType):
|
||||||
Unresolved types are interface types
|
Unresolved types are interface types
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, location, name, promiseInnerType=None):
|
def __init__(self, location, name):
|
||||||
IDLType.__init__(self, location, name)
|
IDLType.__init__(self, location, name)
|
||||||
self._promiseInnerType = promiseInnerType
|
|
||||||
|
|
||||||
def isComplete(self):
|
def isComplete(self):
|
||||||
return False
|
return False
|
||||||
|
@ -2171,11 +2167,8 @@ class IDLUnresolvedType(IDLType):
|
||||||
assert self.name.name == obj.identifier.name
|
assert self.name.name == obj.identifier.name
|
||||||
return IDLCallbackType(self.location, obj)
|
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)
|
name = self.name.resolve(scope, None)
|
||||||
return IDLWrapperType(self.location, obj, self._promiseInnerType)
|
return IDLWrapperType(self.location, obj)
|
||||||
|
|
||||||
def isDistinguishableFrom(self, other):
|
def isDistinguishableFrom(self, other):
|
||||||
raise TypeError("Can't tell whether an unresolved type is or is not "
|
raise TypeError("Can't tell whether an unresolved type is or is not "
|
||||||
|
@ -2285,7 +2278,9 @@ class IDLNullableType(IDLParameterizedType):
|
||||||
return self.inner.isInterface()
|
return self.inner.isInterface()
|
||||||
|
|
||||||
def isPromise(self):
|
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):
|
def isCallbackInterface(self):
|
||||||
return self.inner.isCallbackInterface()
|
return self.inner.isCallbackInterface()
|
||||||
|
@ -2698,13 +2693,11 @@ class IDLTypedef(IDLObjectWithIdentifier):
|
||||||
|
|
||||||
|
|
||||||
class IDLWrapperType(IDLType):
|
class IDLWrapperType(IDLType):
|
||||||
def __init__(self, location, inner, promiseInnerType=None):
|
def __init__(self, location, inner):
|
||||||
IDLType.__init__(self, location, inner.identifier.name)
|
IDLType.__init__(self, location, inner.identifier.name)
|
||||||
self.inner = inner
|
self.inner = inner
|
||||||
self._identifier = inner.identifier
|
self._identifier = inner.identifier
|
||||||
self.builtin = False
|
self.builtin = False
|
||||||
assert not promiseInnerType or inner.identifier.name == "Promise"
|
|
||||||
self._promiseInnerType = promiseInnerType
|
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return (isinstance(other, IDLWrapperType) and
|
return (isinstance(other, IDLWrapperType) and
|
||||||
|
@ -2754,14 +2747,6 @@ class IDLWrapperType(IDLType):
|
||||||
def isEnum(self):
|
def isEnum(self):
|
||||||
return isinstance(self.inner, IDLEnum)
|
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):
|
def isSerializable(self):
|
||||||
if self.isInterface():
|
if self.isInterface():
|
||||||
if self.inner.isExternal():
|
if self.inner.isExternal():
|
||||||
|
@ -2793,8 +2778,6 @@ class IDLWrapperType(IDLType):
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
def isDistinguishableFrom(self, other):
|
def isDistinguishableFrom(self, other):
|
||||||
if self.isPromise():
|
|
||||||
return False
|
|
||||||
if other.isPromise():
|
if other.isPromise():
|
||||||
return False
|
return False
|
||||||
if other.isUnion():
|
if other.isUnion():
|
||||||
|
@ -2841,10 +2824,6 @@ class IDLWrapperType(IDLType):
|
||||||
# Let's say true, though ideally we'd only do this when
|
# Let's say true, though ideally we'd only do this when
|
||||||
# exposureSet contains the primary global's name.
|
# exposureSet contains the primary global's name.
|
||||||
return True
|
return True
|
||||||
if (self.isPromise() and
|
|
||||||
# Check the internal type
|
|
||||||
not self.promiseInnerType().unroll().isExposedInAllOf(exposureSet)):
|
|
||||||
return False
|
|
||||||
return iface.exposureSet.issuperset(exposureSet)
|
return iface.exposureSet.issuperset(exposureSet)
|
||||||
|
|
||||||
def _getDependentObjects(self):
|
def _getDependentObjects(self):
|
||||||
|
@ -2872,6 +2851,45 @@ class IDLWrapperType(IDLType):
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
|
|
||||||
|
class IDLPromiseType(IDLParameterizedType):
|
||||||
|
def __init__(self, location, innerType):
|
||||||
|
IDLParameterizedType.__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):
|
class IDLBuiltinType(IDLType):
|
||||||
|
|
||||||
Types = enum(
|
Types = enum(
|
||||||
|
@ -3990,7 +4008,9 @@ class IDLAttribute(IDLInterfaceMember):
|
||||||
raise WebIDLError("An attribute with [PutForwards] must have an "
|
raise WebIDLError("An attribute with [PutForwards] must have an "
|
||||||
"interface type as its type", [self.location])
|
"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 "
|
raise WebIDLError("An attribute with [SameObject] must have an "
|
||||||
"interface type as its type", [self.location])
|
"interface type as its type", [self.location])
|
||||||
|
|
||||||
|
@ -6394,17 +6414,13 @@ class Parser(Tokenizer):
|
||||||
type = IDLSequenceType(self.getLocation(p, 1), innerType)
|
type = IDLSequenceType(self.getLocation(p, 1), innerType)
|
||||||
p[0] = self.handleNullable(type, p[5])
|
p[0] = self.handleNullable(type, p[5])
|
||||||
|
|
||||||
# Note: Promise<void> is allowed, so we want to parametrize on
|
# Note: Promise<void> is allowed, so we want to parameterize on
|
||||||
# ReturnType, not Type. Also, we want this to end up picking up
|
# ReturnType, not Type. Promise types can't be null, hence no "Null" in there.
|
||||||
# the Promise interface for now, hence the games with IDLUnresolvedType.
|
|
||||||
def p_NonAnyTypePromiseType(self, p):
|
def p_NonAnyTypePromiseType(self, p):
|
||||||
"""
|
"""
|
||||||
NonAnyType : PROMISE LT ReturnType GT Null
|
NonAnyType : PROMISE LT ReturnType GT
|
||||||
"""
|
"""
|
||||||
innerType = p[3]
|
p[0] = IDLPromiseType(self.getLocation(p, 1), 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])
|
|
||||||
|
|
||||||
def p_NonAnyTypeRecordType(self, p):
|
def p_NonAnyTypeRecordType(self, p):
|
||||||
"""
|
"""
|
||||||
|
@ -6423,7 +6439,7 @@ class Parser(Tokenizer):
|
||||||
|
|
||||||
if p[1].name == "Promise":
|
if p[1].name == "Promise":
|
||||||
raise WebIDLError("Promise used without saying what it's "
|
raise WebIDLError("Promise used without saying what it's "
|
||||||
"parametrized over",
|
"parameterized over",
|
||||||
[self.getLocation(p, 1)])
|
[self.getLocation(p, 1)])
|
||||||
|
|
||||||
type = None
|
type = None
|
||||||
|
|
|
@ -263,7 +263,6 @@ def WebIDLTest(parser, harness):
|
||||||
callback Callback2 = long(short arg);
|
callback Callback2 = long(short arg);
|
||||||
dictionary Dict {};
|
dictionary Dict {};
|
||||||
dictionary Dict2 {};
|
dictionary Dict2 {};
|
||||||
interface _Promise {};
|
|
||||||
interface TestInterface {%s
|
interface TestInterface {%s
|
||||||
};
|
};
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -2,7 +2,6 @@ def WebIDLTest(parser, harness):
|
||||||
threw = False
|
threw = False
|
||||||
try:
|
try:
|
||||||
parser.parse("""
|
parser.parse("""
|
||||||
interface _Promise {};
|
|
||||||
interface A {
|
interface A {
|
||||||
legacycaller Promise<any> foo();
|
legacycaller Promise<any> foo();
|
||||||
};
|
};
|
||||||
|
@ -18,7 +17,6 @@ def WebIDLTest(parser, harness):
|
||||||
threw = False
|
threw = False
|
||||||
try:
|
try:
|
||||||
parser.parse("""
|
parser.parse("""
|
||||||
interface _Promise {};
|
|
||||||
interface A {
|
interface A {
|
||||||
Promise<any> foo();
|
Promise<any> foo();
|
||||||
long foo(long arg);
|
long foo(long arg);
|
||||||
|
@ -35,7 +33,6 @@ def WebIDLTest(parser, harness):
|
||||||
threw = False
|
threw = False
|
||||||
try:
|
try:
|
||||||
parser.parse("""
|
parser.parse("""
|
||||||
interface _Promise {};
|
|
||||||
interface A {
|
interface A {
|
||||||
long foo(long arg);
|
long foo(long arg);
|
||||||
Promise<any> foo();
|
Promise<any> foo();
|
||||||
|
@ -50,7 +47,6 @@ def WebIDLTest(parser, harness):
|
||||||
|
|
||||||
parser = parser.reset()
|
parser = parser.reset()
|
||||||
parser.parse("""
|
parser.parse("""
|
||||||
interface _Promise {};
|
|
||||||
interface A {
|
interface A {
|
||||||
Promise<any> foo();
|
Promise<any> foo();
|
||||||
Promise<any> foo(long arg);
|
Promise<any> foo(long arg);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,17 +21,6 @@
|
||||||
#include "js/TypeDecls.h"
|
#include "js/TypeDecls.h"
|
||||||
#include "jspubtd.h"
|
#include "jspubtd.h"
|
||||||
|
|
||||||
// Bug 1083361 introduces a new mechanism for tracking uncaught
|
|
||||||
// rejections. This #define serves to track down the parts of code
|
|
||||||
// that need to be removed once clients have been put together
|
|
||||||
// to take advantage of the new mechanism. New code should not
|
|
||||||
// depend on code #ifdefed to this #define.
|
|
||||||
#define DOM_PROMISE_DEPRECATED_REPORTING !SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
#include "mozilla/dom/workers/bindings/WorkerHolder.h"
|
|
||||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
|
|
||||||
class nsIGlobalObject;
|
class nsIGlobalObject;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -40,88 +29,36 @@ namespace dom {
|
||||||
class AnyCallback;
|
class AnyCallback;
|
||||||
class DOMError;
|
class DOMError;
|
||||||
class MediaStreamError;
|
class MediaStreamError;
|
||||||
class PromiseCallback;
|
|
||||||
class PromiseInit;
|
class PromiseInit;
|
||||||
class PromiseNativeHandler;
|
class PromiseNativeHandler;
|
||||||
class PromiseDebugging;
|
class PromiseDebugging;
|
||||||
|
|
||||||
class Promise;
|
|
||||||
|
|
||||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
class PromiseReportRejectWorkerHolder : public workers::WorkerHolder
|
|
||||||
{
|
|
||||||
// PromiseReportRejectWorkerHolder is held by an nsAutoPtr on the Promise
|
|
||||||
// which means that this object will be destroyed before the Promise is
|
|
||||||
// destroyed.
|
|
||||||
Promise* MOZ_NON_OWNING_REF mPromise;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit PromiseReportRejectWorkerHolder(Promise* aPromise)
|
|
||||||
: mPromise(aPromise)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mPromise);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
Notify(workers::Status aStatus) override;
|
|
||||||
};
|
|
||||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
|
|
||||||
#define NS_PROMISE_IID \
|
#define NS_PROMISE_IID \
|
||||||
{ 0x1b8d6215, 0x3e67, 0x43ba, \
|
{ 0x1b8d6215, 0x3e67, 0x43ba, \
|
||||||
{ 0x8a, 0xf9, 0x31, 0x5e, 0x8f, 0xce, 0x75, 0x65 } }
|
{ 0x8a, 0xf9, 0x31, 0x5e, 0x8f, 0xce, 0x75, 0x65 } }
|
||||||
|
|
||||||
class Promise : public nsISupports,
|
class Promise : public nsISupports,
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
// Only wrappercached when we're not using SpiderMonkey
|
|
||||||
// promises, because those don't have a useful object moved
|
|
||||||
// hook, which wrappercache needs.
|
|
||||||
public nsWrapperCache,
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
public SupportsWeakPtr<Promise>
|
public SupportsWeakPtr<Promise>
|
||||||
{
|
{
|
||||||
friend class NativePromiseCallback;
|
|
||||||
friend class PromiseReactionJob;
|
|
||||||
friend class PromiseResolverTask;
|
|
||||||
friend class PromiseTask;
|
friend class PromiseTask;
|
||||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
friend class PromiseReportRejectWorkerHolder;
|
|
||||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
friend class PromiseWorkerProxy;
|
friend class PromiseWorkerProxy;
|
||||||
friend class PromiseWorkerProxyRunnable;
|
friend class PromiseWorkerProxyRunnable;
|
||||||
friend class RejectPromiseCallback;
|
|
||||||
friend class ResolvePromiseCallback;
|
|
||||||
friend class PromiseResolveThenableJob;
|
|
||||||
friend class FastPromiseResolveThenableJob;
|
|
||||||
friend class WrapperPromiseCallback;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROMISE_IID)
|
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROMISE_IID)
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
// We're not skippable, since we're not owned from JS to start with.
|
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
|
||||||
#else // SPIDERMONKEY_PROMISE
|
|
||||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(Promise)
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Promise)
|
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Promise)
|
||||||
|
|
||||||
// Promise creation tries to create a JS reflector for the Promise, so is
|
// Promise creation tries to create a JS reflector for the Promise, so is
|
||||||
// fallible. Furthermore, we don't want to do JS-wrapping on a 0-refcount
|
// fallible. Furthermore, we don't want to do JS-wrapping on a 0-refcount
|
||||||
// object, so we addref before doing that and return the addrefed pointer
|
// object, so we addref before doing that and return the addrefed pointer
|
||||||
// here.
|
// here.
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
static already_AddRefed<Promise>
|
static already_AddRefed<Promise>
|
||||||
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv);
|
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv);
|
||||||
|
|
||||||
// Reports a rejected Promise by sending an error report.
|
// Reports a rejected Promise by sending an error report.
|
||||||
static void ReportRejectedPromise(JSContext* aCx, JS::HandleObject aPromise);
|
static void ReportRejectedPromise(JSContext* aCx, JS::HandleObject aPromise);
|
||||||
#else
|
|
||||||
static already_AddRefed<Promise>
|
|
||||||
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv,
|
|
||||||
// Passing null for aDesiredProto will use Promise.prototype.
|
|
||||||
JS::Handle<JSObject*> aDesiredProto = nullptr);
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
typedef void (Promise::*MaybeFunc)(JSContext* aCx,
|
typedef void (Promise::*MaybeFunc)(JSContext* aCx,
|
||||||
JS::Handle<JS::Value> aValue);
|
JS::Handle<JS::Value> aValue);
|
||||||
|
@ -183,11 +120,6 @@ public:
|
||||||
return mGlobal;
|
return mGlobal;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
bool
|
|
||||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
|
||||||
JS::MutableHandle<JSObject*> aWrapper);
|
|
||||||
|
|
||||||
// Do the equivalent of Promise.resolve in the compartment of aGlobal. The
|
// Do the equivalent of Promise.resolve in the compartment of aGlobal. The
|
||||||
// compartment of aCx is ignored. Errors are reported on the ErrorResult; if
|
// compartment of aCx is ignored. Errors are reported on the ErrorResult; if
|
||||||
// aRv comes back !Failed(), this function MUST return a non-null value.
|
// aRv comes back !Failed(), this function MUST return a non-null value.
|
||||||
|
@ -223,95 +155,17 @@ public:
|
||||||
return mPromiseObj;
|
return mPromiseObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // SPIDERMONKEY_PROMISE
|
|
||||||
JSObject* PromiseObj()
|
|
||||||
{
|
|
||||||
return GetWrapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual JSObject*
|
|
||||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
|
||||||
|
|
||||||
static already_AddRefed<Promise>
|
|
||||||
Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
|
|
||||||
ErrorResult& aRv, JS::Handle<JSObject*> aDesiredProto);
|
|
||||||
|
|
||||||
static void
|
|
||||||
Resolve(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
|
|
||||||
JS::Handle<JS::Value> aValue,
|
|
||||||
JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);
|
|
||||||
|
|
||||||
static already_AddRefed<Promise>
|
|
||||||
Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
|
||||||
|
|
||||||
static void
|
|
||||||
Reject(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
|
|
||||||
JS::Handle<JS::Value> aValue,
|
|
||||||
JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);
|
|
||||||
|
|
||||||
static already_AddRefed<Promise>
|
|
||||||
Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
|
||||||
|
|
||||||
void
|
|
||||||
Then(JSContext* aCx,
|
|
||||||
// aCalleeGlobal may not be in the compartment of aCx, when called over
|
|
||||||
// Xrays.
|
|
||||||
JS::Handle<JSObject*> aCalleeGlobal,
|
|
||||||
AnyCallback* aResolveCallback, AnyCallback* aRejectCallback,
|
|
||||||
JS::MutableHandle<JS::Value> aRetval,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
void
|
|
||||||
Catch(JSContext* aCx,
|
|
||||||
AnyCallback* aRejectCallback,
|
|
||||||
JS::MutableHandle<JS::Value> aRetval,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
static void
|
|
||||||
All(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
|
|
||||||
JS::Handle<JS::Value> aIterable, JS::MutableHandle<JS::Value> aRetval,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
static already_AddRefed<Promise>
|
|
||||||
All(const GlobalObject& aGlobal,
|
|
||||||
const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv);
|
|
||||||
|
|
||||||
static void
|
|
||||||
Race(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
|
|
||||||
JS::Handle<JS::Value> aIterable, JS::MutableHandle<JS::Value> aRetval,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
static bool
|
|
||||||
PromiseSpecies(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
void AppendNativeHandler(PromiseNativeHandler* aRunnable);
|
void AppendNativeHandler(PromiseNativeHandler* aRunnable);
|
||||||
|
|
||||||
JSObject* GlobalJSObject() const;
|
JSObject* GlobalJSObject() const;
|
||||||
|
|
||||||
JSCompartment* Compartment() const;
|
JSCompartment* Compartment() const;
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
// Return a unique-to-the-process identifier for this Promise.
|
|
||||||
uint64_t GetID();
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
enum JSCallbackSlots {
|
|
||||||
SLOT_PROMISE = 0,
|
|
||||||
SLOT_DATA
|
|
||||||
};
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
// Create a dom::Promise from a given SpiderMonkey Promise object.
|
// Create a dom::Promise from a given SpiderMonkey Promise object.
|
||||||
// aPromiseObj MUST be in the compartment of aGlobal's global JS object.
|
// aPromiseObj MUST be in the compartment of aGlobal's global JS object.
|
||||||
static already_AddRefed<Promise>
|
static already_AddRefed<Promise>
|
||||||
CreateFromExisting(nsIGlobalObject* aGlobal,
|
CreateFromExisting(nsIGlobalObject* aGlobal,
|
||||||
JS::Handle<JSObject*> aPromiseObj);
|
JS::Handle<JSObject*> aPromiseObj);
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
enum class PromiseState {
|
enum class PromiseState {
|
||||||
Pending,
|
Pending,
|
||||||
|
@ -335,99 +189,7 @@ protected:
|
||||||
// use the default prototype for the sort of Promise we have.
|
// use the default prototype for the sort of Promise we have.
|
||||||
void CreateWrapper(JS::Handle<JSObject*> aDesiredProto, ErrorResult& aRv);
|
void CreateWrapper(JS::Handle<JSObject*> aDesiredProto, ErrorResult& aRv);
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
// Create the JS resolving functions of resolve() and reject(). And provide
|
|
||||||
// references to the two functions by calling PromiseInit passed from Promise
|
|
||||||
// constructor.
|
|
||||||
void CallInitFunction(const GlobalObject& aGlobal, PromiseInit& aInit,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
// The NewPromiseCapability function from
|
|
||||||
// <http://www.ecma-international.org/ecma-262/6.0/#sec-newpromisecapability>.
|
|
||||||
// Errors are communicated via aRv. If aForceCallbackCreation is
|
|
||||||
// true, then this function will ensure that aCapability has a
|
|
||||||
// useful mResolve/mReject even if mNativePromise is non-null.
|
|
||||||
static void NewPromiseCapability(JSContext* aCx, nsIGlobalObject* aGlobal,
|
|
||||||
JS::Handle<JS::Value> aConstructor,
|
|
||||||
bool aForceCallbackCreation,
|
|
||||||
PromiseCapability& aCapability,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
bool IsPending()
|
|
||||||
{
|
|
||||||
return mResolvePending;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetDependentPromises(nsTArray<RefPtr<Promise>>& aPromises);
|
|
||||||
|
|
||||||
bool IsLastInChain() const
|
|
||||||
{
|
|
||||||
return mIsLastInChain;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetNotifiedAsUncaught()
|
|
||||||
{
|
|
||||||
mWasNotifiedAsUncaught = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WasNotifiedAsUncaught() const
|
|
||||||
{
|
|
||||||
return mWasNotifiedAsUncaught;
|
|
||||||
}
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
friend class PromiseDebugging;
|
|
||||||
|
|
||||||
void SetState(PromiseState aState)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mState == Pending);
|
|
||||||
MOZ_ASSERT(aState != Pending);
|
|
||||||
mState = aState;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetResult(JS::Handle<JS::Value> aValue)
|
|
||||||
{
|
|
||||||
mResult = aValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method enqueues promise's resolve/reject callbacks with promise's
|
|
||||||
// result. It's executed when the resolver.resolve() or resolver.reject() is
|
|
||||||
// called or when the promise already has a result and new callbacks are
|
|
||||||
// appended by then() or catch().
|
|
||||||
void TriggerPromiseReactions();
|
|
||||||
|
|
||||||
void Settle(JS::Handle<JS::Value> aValue, Promise::PromiseState aState);
|
|
||||||
void MaybeSettle(JS::Handle<JS::Value> aValue, Promise::PromiseState aState);
|
|
||||||
|
|
||||||
void AppendCallbacks(PromiseCallback* aResolveCallback,
|
|
||||||
PromiseCallback* aRejectCallback);
|
|
||||||
|
|
||||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
// If we have been rejected and our mResult is a JS exception,
|
|
||||||
// report it to the error console.
|
|
||||||
// Use MaybeReportRejectedOnce() for actual calls.
|
|
||||||
void MaybeReportRejected();
|
|
||||||
|
|
||||||
void MaybeReportRejectedOnce() {
|
|
||||||
MaybeReportRejected();
|
|
||||||
RemoveWorkerHolder();
|
|
||||||
mResult.setUndefined();
|
|
||||||
}
|
|
||||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
|
|
||||||
void MaybeResolveInternal(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue);
|
|
||||||
void MaybeRejectInternal(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue);
|
|
||||||
|
|
||||||
void ResolveInternal(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue);
|
|
||||||
void RejectInternal(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue);
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void MaybeSomething(T& aArgument, MaybeFunc aFunc) {
|
void MaybeSomething(T& aArgument, MaybeFunc aFunc) {
|
||||||
MOZ_ASSERT(PromiseObj()); // It was preserved!
|
MOZ_ASSERT(PromiseObj()); // It was preserved!
|
||||||
|
@ -444,92 +206,11 @@ private:
|
||||||
(this->*aFunc)(cx, val);
|
(this->*aFunc)(cx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
// Static methods for the PromiseInit functions.
|
|
||||||
static bool
|
|
||||||
JSCallback(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
|
|
||||||
|
|
||||||
static bool
|
|
||||||
ThenableResolverCommon(JSContext* aCx, uint32_t /* PromiseCallback::Task */ aTask,
|
|
||||||
unsigned aArgc, JS::Value* aVp);
|
|
||||||
static bool
|
|
||||||
JSCallbackThenableResolver(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
|
|
||||||
static bool
|
|
||||||
JSCallbackThenableRejecter(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
|
|
||||||
|
|
||||||
static JSObject*
|
|
||||||
CreateFunction(JSContext* aCx, Promise* aPromise, int32_t aTask);
|
|
||||||
|
|
||||||
static JSObject*
|
|
||||||
CreateThenableFunction(JSContext* aCx, Promise* aPromise, uint32_t aTask);
|
|
||||||
|
|
||||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
void RemoveWorkerHolder();
|
|
||||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
|
|
||||||
// Capture the current stack and store it in aTarget. If false is
|
|
||||||
// returned, an exception is presumably pending on aCx.
|
|
||||||
bool CaptureStack(JSContext* aCx, JS::Heap<JSObject*>& aTarget);
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
void HandleException(JSContext* aCx);
|
void HandleException(JSContext* aCx);
|
||||||
|
|
||||||
RefPtr<nsIGlobalObject> mGlobal;
|
RefPtr<nsIGlobalObject> mGlobal;
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
nsTArray<RefPtr<PromiseCallback> > mResolveCallbacks;
|
|
||||||
nsTArray<RefPtr<PromiseCallback> > mRejectCallbacks;
|
|
||||||
|
|
||||||
JS::Heap<JS::Value> mResult;
|
|
||||||
// A stack that shows where this promise was allocated, if there was
|
|
||||||
// JS running at the time. Otherwise null.
|
|
||||||
JS::Heap<JSObject*> mAllocationStack;
|
|
||||||
// mRejectionStack is only set when the promise is rejected directly from
|
|
||||||
// script, by calling Promise.reject() or the rejection callback we pass to
|
|
||||||
// the PromiseInit function. Promises that are rejected internally do not
|
|
||||||
// have a rejection stack.
|
|
||||||
JS::Heap<JSObject*> mRejectionStack;
|
|
||||||
// mFullfillmentStack is only set when the promise is fulfilled directly from
|
|
||||||
// script, by calling Promise.resolve() or the fulfillment callback we pass to
|
|
||||||
// the PromiseInit function. Promises that are fulfilled internally do not
|
|
||||||
// have a fulfillment stack.
|
|
||||||
JS::Heap<JSObject*> mFullfillmentStack;
|
|
||||||
PromiseState mState;
|
|
||||||
|
|
||||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
bool mHadRejectCallback;
|
|
||||||
|
|
||||||
// If a rejected promise on a worker has no reject callbacks attached, it
|
|
||||||
// needs to know when the worker is shutting down, to report the error on the
|
|
||||||
// console before the worker's context is deleted. This feature is used for
|
|
||||||
// that purpose.
|
|
||||||
nsAutoPtr<PromiseReportRejectWorkerHolder> mWorkerHolder;
|
|
||||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
|
||||||
|
|
||||||
bool mTaskPending;
|
|
||||||
bool mResolvePending;
|
|
||||||
|
|
||||||
// `true` if this Promise is the last in the chain, or `false` if
|
|
||||||
// another Promise has been created from this one by a call to
|
|
||||||
// `then`, `all`, `race`, etc.
|
|
||||||
bool mIsLastInChain;
|
|
||||||
|
|
||||||
// `true` if PromiseDebugging has already notified at least one observer that
|
|
||||||
// this promise was left uncaught, `false` otherwise.
|
|
||||||
bool mWasNotifiedAsUncaught;
|
|
||||||
|
|
||||||
// The time when this promise was created.
|
|
||||||
TimeStamp mCreationTimestamp;
|
|
||||||
|
|
||||||
// The time when this promise transitioned out of the pending state.
|
|
||||||
TimeStamp mSettlementTimestamp;
|
|
||||||
|
|
||||||
// Once `GetID()` has been called, a unique-to-the-process identifier for this
|
|
||||||
// promise. Until then, `0`.
|
|
||||||
uint64_t mID;
|
|
||||||
#else // SPIDERMONKEY_PROMISE
|
|
||||||
JS::Heap<JSObject*> mPromiseObj;
|
JS::Heap<JSObject*> mPromiseObj;
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(Promise, NS_PROMISE_IID)
|
NS_DEFINE_STATIC_IID_ACCESSOR(Promise, NS_PROMISE_IID)
|
||||||
|
|
|
@ -1,571 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* 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/. */
|
|
||||||
|
|
||||||
#include "PromiseCallback.h"
|
|
||||||
#include "mozilla/dom/Promise.h"
|
|
||||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
|
||||||
|
|
||||||
#include "jsapi.h"
|
|
||||||
#include "jsfriendapi.h"
|
|
||||||
#include "jswrapper.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseCallback)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
||||||
NS_INTERFACE_MAP_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_0(PromiseCallback)
|
|
||||||
|
|
||||||
PromiseCallback::PromiseCallback()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PromiseCallback::~PromiseCallback()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResolvePromiseCallback
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(ResolvePromiseCallback)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ResolvePromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
|
|
||||||
tmp->mGlobal = nullptr;
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ResolvePromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ResolvePromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ResolvePromiseCallback)
|
|
||||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
|
||||||
|
|
||||||
NS_IMPL_ADDREF_INHERITED(ResolvePromiseCallback, PromiseCallback)
|
|
||||||
NS_IMPL_RELEASE_INHERITED(ResolvePromiseCallback, PromiseCallback)
|
|
||||||
|
|
||||||
ResolvePromiseCallback::ResolvePromiseCallback(Promise* aPromise,
|
|
||||||
JS::Handle<JSObject*> aGlobal)
|
|
||||||
: mPromise(aPromise)
|
|
||||||
, mGlobal(aGlobal)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aPromise);
|
|
||||||
MOZ_ASSERT(aGlobal);
|
|
||||||
HoldJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvePromiseCallback::~ResolvePromiseCallback()
|
|
||||||
{
|
|
||||||
DropJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
ResolvePromiseCallback::Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue)
|
|
||||||
{
|
|
||||||
// Run resolver's algorithm with value and the synchronous flag set.
|
|
||||||
|
|
||||||
JS::ExposeValueToActiveJS(aValue);
|
|
||||||
|
|
||||||
JSAutoCompartment ac(aCx, mGlobal);
|
|
||||||
JS::Rooted<JS::Value> value(aCx, aValue);
|
|
||||||
if (!JS_WrapValue(aCx, &value)) {
|
|
||||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
mPromise->ResolveInternal(aCx, value);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// RejectPromiseCallback
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(RejectPromiseCallback)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(RejectPromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
|
|
||||||
tmp->mGlobal = nullptr;
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(RejectPromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(RejectPromiseCallback)
|
|
||||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(RejectPromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
||||||
|
|
||||||
NS_IMPL_ADDREF_INHERITED(RejectPromiseCallback, PromiseCallback)
|
|
||||||
NS_IMPL_RELEASE_INHERITED(RejectPromiseCallback, PromiseCallback)
|
|
||||||
|
|
||||||
RejectPromiseCallback::RejectPromiseCallback(Promise* aPromise,
|
|
||||||
JS::Handle<JSObject*> aGlobal)
|
|
||||||
: mPromise(aPromise)
|
|
||||||
, mGlobal(aGlobal)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aPromise);
|
|
||||||
MOZ_ASSERT(mGlobal);
|
|
||||||
HoldJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
RejectPromiseCallback::~RejectPromiseCallback()
|
|
||||||
{
|
|
||||||
DropJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
RejectPromiseCallback::Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue)
|
|
||||||
{
|
|
||||||
// Run resolver's algorithm with value and the synchronous flag set.
|
|
||||||
|
|
||||||
JS::ExposeValueToActiveJS(aValue);
|
|
||||||
|
|
||||||
JSAutoCompartment ac(aCx, mGlobal);
|
|
||||||
JS::Rooted<JS::Value> value(aCx, aValue);
|
|
||||||
if (!JS_WrapValue(aCx, &value)) {
|
|
||||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mPromise->RejectInternal(aCx, value);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// InvokePromiseFuncCallback
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(InvokePromiseFuncCallback)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(InvokePromiseFuncCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromiseFunc)
|
|
||||||
tmp->mGlobal = nullptr;
|
|
||||||
tmp->mNextPromiseObj = nullptr;
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(InvokePromiseFuncCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromiseFunc)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(InvokePromiseFuncCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mNextPromiseObj)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(InvokePromiseFuncCallback)
|
|
||||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
|
||||||
|
|
||||||
NS_IMPL_ADDREF_INHERITED(InvokePromiseFuncCallback, PromiseCallback)
|
|
||||||
NS_IMPL_RELEASE_INHERITED(InvokePromiseFuncCallback, PromiseCallback)
|
|
||||||
|
|
||||||
InvokePromiseFuncCallback::InvokePromiseFuncCallback(JS::Handle<JSObject*> aGlobal,
|
|
||||||
JS::Handle<JSObject*> aNextPromiseObj,
|
|
||||||
AnyCallback* aPromiseFunc)
|
|
||||||
: mGlobal(aGlobal)
|
|
||||||
, mNextPromiseObj(aNextPromiseObj)
|
|
||||||
, mPromiseFunc(aPromiseFunc)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aGlobal);
|
|
||||||
MOZ_ASSERT(aNextPromiseObj);
|
|
||||||
MOZ_ASSERT(aPromiseFunc);
|
|
||||||
HoldJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
InvokePromiseFuncCallback::~InvokePromiseFuncCallback()
|
|
||||||
{
|
|
||||||
DropJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
InvokePromiseFuncCallback::Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue)
|
|
||||||
{
|
|
||||||
// Run resolver's algorithm with value and the synchronous flag set.
|
|
||||||
|
|
||||||
JS::ExposeValueToActiveJS(aValue);
|
|
||||||
|
|
||||||
JSAutoCompartment ac(aCx, mGlobal);
|
|
||||||
JS::Rooted<JS::Value> value(aCx, aValue);
|
|
||||||
if (!JS_WrapValue(aCx, &value)) {
|
|
||||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorResult rv;
|
|
||||||
JS::Rooted<JS::Value> ignored(aCx);
|
|
||||||
mPromiseFunc->Call(value, &ignored, rv);
|
|
||||||
// Useful exceptions already got reported.
|
|
||||||
rv.SuppressException();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise*
|
|
||||||
InvokePromiseFuncCallback::GetDependentPromise()
|
|
||||||
{
|
|
||||||
Promise* promise;
|
|
||||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Oh, well.
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrapperPromiseCallback
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(WrapperPromiseCallback)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WrapperPromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNextPromise)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolveFunc)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRejectFunc)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
|
|
||||||
tmp->mGlobal = nullptr;
|
|
||||||
tmp->mNextPromiseObj = nullptr;
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WrapperPromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNextPromise)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolveFunc)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRejectFunc)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WrapperPromiseCallback)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mNextPromiseObj)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(WrapperPromiseCallback)
|
|
||||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
|
||||||
|
|
||||||
NS_IMPL_ADDREF_INHERITED(WrapperPromiseCallback, PromiseCallback)
|
|
||||||
NS_IMPL_RELEASE_INHERITED(WrapperPromiseCallback, PromiseCallback)
|
|
||||||
|
|
||||||
WrapperPromiseCallback::WrapperPromiseCallback(Promise* aNextPromise,
|
|
||||||
JS::Handle<JSObject*> aGlobal,
|
|
||||||
AnyCallback* aCallback)
|
|
||||||
: mNextPromise(aNextPromise)
|
|
||||||
, mGlobal(aGlobal)
|
|
||||||
, mCallback(aCallback)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aNextPromise);
|
|
||||||
MOZ_ASSERT(aGlobal);
|
|
||||||
HoldJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
WrapperPromiseCallback::WrapperPromiseCallback(JS::Handle<JSObject*> aGlobal,
|
|
||||||
AnyCallback* aCallback,
|
|
||||||
JS::Handle<JSObject*> aNextPromiseObj,
|
|
||||||
AnyCallback* aResolveFunc,
|
|
||||||
AnyCallback* aRejectFunc)
|
|
||||||
: mNextPromiseObj(aNextPromiseObj)
|
|
||||||
, mResolveFunc(aResolveFunc)
|
|
||||||
, mRejectFunc(aRejectFunc)
|
|
||||||
, mGlobal(aGlobal)
|
|
||||||
, mCallback(aCallback)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mNextPromiseObj);
|
|
||||||
MOZ_ASSERT(aResolveFunc);
|
|
||||||
MOZ_ASSERT(aRejectFunc);
|
|
||||||
MOZ_ASSERT(aGlobal);
|
|
||||||
HoldJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
WrapperPromiseCallback::~WrapperPromiseCallback()
|
|
||||||
{
|
|
||||||
DropJSObjects(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
WrapperPromiseCallback::Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue)
|
|
||||||
{
|
|
||||||
JS::ExposeValueToActiveJS(aValue);
|
|
||||||
|
|
||||||
JSAutoCompartment ac(aCx, mGlobal);
|
|
||||||
JS::Rooted<JS::Value> value(aCx, aValue);
|
|
||||||
if (!JS_WrapValue(aCx, &value)) {
|
|
||||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorResult rv;
|
|
||||||
|
|
||||||
// PromiseReactionTask step 6
|
|
||||||
JS::Rooted<JS::Value> retValue(aCx);
|
|
||||||
JSCompartment* compartment;
|
|
||||||
if (mNextPromise) {
|
|
||||||
compartment = mNextPromise->Compartment();
|
|
||||||
} else {
|
|
||||||
MOZ_ASSERT(mNextPromiseObj);
|
|
||||||
compartment = js::GetObjectCompartment(mNextPromiseObj);
|
|
||||||
}
|
|
||||||
mCallback->Call(value, &retValue, rv, "promise callback",
|
|
||||||
CallbackObject::eRethrowExceptions,
|
|
||||||
compartment);
|
|
||||||
|
|
||||||
rv.WouldReportJSException();
|
|
||||||
|
|
||||||
// PromiseReactionTask step 7
|
|
||||||
if (rv.Failed()) {
|
|
||||||
if (rv.IsUncatchableException()) {
|
|
||||||
// We have nothing to resolve/reject the promise with.
|
|
||||||
return rv.StealNSResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::Rooted<JS::Value> value(aCx);
|
|
||||||
{ // Scope for JSAutoCompartment
|
|
||||||
// Convert the ErrorResult to a JS exception object that we can reject
|
|
||||||
// ourselves with. This will be exactly the exception that would get
|
|
||||||
// thrown from a binding method whose ErrorResult ended up with whatever
|
|
||||||
// is on "rv" right now. Do this in the promise reflector compartment.
|
|
||||||
Maybe<JSAutoCompartment> ac;
|
|
||||||
if (mNextPromise) {
|
|
||||||
ac.emplace(aCx, mNextPromise->GlobalJSObject());
|
|
||||||
} else {
|
|
||||||
ac.emplace(aCx, mNextPromiseObj);
|
|
||||||
}
|
|
||||||
DebugOnly<bool> conversionResult = ToJSValue(aCx, rv, &value);
|
|
||||||
MOZ_ASSERT(conversionResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mNextPromise) {
|
|
||||||
mNextPromise->RejectInternal(aCx, value);
|
|
||||||
} else {
|
|
||||||
JS::Rooted<JS::Value> ignored(aCx);
|
|
||||||
ErrorResult rejectRv;
|
|
||||||
mRejectFunc->Call(value, &ignored, rejectRv);
|
|
||||||
// This reported any JS exceptions; we just have a pointless exception on
|
|
||||||
// there now.
|
|
||||||
rejectRv.SuppressException();
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the return value is the same as the promise itself, throw TypeError.
|
|
||||||
if (retValue.isObject()) {
|
|
||||||
JS::Rooted<JSObject*> valueObj(aCx, &retValue.toObject());
|
|
||||||
valueObj = js::CheckedUnwrap(valueObj);
|
|
||||||
JS::Rooted<JSObject*> nextPromiseObj(aCx);
|
|
||||||
if (mNextPromise) {
|
|
||||||
nextPromiseObj = mNextPromise->GetWrapper();
|
|
||||||
} else {
|
|
||||||
MOZ_ASSERT(mNextPromiseObj);
|
|
||||||
nextPromiseObj = mNextPromiseObj;
|
|
||||||
}
|
|
||||||
// XXXbz shouldn't this check be over in ResolveInternal anyway?
|
|
||||||
if (valueObj == nextPromiseObj) {
|
|
||||||
const char* fileName = nullptr;
|
|
||||||
uint32_t lineNumber = 0;
|
|
||||||
|
|
||||||
// Try to get some information about the callback to report a sane error,
|
|
||||||
// but don't try too hard (only deals with scripted functions).
|
|
||||||
JS::Rooted<JSObject*> unwrapped(aCx,
|
|
||||||
js::CheckedUnwrap(mCallback->Callback()));
|
|
||||||
|
|
||||||
if (unwrapped) {
|
|
||||||
JSAutoCompartment ac(aCx, unwrapped);
|
|
||||||
if (JS_ObjectIsFunction(aCx, unwrapped)) {
|
|
||||||
JS::Rooted<JS::Value> asValue(aCx, JS::ObjectValue(*unwrapped));
|
|
||||||
JS::Rooted<JSFunction*> func(aCx, JS_ValueToFunction(aCx, asValue));
|
|
||||||
|
|
||||||
MOZ_ASSERT(func);
|
|
||||||
JSScript* script = JS_GetFunctionScript(aCx, func);
|
|
||||||
if (script) {
|
|
||||||
fileName = JS_GetScriptFilename(script);
|
|
||||||
lineNumber = JS_GetScriptBaseLineNumber(aCx, script);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're back in aValue's compartment here.
|
|
||||||
JS::Rooted<JSString*> fn(aCx, JS_NewStringCopyZ(aCx, fileName));
|
|
||||||
if (!fn) {
|
|
||||||
// Out of memory. Promise will stay unresolved.
|
|
||||||
JS_ClearPendingException(aCx);
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::Rooted<JSString*> message(aCx,
|
|
||||||
JS_NewStringCopyZ(aCx,
|
|
||||||
"then() cannot return same Promise that it resolves."));
|
|
||||||
if (!message) {
|
|
||||||
// Out of memory. Promise will stay unresolved.
|
|
||||||
JS_ClearPendingException(aCx);
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::Rooted<JS::Value> typeError(aCx);
|
|
||||||
if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, fn, lineNumber, 0,
|
|
||||||
nullptr, message, &typeError)) {
|
|
||||||
// Out of memory. Promise will stay unresolved.
|
|
||||||
JS_ClearPendingException(aCx);
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mNextPromise) {
|
|
||||||
mNextPromise->RejectInternal(aCx, typeError);
|
|
||||||
} else {
|
|
||||||
JS::Rooted<JS::Value> ignored(aCx);
|
|
||||||
ErrorResult rejectRv;
|
|
||||||
mRejectFunc->Call(typeError, &ignored, rejectRv);
|
|
||||||
// This reported any JS exceptions; we just have a pointless exception
|
|
||||||
// on there now.
|
|
||||||
rejectRv.SuppressException();
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, run resolver's resolve with value.
|
|
||||||
if (!JS_WrapValue(aCx, &retValue)) {
|
|
||||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mNextPromise) {
|
|
||||||
mNextPromise->ResolveInternal(aCx, retValue);
|
|
||||||
} else {
|
|
||||||
JS::Rooted<JS::Value> ignored(aCx);
|
|
||||||
ErrorResult resolveRv;
|
|
||||||
mResolveFunc->Call(retValue, &ignored, resolveRv);
|
|
||||||
// This reported any JS exceptions; we just have a pointless exception
|
|
||||||
// on there now.
|
|
||||||
resolveRv.SuppressException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise*
|
|
||||||
WrapperPromiseCallback::GetDependentPromise()
|
|
||||||
{
|
|
||||||
// Per spec, various algorithms like all() and race() are actually implemented
|
|
||||||
// in terms of calling then() but passing it the resolve/reject functions that
|
|
||||||
// are passed as arguments to function passed to the Promise constructor.
|
|
||||||
// That will cause the promise in question to hold on to a
|
|
||||||
// WrapperPromiseCallback, but the dependent promise should really be the one
|
|
||||||
// whose constructor those functions came from, not the about-to-be-ignored
|
|
||||||
// return value of "then". So try to determine whether we're in that case and
|
|
||||||
// if so go ahead and dig the dependent promise out of the function we have.
|
|
||||||
JSObject* callable = mCallback->Callable();
|
|
||||||
// Unwrap it, in case it's a cross-compartment wrapper. Our caller here is
|
|
||||||
// system, so it's really ok to just go and unwrap.
|
|
||||||
callable = js::UncheckedUnwrap(callable);
|
|
||||||
if (JS_IsNativeFunction(callable, Promise::JSCallback)) {
|
|
||||||
JS::Value promiseVal =
|
|
||||||
js::GetFunctionNativeReserved(callable, Promise::SLOT_PROMISE);
|
|
||||||
Promise* promise;
|
|
||||||
UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mNextPromise) {
|
|
||||||
return mNextPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise* promise;
|
|
||||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Oh, well.
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NativePromiseCallback
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(NativePromiseCallback,
|
|
||||||
PromiseCallback, mHandler)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NativePromiseCallback)
|
|
||||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
|
||||||
|
|
||||||
NS_IMPL_ADDREF_INHERITED(NativePromiseCallback, PromiseCallback)
|
|
||||||
NS_IMPL_RELEASE_INHERITED(NativePromiseCallback, PromiseCallback)
|
|
||||||
|
|
||||||
NativePromiseCallback::NativePromiseCallback(PromiseNativeHandler* aHandler,
|
|
||||||
Promise::PromiseState aState)
|
|
||||||
: mHandler(aHandler)
|
|
||||||
, mState(aState)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
NativePromiseCallback::~NativePromiseCallback()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
NativePromiseCallback::Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue)
|
|
||||||
{
|
|
||||||
JS::ExposeValueToActiveJS(aValue);
|
|
||||||
|
|
||||||
if (mState == Promise::Resolved) {
|
|
||||||
mHandler->ResolvedCallback(aCx, aValue);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mState == Promise::Rejected) {
|
|
||||||
mHandler->RejectedCallback(aCx, aValue);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_NOTREACHED("huh?");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ PromiseCallback*
|
|
||||||
PromiseCallback::Factory(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
|
|
||||||
AnyCallback* aCallback, Task aTask)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aNextPromise);
|
|
||||||
|
|
||||||
// If we have a callback and a next resolver, we have to exec the callback and
|
|
||||||
// then propagate the return value to the next resolver->resolve().
|
|
||||||
if (aCallback) {
|
|
||||||
return new WrapperPromiseCallback(aNextPromise, aGlobal, aCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aTask == Resolve) {
|
|
||||||
return new ResolvePromiseCallback(aNextPromise, aGlobal);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aTask == Reject) {
|
|
||||||
return new RejectPromiseCallback(aNextPromise, aGlobal);
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ASSERT(false, "This should not happen");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,203 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PromiseCallback_h
|
|
||||||
#define mozilla_dom_PromiseCallback_h
|
|
||||||
|
|
||||||
#include "mozilla/dom/Promise.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
// This is the base class for any PromiseCallback.
|
|
||||||
// It's a logical step in the promise chain of callbacks.
|
|
||||||
class PromiseCallback : public nsISupports
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
virtual ~PromiseCallback();
|
|
||||||
|
|
||||||
public:
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS(PromiseCallback)
|
|
||||||
|
|
||||||
PromiseCallback();
|
|
||||||
|
|
||||||
virtual nsresult Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue) = 0;
|
|
||||||
|
|
||||||
// Return the Promise that this callback will end up resolving or
|
|
||||||
// rejecting, if any.
|
|
||||||
virtual Promise* GetDependentPromise() = 0;
|
|
||||||
|
|
||||||
enum Task {
|
|
||||||
Resolve,
|
|
||||||
Reject
|
|
||||||
};
|
|
||||||
|
|
||||||
// This factory returns a PromiseCallback object with refcount of 0.
|
|
||||||
static PromiseCallback*
|
|
||||||
Factory(Promise* aNextPromise, JS::Handle<JSObject*> aObject,
|
|
||||||
AnyCallback* aCallback, Task aTask);
|
|
||||||
};
|
|
||||||
|
|
||||||
// WrapperPromiseCallback execs a JS Callback with a value, and then the return
|
|
||||||
// value is sent to either:
|
|
||||||
// a) If aNextPromise is non-null, the aNextPromise->ResolveFunction() or to
|
|
||||||
// aNextPromise->RejectFunction() if the JS Callback throws.
|
|
||||||
// or
|
|
||||||
// b) If aNextPromise is null, in which case aResolveFunc and aRejectFunc must
|
|
||||||
// be non-null, then to aResolveFunc, unless aCallback threw, in which case
|
|
||||||
// aRejectFunc.
|
|
||||||
class WrapperPromiseCallback final : public PromiseCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WrapperPromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
|
|
||||||
nsresult Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue) override;
|
|
||||||
|
|
||||||
Promise* GetDependentPromise() override;
|
|
||||||
|
|
||||||
// Constructor for when we know we have a vanilla Promise.
|
|
||||||
WrapperPromiseCallback(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
|
|
||||||
AnyCallback* aCallback);
|
|
||||||
|
|
||||||
// Constructor for when all we have to work with are resolve/reject functions.
|
|
||||||
WrapperPromiseCallback(JS::Handle<JSObject*> aGlobal,
|
|
||||||
AnyCallback* aCallback,
|
|
||||||
JS::Handle<JSObject*> mNextPromiseObj,
|
|
||||||
AnyCallback* aResolveFunc,
|
|
||||||
AnyCallback* aRejectFunc);
|
|
||||||
|
|
||||||
private:
|
|
||||||
~WrapperPromiseCallback();
|
|
||||||
|
|
||||||
// Either mNextPromise is non-null or all three of mNextPromiseObj,
|
|
||||||
// mResolveFund and mRejectFunc must are non-null.
|
|
||||||
RefPtr<Promise> mNextPromise;
|
|
||||||
// mNextPromiseObj is the reflector itself; it may not be in the
|
|
||||||
// same compartment as anything else we have.
|
|
||||||
JS::Heap<JSObject*> mNextPromiseObj;
|
|
||||||
RefPtr<AnyCallback> mResolveFunc;
|
|
||||||
RefPtr<AnyCallback> mRejectFunc;
|
|
||||||
JS::Heap<JSObject*> mGlobal;
|
|
||||||
RefPtr<AnyCallback> mCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ResolvePromiseCallback calls aPromise->ResolveFunction() with the value
|
|
||||||
// received by Call().
|
|
||||||
class ResolvePromiseCallback final : public PromiseCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ResolvePromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
|
|
||||||
nsresult Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue) override;
|
|
||||||
|
|
||||||
Promise* GetDependentPromise() override
|
|
||||||
{
|
|
||||||
return mPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResolvePromiseCallback(Promise* aPromise, JS::Handle<JSObject*> aGlobal);
|
|
||||||
|
|
||||||
private:
|
|
||||||
~ResolvePromiseCallback();
|
|
||||||
|
|
||||||
RefPtr<Promise> mPromise;
|
|
||||||
JS::Heap<JSObject*> mGlobal;
|
|
||||||
};
|
|
||||||
|
|
||||||
// RejectPromiseCallback calls aPromise->RejectFunction() with the value
|
|
||||||
// received by Call().
|
|
||||||
class RejectPromiseCallback final : public PromiseCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(RejectPromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
|
|
||||||
nsresult Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue) override;
|
|
||||||
|
|
||||||
Promise* GetDependentPromise() override
|
|
||||||
{
|
|
||||||
return mPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
RejectPromiseCallback(Promise* aPromise, JS::Handle<JSObject*> aGlobal);
|
|
||||||
|
|
||||||
private:
|
|
||||||
~RejectPromiseCallback();
|
|
||||||
|
|
||||||
RefPtr<Promise> mPromise;
|
|
||||||
JS::Heap<JSObject*> mGlobal;
|
|
||||||
};
|
|
||||||
|
|
||||||
// InvokePromiseFuncCallback calls the given function with the value
|
|
||||||
// received by Call().
|
|
||||||
class InvokePromiseFuncCallback final : public PromiseCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(InvokePromiseFuncCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
|
|
||||||
nsresult Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue) override;
|
|
||||||
|
|
||||||
Promise* GetDependentPromise() override;
|
|
||||||
|
|
||||||
InvokePromiseFuncCallback(JS::Handle<JSObject*> aGlobal,
|
|
||||||
JS::Handle<JSObject*> aNextPromiseObj,
|
|
||||||
AnyCallback* aPromiseFunc);
|
|
||||||
|
|
||||||
private:
|
|
||||||
~InvokePromiseFuncCallback();
|
|
||||||
|
|
||||||
JS::Heap<JSObject*> mGlobal;
|
|
||||||
JS::Heap<JSObject*> mNextPromiseObj;
|
|
||||||
RefPtr<AnyCallback> mPromiseFunc;
|
|
||||||
};
|
|
||||||
|
|
||||||
// NativePromiseCallback wraps a PromiseNativeHandler.
|
|
||||||
class NativePromiseCallback final : public PromiseCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NativePromiseCallback,
|
|
||||||
PromiseCallback)
|
|
||||||
|
|
||||||
nsresult Call(JSContext* aCx,
|
|
||||||
JS::Handle<JS::Value> aValue) override;
|
|
||||||
|
|
||||||
Promise* GetDependentPromise() override
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
NativePromiseCallback(PromiseNativeHandler* aHandler,
|
|
||||||
Promise::PromiseState aState);
|
|
||||||
|
|
||||||
private:
|
|
||||||
~NativePromiseCallback();
|
|
||||||
|
|
||||||
RefPtr<PromiseNativeHandler> mHandler;
|
|
||||||
Promise::PromiseState mState;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PromiseCallback_h
|
|
|
@ -66,20 +66,6 @@ private:
|
||||||
/* static */ MOZ_THREAD_LOCAL(bool)
|
/* static */ MOZ_THREAD_LOCAL(bool)
|
||||||
FlushRejections::sDispatched;
|
FlushRejections::sDispatched;
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
static Promise*
|
|
||||||
UnwrapPromise(JS::Handle<JSObject*> aPromise, ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
Promise* promise;
|
|
||||||
if (NS_WARN_IF(NS_FAILED(UNWRAP_OBJECT(Promise, aPromise, promise)))) {
|
|
||||||
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING("Argument"));
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
PromiseDebugging::GetState(GlobalObject& aGlobal, JS::Handle<JSObject*> aPromise,
|
PromiseDebugging::GetState(GlobalObject& aGlobal, JS::Handle<JSObject*> aPromise,
|
||||||
PromiseDebuggingStateHolder& aState,
|
PromiseDebuggingStateHolder& aState,
|
||||||
|
@ -173,34 +159,6 @@ PromiseDebugging::GetFullfillmentStack(GlobalObject& aGlobal,
|
||||||
aStack.set(JS::GetPromiseResolutionSite(obj));
|
aStack.set(JS::GetPromiseResolutionSite(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* static */ void
|
|
||||||
PromiseDebugging::GetState(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
|
||||||
PromiseDebuggingStateHolder& aState,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
|
||||||
if (aRv.Failed()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (promise->mState) {
|
|
||||||
case Promise::Pending:
|
|
||||||
aState.mState = PromiseDebuggingState::Pending;
|
|
||||||
break;
|
|
||||||
case Promise::Resolved:
|
|
||||||
aState.mState = PromiseDebuggingState::Fulfilled;
|
|
||||||
aState.mValue = promise->mResult;
|
|
||||||
break;
|
|
||||||
case Promise::Rejected:
|
|
||||||
aState.mState = PromiseDebuggingState::Rejected;
|
|
||||||
aState.mReason = promise->mResult;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/*static */ nsString
|
/*static */ nsString
|
||||||
PromiseDebugging::sIDPrefix;
|
PromiseDebugging::sIDPrefix;
|
||||||
|
|
||||||
|
@ -232,86 +190,6 @@ PromiseDebugging::FlushUncaughtRejections()
|
||||||
FlushRejections::FlushSync();
|
FlushRejections::FlushSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/* static */ void
|
|
||||||
PromiseDebugging::GetAllocationStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
|
||||||
JS::MutableHandle<JSObject*> aStack,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
|
||||||
if (aRv.Failed()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
aStack.set(promise->mAllocationStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ void
|
|
||||||
PromiseDebugging::GetRejectionStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
|
||||||
JS::MutableHandle<JSObject*> aStack,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
|
||||||
if (aRv.Failed()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
aStack.set(promise->mRejectionStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ void
|
|
||||||
PromiseDebugging::GetFullfillmentStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
|
||||||
JS::MutableHandle<JSObject*> aStack,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
|
||||||
if (aRv.Failed()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
aStack.set(promise->mFullfillmentStack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ void
|
|
||||||
PromiseDebugging::GetDependentPromises(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
|
||||||
nsTArray<RefPtr<Promise>>& aPromises,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
|
||||||
if (aRv.Failed()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
promise->GetDependentPromises(aPromises);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ double
|
|
||||||
PromiseDebugging::GetPromiseLifetime(GlobalObject&,
|
|
||||||
JS::Handle<JSObject*> aPromise,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
|
||||||
if (aRv.Failed()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (TimeStamp::Now() - promise->mCreationTimestamp).ToMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ double
|
|
||||||
PromiseDebugging::GetTimeToSettle(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
|
||||||
if (aRv.Failed()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (promise->mState == Promise::Pending) {
|
|
||||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return (promise->mSettlementTimestamp -
|
|
||||||
promise->mCreationTimestamp).ToMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
PromiseDebugging::AddUncaughtRejectionObserver(GlobalObject&,
|
PromiseDebugging::AddUncaughtRejectionObserver(GlobalObject&,
|
||||||
UncaughtRejectionObserver& aObserver)
|
UncaughtRejectionObserver& aObserver)
|
||||||
|
@ -337,8 +215,6 @@ PromiseDebugging::RemoveUncaughtRejectionObserver(GlobalObject&,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
PromiseDebugging::AddUncaughtRejection(JS::HandleObject aPromise)
|
PromiseDebugging::AddUncaughtRejection(JS::HandleObject aPromise)
|
||||||
{
|
{
|
||||||
|
@ -420,102 +296,5 @@ PromiseDebugging::FlushUncaughtRejectionsInternal()
|
||||||
storage->mConsumedRejections.clear();
|
storage->mConsumedRejections.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* static */ void
|
|
||||||
PromiseDebugging::AddUncaughtRejection(Promise& aPromise)
|
|
||||||
{
|
|
||||||
CycleCollectedJSContext::Get()->mUncaughtRejections.AppendElement(&aPromise);
|
|
||||||
FlushRejections::DispatchNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* void */ void
|
|
||||||
PromiseDebugging::AddConsumedRejection(Promise& aPromise)
|
|
||||||
{
|
|
||||||
CycleCollectedJSContext::Get()->mConsumedRejections.AppendElement(&aPromise);
|
|
||||||
FlushRejections::DispatchNeeded();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ void
|
|
||||||
PromiseDebugging::GetPromiseID(GlobalObject&,
|
|
||||||
JS::Handle<JSObject*> aPromise,
|
|
||||||
nsString& aID,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
|
||||||
if (aRv.Failed()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint64_t promiseID = promise->GetID();
|
|
||||||
aID = sIDPrefix;
|
|
||||||
aID.AppendInt(promiseID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ void
|
|
||||||
PromiseDebugging::FlushUncaughtRejectionsInternal()
|
|
||||||
{
|
|
||||||
CycleCollectedJSContext* storage = CycleCollectedJSContext::Get();
|
|
||||||
|
|
||||||
// The Promise that have been left uncaught (rejected and last in
|
|
||||||
// their chain) since the last call to this function.
|
|
||||||
nsTArray<nsCOMPtr<nsISupports>> uncaught;
|
|
||||||
storage->mUncaughtRejections.SwapElements(uncaught);
|
|
||||||
|
|
||||||
// The Promise that have been left uncaught at some point, but that
|
|
||||||
// have eventually had their `then` method called.
|
|
||||||
nsTArray<nsCOMPtr<nsISupports>> consumed;
|
|
||||||
storage->mConsumedRejections.SwapElements(consumed);
|
|
||||||
|
|
||||||
nsTArray<nsCOMPtr<nsISupports>>& observers = storage->mUncaughtRejectionObservers;
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
// Notify observers of uncaught Promise.
|
|
||||||
|
|
||||||
for (size_t i = 0; i < uncaught.Length(); ++i) {
|
|
||||||
nsCOMPtr<Promise> promise = do_QueryInterface(uncaught[i], &rv);
|
|
||||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
|
||||||
|
|
||||||
if (!promise->IsLastInChain()) {
|
|
||||||
// This promise is not the last in the chain anymore,
|
|
||||||
// so the error has been caught at some point.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For the moment, the Promise is still at the end of the
|
|
||||||
// chain. Let's inform observers, so that they may decide whether
|
|
||||||
// to report it.
|
|
||||||
for (size_t j = 0; j < observers.Length(); ++j) {
|
|
||||||
ErrorResult err;
|
|
||||||
RefPtr<UncaughtRejectionObserver> obs =
|
|
||||||
static_cast<UncaughtRejectionObserver*>(observers[j].get());
|
|
||||||
|
|
||||||
obs->OnLeftUncaught(*promise, err); // Ignore errors
|
|
||||||
}
|
|
||||||
|
|
||||||
promise->SetNotifiedAsUncaught();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify observers of consumed Promise.
|
|
||||||
|
|
||||||
for (size_t i = 0; i < consumed.Length(); ++i) {
|
|
||||||
nsCOMPtr<Promise> promise = do_QueryInterface(consumed[i], &rv);
|
|
||||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
|
||||||
|
|
||||||
if (!promise->WasNotifiedAsUncaught()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ASSERT(!promise->IsLastInChain());
|
|
||||||
for (size_t j = 0; j < observers.Length(); ++j) {
|
|
||||||
ErrorResult err;
|
|
||||||
RefPtr<UncaughtRejectionObserver> obs =
|
|
||||||
static_cast<UncaughtRejectionObserver*>(observers[j].get());
|
|
||||||
|
|
||||||
obs->OnConsumed(*promise, err); // Ignore errors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -52,37 +52,17 @@ public:
|
||||||
JS::MutableHandle<JSObject*> aStack,
|
JS::MutableHandle<JSObject*> aStack,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
static void GetDependentPromises(GlobalObject&,
|
|
||||||
JS::Handle<JSObject*> aPromise,
|
|
||||||
nsTArray<RefPtr<Promise>>& aPromises,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
static double GetPromiseLifetime(GlobalObject&,
|
|
||||||
JS::Handle<JSObject*> aPromise,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
static double GetTimeToSettle(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
// Mechanism for watching uncaught instances of Promise.
|
// Mechanism for watching uncaught instances of Promise.
|
||||||
static void AddUncaughtRejectionObserver(GlobalObject&,
|
static void AddUncaughtRejectionObserver(GlobalObject&,
|
||||||
UncaughtRejectionObserver& aObserver);
|
UncaughtRejectionObserver& aObserver);
|
||||||
static bool RemoveUncaughtRejectionObserver(GlobalObject&,
|
static bool RemoveUncaughtRejectionObserver(GlobalObject&,
|
||||||
UncaughtRejectionObserver& aObserver);
|
UncaughtRejectionObserver& aObserver);
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
// Mark a Promise as having been left uncaught at script completion.
|
// Mark a Promise as having been left uncaught at script completion.
|
||||||
static void AddUncaughtRejection(JS::HandleObject);
|
static void AddUncaughtRejection(JS::HandleObject);
|
||||||
// Mark a Promise previously added with `AddUncaughtRejection` as
|
// Mark a Promise previously added with `AddUncaughtRejection` as
|
||||||
// eventually consumed.
|
// eventually consumed.
|
||||||
static void AddConsumedRejection(JS::HandleObject);
|
static void AddConsumedRejection(JS::HandleObject);
|
||||||
#else
|
|
||||||
// Mark a Promise as having been left uncaught at script completion.
|
|
||||||
static void AddUncaughtRejection(Promise&);
|
|
||||||
// Mark a Promise previously added with `AddUncaughtRejection` as
|
|
||||||
// eventually consumed.
|
|
||||||
static void AddConsumedRejection(Promise&);
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
// Propagate the informations from AddUncaughtRejection
|
// Propagate the informations from AddUncaughtRejection
|
||||||
// and AddConsumedRejection to observers.
|
// and AddConsumedRejection to observers.
|
||||||
static void FlushUncaughtRejections();
|
static void FlushUncaughtRejections();
|
||||||
|
|
|
@ -11,9 +11,8 @@ EXPORTS.mozilla.dom += [
|
||||||
'PromiseWorkerProxy.h',
|
'PromiseWorkerProxy.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
SOURCES += [
|
||||||
'Promise.cpp',
|
'Promise.cpp',
|
||||||
'PromiseCallback.cpp',
|
|
||||||
'PromiseDebugging.cpp',
|
'PromiseDebugging.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -3,75 +3,18 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/.
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*
|
*
|
||||||
* The origin of this IDL file is
|
* This IDL file contains utilities to help connect JS promises to our
|
||||||
* http://dom.spec.whatwg.org/#promises
|
* 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();
|
callback PromiseJobCallback = void();
|
||||||
|
|
||||||
[TreatNonCallableAsNull]
|
[TreatNonCallableAsNull]
|
||||||
callback AnyCallback = any (any value);
|
callback AnyCallback = any (any value);
|
||||||
|
|
||||||
// When using SpiderMonkey promises, we don't want to define all this stuff;
|
|
||||||
// just define a tiny interface to make codegen of Promise arguments and return
|
|
||||||
// values work.
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
[Constructor(PromiseInit init),
|
|
||||||
Exposed=(Window,Worker,WorkerDebugger,System)]
|
|
||||||
// Need to escape "Promise" so it's treated as an identifier.
|
|
||||||
interface _Promise {
|
|
||||||
// Have to use "any" (or "object", but "any" is simpler) as the type to
|
|
||||||
// support the subclassing behavior, since nothing actually requires the
|
|
||||||
// return value of PromiseSubclass.resolve/reject to be a Promise object.
|
|
||||||
[NewObject, Throws]
|
|
||||||
static any resolve(optional any value);
|
|
||||||
[NewObject, Throws]
|
|
||||||
static any reject(optional any value);
|
|
||||||
|
|
||||||
// The [TreatNonCallableAsNull] annotation is required since then() should do
|
|
||||||
// nothing instead of throwing errors when non-callable arguments are passed.
|
|
||||||
// Have to use "any" (or "object", but "any" is simpler) as the type to
|
|
||||||
// support the subclassing behavior, since nothing actually requires the
|
|
||||||
// return value of PromiseSubclass.then/catch to be a Promise object.
|
|
||||||
[NewObject, Throws]
|
|
||||||
any then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
|
|
||||||
[TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
|
|
||||||
|
|
||||||
[NewObject, Throws]
|
|
||||||
any catch([TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
|
|
||||||
|
|
||||||
// Have to use "any" (or "object", but "any" is simpler) as the type to
|
|
||||||
// support the subclassing behavior, since nothing actually requires the
|
|
||||||
// return value of PromiseSubclass.all to be a Promise object. As a result,
|
|
||||||
// we also have to do our argument conversion manually, because we want to
|
|
||||||
// convert its exceptions into rejections.
|
|
||||||
[NewObject, Throws]
|
|
||||||
static any all(optional any iterable);
|
|
||||||
|
|
||||||
// Have to use "any" (or "object", but "any" is simpler) as the type to
|
|
||||||
// support the subclassing behavior, since nothing actually requires the
|
|
||||||
// return value of PromiseSubclass.race to be a Promise object. As a result,
|
|
||||||
// we also have to do our argument conversion manually, because we want to
|
|
||||||
// convert its exceptions into rejections.
|
|
||||||
[NewObject, Throws]
|
|
||||||
static any race(optional any iterable);
|
|
||||||
};
|
|
||||||
#else // SPIDERMONKEY_PROMISE
|
|
||||||
[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
|
// Hack to allow us to have JS owning and properly tracing/CCing/etc a
|
||||||
// PromiseNativeHandler.
|
// PromiseNativeHandler.
|
||||||
[NoInterfaceObject,
|
[NoInterfaceObject,
|
||||||
Exposed=(Window,Worker,System)]
|
Exposed=(Window,Worker,System)]
|
||||||
interface PromiseNativeHandler {
|
interface PromiseNativeHandler {
|
||||||
};
|
};
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
|
@ -38,11 +38,7 @@ callback interface UncaughtRejectionObserver {
|
||||||
* caught, i.e. if its `then` callback is called, `onConsumed` will
|
* caught, i.e. if its `then` callback is called, `onConsumed` will
|
||||||
* be called.
|
* be called.
|
||||||
*/
|
*/
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
void onLeftUncaught(object p);
|
void onLeftUncaught(object p);
|
||||||
#else
|
|
||||||
void onLeftUncaught(Promise<any> p);
|
|
||||||
#endif SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Promise previously left uncaught is not the last in its
|
* A Promise previously left uncaught is not the last in its
|
||||||
|
@ -51,11 +47,7 @@ callback interface UncaughtRejectionObserver {
|
||||||
* @param p A Promise that was previously left in uncaught state is
|
* @param p A Promise that was previously left in uncaught state is
|
||||||
* now caught, i.e. it is not the last in its chain anymore.
|
* now caught, i.e. it is not the last in its chain anymore.
|
||||||
*/
|
*/
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
void onConsumed(object p);
|
void onConsumed(object p);
|
||||||
#else
|
|
||||||
void onConsumed(Promise<any> p);
|
|
||||||
#endif SPIDERMONKEY_PROMISE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[ChromeOnly, Exposed=(Window,System)]
|
[ChromeOnly, Exposed=(Window,System)]
|
||||||
|
@ -105,42 +97,6 @@ interface PromiseDebugging {
|
||||||
[Throws]
|
[Throws]
|
||||||
static object? getFullfillmentStack(object p);
|
static object? getFullfillmentStack(object p);
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
/**
|
|
||||||
* Get the promises directly depending on a given promise. These are:
|
|
||||||
*
|
|
||||||
* 1) Return values of then() calls on the promise
|
|
||||||
* 2) Return values of Promise.all() if the given promise was passed in as one
|
|
||||||
* of the arguments.
|
|
||||||
* 3) Return values of Promise.race() if the given promise was passed in as
|
|
||||||
* one of the arguments.
|
|
||||||
*
|
|
||||||
* Once a promise is settled, it will generally notify its dependent promises
|
|
||||||
* and forget about them, so this is most useful on unsettled promises.
|
|
||||||
*
|
|
||||||
* Note that this function only returns the promises that directly depend on
|
|
||||||
* p. It does not recursively return promises that depend on promises that
|
|
||||||
* depend on p.
|
|
||||||
*/
|
|
||||||
[Throws]
|
|
||||||
static sequence<Promise<any>> getDependentPromises(object p);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of milliseconds elapsed since the given promise was created.
|
|
||||||
*/
|
|
||||||
[Throws]
|
|
||||||
static DOMHighResTimeStamp getPromiseLifetime(object p);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the number of milliseconds elapsed between the promise being created
|
|
||||||
* and being settled. Throws NS_ERROR_UNEXPECTED if the promise has not
|
|
||||||
* settled.
|
|
||||||
*/
|
|
||||||
[Throws]
|
|
||||||
static DOMHighResTimeStamp getTimeToSettle(object p);
|
|
||||||
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Watching uncaught rejections on the current thread.
|
* Watching uncaught rejections on the current thread.
|
||||||
*
|
*
|
||||||
|
|
|
@ -70,7 +70,7 @@ interface TestInterfaceJS : EventTarget {
|
||||||
|
|
||||||
// Tests for promise-rejection behavior
|
// Tests for promise-rejection behavior
|
||||||
Promise<void> testPromiseWithThrowingChromePromiseInit();
|
Promise<void> testPromiseWithThrowingChromePromiseInit();
|
||||||
Promise<void> testPromiseWithThrowingContentPromiseInit(PromiseInit func);
|
Promise<void> testPromiseWithThrowingContentPromiseInit(Function func);
|
||||||
Promise<void> testPromiseWithDOMExceptionThrowingPromiseInit();
|
Promise<void> testPromiseWithDOMExceptionThrowingPromiseInit();
|
||||||
Promise<void> testPromiseWithThrowingChromeThenFunction();
|
Promise<void> testPromiseWithThrowingChromeThenFunction();
|
||||||
Promise<void> testPromiseWithThrowingContentThenFunction(AnyCallback func);
|
Promise<void> testPromiseWithThrowingContentThenFunction(AnyCallback func);
|
||||||
|
|
|
@ -12,8 +12,6 @@ PREPROCESSED_WEBIDL_FILES = [
|
||||||
'HTMLMediaElement.webidl',
|
'HTMLMediaElement.webidl',
|
||||||
'Navigator.webidl',
|
'Navigator.webidl',
|
||||||
'Node.webidl',
|
'Node.webidl',
|
||||||
'Promise.webidl',
|
|
||||||
'PromiseDebugging.webidl',
|
|
||||||
'Window.webidl',
|
'Window.webidl',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -363,6 +361,8 @@ WEBIDL_FILES = [
|
||||||
'PresentationRequest.webidl',
|
'PresentationRequest.webidl',
|
||||||
'ProcessingInstruction.webidl',
|
'ProcessingInstruction.webidl',
|
||||||
'ProfileTimelineMarker.webidl',
|
'ProfileTimelineMarker.webidl',
|
||||||
|
'Promise.webidl',
|
||||||
|
'PromiseDebugging.webidl',
|
||||||
'PushEvent.webidl',
|
'PushEvent.webidl',
|
||||||
'PushManager.webidl',
|
'PushManager.webidl',
|
||||||
'PushManager.webidl',
|
'PushManager.webidl',
|
||||||
|
|
|
@ -37,19 +37,6 @@ def js_disable_shell(value):
|
||||||
set_config('JS_DISABLE_SHELL', js_disable_shell)
|
set_config('JS_DISABLE_SHELL', js_disable_shell)
|
||||||
|
|
||||||
|
|
||||||
# Use SpiderMonkey Promise implementation if it's enabled
|
|
||||||
# =======================================================
|
|
||||||
js_option('--enable-sm-promise', default=True,
|
|
||||||
help='Enable SpiderMonkey promises')
|
|
||||||
|
|
||||||
@depends('--enable-sm-promise')
|
|
||||||
def sm_promise(value):
|
|
||||||
if value:
|
|
||||||
return True
|
|
||||||
|
|
||||||
set_config('SPIDERMONKEY_PROMISE', sm_promise)
|
|
||||||
set_define('SPIDERMONKEY_PROMISE', sm_promise)
|
|
||||||
|
|
||||||
# SpiderMonkey as a shared library, and how its symbols are exported
|
# SpiderMonkey as a shared library, and how its symbols are exported
|
||||||
# ==================================================================
|
# ==================================================================
|
||||||
js_option('--disable-shared-js', default=building_js,
|
js_option('--disable-shared-js', default=building_js,
|
||||||
|
|
|
@ -1328,7 +1328,6 @@ OOMTest(JSContext* cx, unsigned argc, Value* vp)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
static bool
|
static bool
|
||||||
SettlePromiseNow(JSContext* cx, unsigned argc, Value* vp)
|
SettlePromiseNow(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
@ -1437,43 +1436,6 @@ RejectPromise(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static const js::Class FakePromiseClass = {
|
|
||||||
"Promise", JSCLASS_IS_ANONYMOUS
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool
|
|
||||||
MakeFakePromise(JSContext* cx, unsigned argc, Value* vp)
|
|
||||||
{
|
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
|
||||||
|
|
||||||
RootedObject obj(cx, NewObjectWithGivenProto(cx, &FakePromiseClass, nullptr));
|
|
||||||
if (!obj)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
JS::dbg::onNewPromise(cx, obj);
|
|
||||||
args.rval().setObject(*obj);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
SettleFakePromise(JSContext* cx, unsigned argc, Value* vp)
|
|
||||||
{
|
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
|
||||||
if (!args.requireAtLeast(cx, "settleFakePromise", 1))
|
|
||||||
return false;
|
|
||||||
if (!args[0].isObject() || args[0].toObject().getClass() != &FakePromiseClass) {
|
|
||||||
JS_ReportErrorASCII(cx, "first argument must be a (fake) Promise object");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RootedObject promise(cx, &args[0].toObject());
|
|
||||||
JS::dbg::onPromiseSettled(cx, promise);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
static unsigned finalizeCount = 0;
|
static unsigned finalizeCount = 0;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -4190,7 +4152,6 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
|
||||||
" This is also disabled when --fuzzing-safe is specified."),
|
" This is also disabled when --fuzzing-safe is specified."),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
JS_FN_HELP("settlePromiseNow", SettlePromiseNow, 1, 0,
|
JS_FN_HELP("settlePromiseNow", SettlePromiseNow, 1, 0,
|
||||||
"settlePromiseNow(promise)",
|
"settlePromiseNow(promise)",
|
||||||
" 'Settle' a 'promise' immediately. This just marks the promise as resolved\n"
|
" 'Settle' a 'promise' immediately. This just marks the promise as resolved\n"
|
||||||
|
@ -4207,20 +4168,6 @@ JS_FN_HELP("resolvePromise", ResolvePromise, 2, 0,
|
||||||
JS_FN_HELP("rejectPromise", RejectPromise, 2, 0,
|
JS_FN_HELP("rejectPromise", RejectPromise, 2, 0,
|
||||||
"rejectPromise(promise, reason)",
|
"rejectPromise(promise, reason)",
|
||||||
" Reject a Promise by calling the JSAPI function JS::RejectPromise."),
|
" Reject a Promise by calling the JSAPI function JS::RejectPromise."),
|
||||||
#else
|
|
||||||
JS_FN_HELP("makeFakePromise", MakeFakePromise, 0, 0,
|
|
||||||
"makeFakePromise()",
|
|
||||||
" Create an object whose [[Class]] name is 'Promise' and call\n"
|
|
||||||
" JS::dbg::onNewPromise on it before returning it. It doesn't actually have\n"
|
|
||||||
" any of the other behavior associated with promises."),
|
|
||||||
|
|
||||||
JS_FN_HELP("settleFakePromise", SettleFakePromise, 1, 0,
|
|
||||||
"settleFakePromise(promise)",
|
|
||||||
" 'Settle' a 'promise' created by makeFakePromise(). This doesn't have any\n"
|
|
||||||
" observable effects outside of firing any onPromiseSettled hooks set on\n"
|
|
||||||
" Debugger instances that are observing the given promise's global as a\n"
|
|
||||||
" debuggee."),
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
JS_FN_HELP("makeFinalizeObserver", MakeFinalizeObserver, 0, 0,
|
JS_FN_HELP("makeFinalizeObserver", MakeFinalizeObserver, 0, 0,
|
||||||
"makeFinalizeObserver()",
|
"makeFinalizeObserver()",
|
||||||
|
|
|
@ -77,6 +77,7 @@ UNIFIED_SOURCES += [
|
||||||
'testPrintf.cpp',
|
'testPrintf.cpp',
|
||||||
'testPrivateGCThingValue.cpp',
|
'testPrivateGCThingValue.cpp',
|
||||||
'testProfileStrings.cpp',
|
'testProfileStrings.cpp',
|
||||||
|
'testPromise.cpp',
|
||||||
'testPropCache.cpp',
|
'testPropCache.cpp',
|
||||||
'testRegExp.cpp',
|
'testRegExp.cpp',
|
||||||
'testResolveRecursion.cpp',
|
'testResolveRecursion.cpp',
|
||||||
|
@ -124,11 +125,6 @@ if CONFIG['ENABLE_ION']:
|
||||||
'testJitRValueAlloc.cpp',
|
'testJitRValueAlloc.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['SPIDERMONKEY_PROMISE']:
|
|
||||||
UNIFIED_SOURCES += [
|
|
||||||
'testPromise.cpp',
|
|
||||||
]
|
|
||||||
|
|
||||||
DEFINES['EXPORT_JS_API'] = True
|
DEFINES['EXPORT_JS_API'] = True
|
||||||
|
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
|
|
|
@ -57,12 +57,6 @@
|
||||||
#define IF_SAB(real,imaginary) imaginary
|
#define IF_SAB(real,imaginary) imaginary
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
#define IF_PROMISE(real,imaginary) real
|
|
||||||
#else
|
|
||||||
#define IF_PROMISE(real,imaginary) imaginary
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define JS_FOR_PROTOTYPES(real,imaginary) \
|
#define JS_FOR_PROTOTYPES(real,imaginary) \
|
||||||
imaginary(Null, 0, InitNullClass, dummy) \
|
imaginary(Null, 0, InitNullClass, dummy) \
|
||||||
real(Object, 1, InitViaClassSpec, OCLASP(Plain)) \
|
real(Object, 1, InitViaClassSpec, OCLASP(Plain)) \
|
||||||
|
@ -118,7 +112,7 @@ IF_SAB(real,imaginary)(Atomics, 47, InitAtomicsClass, OCLASP(Atomics)) \
|
||||||
imaginary(WasmInstance, 51, dummy, dummy) \
|
imaginary(WasmInstance, 51, dummy, dummy) \
|
||||||
imaginary(WasmMemory, 52, dummy, dummy) \
|
imaginary(WasmMemory, 52, dummy, dummy) \
|
||||||
imaginary(WasmTable, 53, dummy, dummy) \
|
imaginary(WasmTable, 53, dummy, dummy) \
|
||||||
IF_PROMISE(real,imaginary)(Promise, 54, InitViaClassSpec, OCLASP(Promise)) \
|
real(Promise, 54, InitViaClassSpec, OCLASP(Promise)) \
|
||||||
|
|
||||||
#define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
|
#define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
|
||||||
|
|
||||||
|
|
|
@ -761,6 +761,7 @@ selfhosted.inputs = [
|
||||||
'builtin/Module.js',
|
'builtin/Module.js',
|
||||||
'builtin/Number.js',
|
'builtin/Number.js',
|
||||||
'builtin/Object.js',
|
'builtin/Object.js',
|
||||||
|
'builtin/Promise.js',
|
||||||
'builtin/Reflect.js',
|
'builtin/Reflect.js',
|
||||||
'builtin/RegExp.js',
|
'builtin/RegExp.js',
|
||||||
'builtin/RegExpGlobalReplaceOpt.h.js',
|
'builtin/RegExpGlobalReplaceOpt.h.js',
|
||||||
|
@ -774,9 +775,6 @@ selfhosted.inputs = [
|
||||||
'builtin/WeakSet.js'
|
'builtin/WeakSet.js'
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['SPIDERMONKEY_PROMISE']:
|
|
||||||
selfhosted.inputs += ['builtin/Promise.js']
|
|
||||||
|
|
||||||
if CONFIG['JS_HAS_CTYPES']:
|
if CONFIG['JS_HAS_CTYPES']:
|
||||||
if CONFIG['MOZ_SYSTEM_FFI']:
|
if CONFIG['MOZ_SYSTEM_FFI']:
|
||||||
CXXFLAGS += CONFIG['MOZ_FFI_CFLAGS']
|
CXXFLAGS += CONFIG['MOZ_FFI_CFLAGS']
|
||||||
|
|
|
@ -154,7 +154,6 @@ static const double MAX_TIMEOUT_SECONDS = 1800.0;
|
||||||
# define SHARED_MEMORY_DEFAULT 0
|
# define SHARED_MEMORY_DEFAULT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
using JobQueue = GCVector<JSObject*, 0, SystemAllocPolicy>;
|
using JobQueue = GCVector<JSObject*, 0, SystemAllocPolicy>;
|
||||||
|
|
||||||
struct ShellAsyncTasks
|
struct ShellAsyncTasks
|
||||||
|
@ -167,7 +166,6 @@ struct ShellAsyncTasks
|
||||||
size_t outstanding;
|
size_t outstanding;
|
||||||
Vector<JS::AsyncTask*> finished;
|
Vector<JS::AsyncTask*> finished;
|
||||||
};
|
};
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
enum class ScriptKind
|
enum class ScriptKind
|
||||||
{
|
{
|
||||||
|
@ -272,12 +270,10 @@ struct ShellContext
|
||||||
JS::PersistentRootedValue interruptFunc;
|
JS::PersistentRootedValue interruptFunc;
|
||||||
bool lastWarningEnabled;
|
bool lastWarningEnabled;
|
||||||
JS::PersistentRootedValue lastWarning;
|
JS::PersistentRootedValue lastWarning;
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
JS::PersistentRootedValue promiseRejectionTrackerCallback;
|
JS::PersistentRootedValue promiseRejectionTrackerCallback;
|
||||||
JS::PersistentRooted<JobQueue> jobQueue;
|
JS::PersistentRooted<JobQueue> jobQueue;
|
||||||
ExclusiveData<ShellAsyncTasks> asyncTasks;
|
ExclusiveData<ShellAsyncTasks> asyncTasks;
|
||||||
bool drainingJobQueue;
|
bool drainingJobQueue;
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Watchdog thread state.
|
* Watchdog thread state.
|
||||||
|
@ -435,11 +431,9 @@ ShellContext::ShellContext(JSContext* cx)
|
||||||
interruptFunc(cx, NullValue()),
|
interruptFunc(cx, NullValue()),
|
||||||
lastWarningEnabled(false),
|
lastWarningEnabled(false),
|
||||||
lastWarning(cx, NullValue()),
|
lastWarning(cx, NullValue()),
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
promiseRejectionTrackerCallback(cx, NullValue()),
|
promiseRejectionTrackerCallback(cx, NullValue()),
|
||||||
asyncTasks(mutexid::ShellAsyncTasks, cx),
|
asyncTasks(mutexid::ShellAsyncTasks, cx),
|
||||||
drainingJobQueue(false),
|
drainingJobQueue(false),
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
watchdogLock(mutexid::ShellContextWatchdog),
|
watchdogLock(mutexid::ShellContextWatchdog),
|
||||||
exitCode(0),
|
exitCode(0),
|
||||||
quitting(false),
|
quitting(false),
|
||||||
|
@ -739,7 +733,6 @@ RunModule(JSContext* cx, const char* filename, FILE* file, bool compileOnly)
|
||||||
return JS_CallFunction(cx, loaderObj, importFun, args, &value);
|
return JS_CallFunction(cx, loaderObj, importFun, args, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
static JSObject*
|
static JSObject*
|
||||||
ShellGetIncumbentGlobalCallback(JSContext* cx)
|
ShellGetIncumbentGlobalCallback(JSContext* cx)
|
||||||
{
|
{
|
||||||
|
@ -776,12 +769,10 @@ ShellFinishAsyncTaskCallback(JS::AsyncTask* task)
|
||||||
asyncTasks->outstanding--;
|
asyncTasks->outstanding--;
|
||||||
return asyncTasks->finished.append(task);
|
return asyncTasks->finished.append(task);
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
DrainJobQueue(JSContext* cx)
|
DrainJobQueue(JSContext* cx)
|
||||||
{
|
{
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
ShellContext* sc = GetShellContext(cx);
|
ShellContext* sc = GetShellContext(cx);
|
||||||
if (sc->quitting || sc->drainingJobQueue)
|
if (sc->quitting || sc->drainingJobQueue)
|
||||||
return true;
|
return true;
|
||||||
|
@ -832,7 +823,6 @@ DrainJobQueue(JSContext* cx)
|
||||||
}
|
}
|
||||||
sc->jobQueue.clear();
|
sc->jobQueue.clear();
|
||||||
sc->drainingJobQueue = false;
|
sc->drainingJobQueue = false;
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,7 +837,6 @@ DrainJobQueue(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
static void
|
static void
|
||||||
ForwardingPromiseRejectionTrackerCallback(JSContext* cx, JS::HandleObject promise,
|
ForwardingPromiseRejectionTrackerCallback(JSContext* cx, JS::HandleObject promise,
|
||||||
PromiseRejectionHandlingState state, void* data)
|
PromiseRejectionHandlingState state, void* data)
|
||||||
|
@ -870,14 +859,12 @@ ForwardingPromiseRejectionTrackerCallback(JSContext* cx, JS::HandleObject promis
|
||||||
if (!Call(cx, callback, UndefinedHandleValue, args, &rval))
|
if (!Call(cx, callback, UndefinedHandleValue, args, &rval))
|
||||||
JS_ClearPendingException(cx);
|
JS_ClearPendingException(cx);
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
SetPromiseRejectionTrackerCallback(JSContext* cx, unsigned argc, Value* vp)
|
SetPromiseRejectionTrackerCallback(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
if (!IsCallable(args.get(0))) {
|
if (!IsCallable(args.get(0))) {
|
||||||
JS_ReportErrorASCII(cx,
|
JS_ReportErrorASCII(cx,
|
||||||
"setPromiseRejectionTrackerCallback expects a function as its sole "
|
"setPromiseRejectionTrackerCallback expects a function as its sole "
|
||||||
|
@ -888,7 +875,6 @@ SetPromiseRejectionTrackerCallback(JSContext* cx, unsigned argc, Value* vp)
|
||||||
GetShellContext(cx)->promiseRejectionTrackerCallback = args[0];
|
GetShellContext(cx)->promiseRejectionTrackerCallback = args[0];
|
||||||
JS::SetPromiseRejectionTrackerCallback(cx, ForwardingPromiseRejectionTrackerCallback);
|
JS::SetPromiseRejectionTrackerCallback(cx, ForwardingPromiseRejectionTrackerCallback);
|
||||||
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
args.rval().setUndefined();
|
args.rval().setUndefined();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3349,12 +3335,10 @@ WorkerMain(void* arg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
sc->jobQueue.init(cx, JobQueue(SystemAllocPolicy()));
|
sc->jobQueue.init(cx, JobQueue(SystemAllocPolicy()));
|
||||||
JS::SetEnqueuePromiseJobCallback(cx, ShellEnqueuePromiseJobCallback);
|
JS::SetEnqueuePromiseJobCallback(cx, ShellEnqueuePromiseJobCallback);
|
||||||
JS::SetGetIncumbentGlobalCallback(cx, ShellGetIncumbentGlobalCallback);
|
JS::SetGetIncumbentGlobalCallback(cx, ShellGetIncumbentGlobalCallback);
|
||||||
JS::SetAsyncTaskCallbacks(cx, ShellStartAsyncTaskCallback, ShellFinishAsyncTaskCallback);
|
JS::SetAsyncTaskCallbacks(cx, ShellStartAsyncTaskCallback, ShellFinishAsyncTaskCallback);
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
EnvironmentPreparer environmentPreparer(cx);
|
EnvironmentPreparer environmentPreparer(cx);
|
||||||
|
|
||||||
|
@ -3385,11 +3369,9 @@ WorkerMain(void* arg)
|
||||||
|
|
||||||
JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr);
|
JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr);
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
JS::SetGetIncumbentGlobalCallback(cx, nullptr);
|
JS::SetGetIncumbentGlobalCallback(cx, nullptr);
|
||||||
JS::SetEnqueuePromiseJobCallback(cx, nullptr);
|
JS::SetEnqueuePromiseJobCallback(cx, nullptr);
|
||||||
sc->jobQueue.reset();
|
sc->jobQueue.reset();
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
KillWatchdog(cx);
|
KillWatchdog(cx);
|
||||||
|
|
||||||
|
@ -7945,12 +7927,10 @@ main(int argc, char** argv, char** envp)
|
||||||
if (!JS::InitSelfHostedCode(cx))
|
if (!JS::InitSelfHostedCode(cx))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
sc->jobQueue.init(cx, JobQueue(SystemAllocPolicy()));
|
sc->jobQueue.init(cx, JobQueue(SystemAllocPolicy()));
|
||||||
JS::SetEnqueuePromiseJobCallback(cx, ShellEnqueuePromiseJobCallback);
|
JS::SetEnqueuePromiseJobCallback(cx, ShellEnqueuePromiseJobCallback);
|
||||||
JS::SetGetIncumbentGlobalCallback(cx, ShellGetIncumbentGlobalCallback);
|
JS::SetGetIncumbentGlobalCallback(cx, ShellGetIncumbentGlobalCallback);
|
||||||
JS::SetAsyncTaskCallbacks(cx, ShellStartAsyncTaskCallback, ShellFinishAsyncTaskCallback);
|
JS::SetAsyncTaskCallbacks(cx, ShellStartAsyncTaskCallback, ShellFinishAsyncTaskCallback);
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
EnvironmentPreparer environmentPreparer(cx);
|
EnvironmentPreparer environmentPreparer(cx);
|
||||||
|
|
||||||
|
@ -7980,11 +7960,9 @@ main(int argc, char** argv, char** envp)
|
||||||
|
|
||||||
JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr);
|
JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr);
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
JS::SetGetIncumbentGlobalCallback(cx, nullptr);
|
JS::SetGetIncumbentGlobalCallback(cx, nullptr);
|
||||||
JS::SetEnqueuePromiseJobCallback(cx, nullptr);
|
JS::SetEnqueuePromiseJobCallback(cx, nullptr);
|
||||||
sc->jobQueue.reset();
|
sc->jobQueue.reset();
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
KillWatchdog(cx);
|
KillWatchdog(cx);
|
||||||
|
|
||||||
|
|
|
@ -8728,7 +8728,6 @@ DebuggerObject::proxyHandlerGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
DebuggerObject::isPromiseGetter(JSContext* cx, unsigned argc, Value* vp)
|
DebuggerObject::isPromiseGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
@ -8897,7 +8896,6 @@ DebuggerObject::promiseDependentPromisesGetter(JSContext* cx, unsigned argc, Val
|
||||||
args.rval().setObject(*promises);
|
args.rval().setObject(*promises);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
DebuggerObject::isExtensibleMethod(JSContext* cx, unsigned argc, Value* vp)
|
DebuggerObject::isExtensibleMethod(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
@ -9336,7 +9334,6 @@ const JSPropertySpec DebuggerObject::properties_[] = {
|
||||||
JS_PS_END
|
JS_PS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
const JSPropertySpec DebuggerObject::promiseProperties_[] = {
|
const JSPropertySpec DebuggerObject::promiseProperties_[] = {
|
||||||
JS_PSG("isPromise", DebuggerObject::isPromiseGetter, 0),
|
JS_PSG("isPromise", DebuggerObject::isPromiseGetter, 0),
|
||||||
JS_PSG("promiseState", DebuggerObject::promiseStateGetter, 0),
|
JS_PSG("promiseState", DebuggerObject::promiseStateGetter, 0),
|
||||||
|
@ -9350,7 +9347,6 @@ const JSPropertySpec DebuggerObject::promiseProperties_[] = {
|
||||||
JS_PSG("promiseDependentPromises", DebuggerObject::promiseDependentPromisesGetter, 0),
|
JS_PSG("promiseDependentPromises", DebuggerObject::promiseDependentPromisesGetter, 0),
|
||||||
JS_PS_END
|
JS_PS_END
|
||||||
};
|
};
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
const JSFunctionSpec DebuggerObject::methods_[] = {
|
const JSFunctionSpec DebuggerObject::methods_[] = {
|
||||||
JS_FN("isExtensible", DebuggerObject::isExtensibleMethod, 0, 0),
|
JS_FN("isExtensible", DebuggerObject::isExtensibleMethod, 0, 0),
|
||||||
|
@ -9390,10 +9386,8 @@ DebuggerObject::initClass(JSContext* cx, HandleObject obj, HandleObject debugCto
|
||||||
if (!objectProto)
|
if (!objectProto)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
if (!DefinePropertiesAndFunctions(cx, objectProto, promiseProperties_, nullptr))
|
if (!DefinePropertiesAndFunctions(cx, objectProto, promiseProperties_, nullptr))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
return objectProto;
|
return objectProto;
|
||||||
}
|
}
|
||||||
|
@ -9461,7 +9455,6 @@ DebuggerObject::isScriptedProxy() const
|
||||||
return js::IsScriptedProxy(referent());
|
return js::IsScriptedProxy(referent());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
bool
|
bool
|
||||||
DebuggerObject::isPromise() const
|
DebuggerObject::isPromise() const
|
||||||
{
|
{
|
||||||
|
@ -9475,7 +9468,6 @@ DebuggerObject::isPromise() const
|
||||||
|
|
||||||
return referent->is<PromiseObject>();
|
return referent->is<PromiseObject>();
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
DebuggerObject::getClassName(JSContext* cx, HandleDebuggerObject object,
|
DebuggerObject::getClassName(JSContext* cx, HandleDebuggerObject object,
|
||||||
|
@ -9758,7 +9750,6 @@ DebuggerObject::getErrorColumnNumber(JSContext* cx, HandleDebuggerObject object,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
DebuggerObject::getPromiseValue(JSContext* cx, HandleDebuggerObject object,
|
DebuggerObject::getPromiseValue(JSContext* cx, HandleDebuggerObject object,
|
||||||
MutableHandleValue result)
|
MutableHandleValue result)
|
||||||
|
@ -9778,7 +9769,6 @@ DebuggerObject::getPromiseReason(JSContext* cx, HandleDebuggerObject object,
|
||||||
result.set(object->promise()->reason());
|
result.set(object->promise()->reason());
|
||||||
return object->owner()->wrapDebuggeeValue(cx, result);
|
return object->owner()->wrapDebuggeeValue(cx, result);
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
DebuggerObject::isExtensible(JSContext* cx, HandleDebuggerObject object, bool& result)
|
DebuggerObject::isExtensible(JSContext* cx, HandleDebuggerObject object, bool& result)
|
||||||
|
@ -10248,7 +10238,6 @@ DebuggerObject::requireGlobal(JSContext* cx, HandleDebuggerObject object)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
DebuggerObject::requirePromise(JSContext* cx, HandleDebuggerObject object)
|
DebuggerObject::requirePromise(JSContext* cx, HandleDebuggerObject object)
|
||||||
{
|
{
|
||||||
|
@ -10270,7 +10259,6 @@ DebuggerObject::requirePromise(JSContext* cx, HandleDebuggerObject object)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
DebuggerObject::getScriptedProxyTarget(JSContext* cx, HandleDebuggerObject object,
|
DebuggerObject::getScriptedProxyTarget(JSContext* cx, HandleDebuggerObject object,
|
||||||
|
|
|
@ -1256,12 +1256,10 @@ class DebuggerObject : public NativeObject
|
||||||
MutableHandleDebuggerObject result);
|
MutableHandleDebuggerObject result);
|
||||||
static MOZ_MUST_USE bool getScriptedProxyHandler(JSContext* cx, HandleDebuggerObject object,
|
static MOZ_MUST_USE bool getScriptedProxyHandler(JSContext* cx, HandleDebuggerObject object,
|
||||||
MutableHandleDebuggerObject result);
|
MutableHandleDebuggerObject result);
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
static MOZ_MUST_USE bool getPromiseValue(JSContext* cx, HandleDebuggerObject object,
|
static MOZ_MUST_USE bool getPromiseValue(JSContext* cx, HandleDebuggerObject object,
|
||||||
MutableHandleValue result);
|
MutableHandleValue result);
|
||||||
static MOZ_MUST_USE bool getPromiseReason(JSContext* cx, HandleDebuggerObject object,
|
static MOZ_MUST_USE bool getPromiseReason(JSContext* cx, HandleDebuggerObject object,
|
||||||
MutableHandleValue result);
|
MutableHandleValue result);
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
static MOZ_MUST_USE bool isExtensible(JSContext* cx, HandleDebuggerObject object,
|
static MOZ_MUST_USE bool isExtensible(JSContext* cx, HandleDebuggerObject object,
|
||||||
|
@ -1311,16 +1309,12 @@ class DebuggerObject : public NativeObject
|
||||||
bool isArrowFunction() const;
|
bool isArrowFunction() const;
|
||||||
bool isGlobal() const;
|
bool isGlobal() const;
|
||||||
bool isScriptedProxy() const;
|
bool isScriptedProxy() const;
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
bool isPromise() const;
|
bool isPromise() const;
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
JSAtom* name() const;
|
JSAtom* name() const;
|
||||||
JSAtom* displayName() const;
|
JSAtom* displayName() const;
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
JS::PromiseState promiseState() const;
|
JS::PromiseState promiseState() const;
|
||||||
double promiseLifetime() const;
|
double promiseLifetime() const;
|
||||||
double promiseTimeToResolution() const;
|
double promiseTimeToResolution() const;
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
|
@ -1332,9 +1326,7 @@ class DebuggerObject : public NativeObject
|
||||||
static const ClassOps classOps_;
|
static const ClassOps classOps_;
|
||||||
|
|
||||||
static const JSPropertySpec properties_[];
|
static const JSPropertySpec properties_[];
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
static const JSPropertySpec promiseProperties_[];
|
static const JSPropertySpec promiseProperties_[];
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
static const JSFunctionSpec methods_[];
|
static const JSFunctionSpec methods_[];
|
||||||
|
|
||||||
JSObject* referent() const {
|
JSObject* referent() const {
|
||||||
|
@ -1345,14 +1337,10 @@ class DebuggerObject : public NativeObject
|
||||||
|
|
||||||
Debugger* owner() const;
|
Debugger* owner() const;
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
PromiseObject* promise() const;
|
PromiseObject* promise() const;
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
static MOZ_MUST_USE bool requireGlobal(JSContext* cx, HandleDebuggerObject object);
|
static MOZ_MUST_USE bool requireGlobal(JSContext* cx, HandleDebuggerObject object);
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
static MOZ_MUST_USE bool requirePromise(JSContext* cx, HandleDebuggerObject object);
|
static MOZ_MUST_USE bool requirePromise(JSContext* cx, HandleDebuggerObject object);
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
|
||||||
|
@ -1379,7 +1367,6 @@ class DebuggerObject : public NativeObject
|
||||||
static MOZ_MUST_USE bool isProxyGetter(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool isProxyGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool proxyTargetGetter(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool proxyTargetGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool proxyHandlerGetter(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool proxyHandlerGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
static MOZ_MUST_USE bool isPromiseGetter(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool isPromiseGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool promiseStateGetter(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool promiseStateGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool promiseValueGetter(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool promiseValueGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
@ -1390,7 +1377,6 @@ class DebuggerObject : public NativeObject
|
||||||
static MOZ_MUST_USE bool promiseResolutionSiteGetter(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool promiseResolutionSiteGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool promiseIDGetter(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool promiseIDGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
static MOZ_MUST_USE bool promiseDependentPromisesGetter(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool promiseDependentPromisesGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
// JSNative methods
|
// JSNative methods
|
||||||
static MOZ_MUST_USE bool isExtensibleMethod(JSContext* cx, unsigned argc, Value* vp);
|
static MOZ_MUST_USE bool isExtensibleMethod(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
|
|
@ -21,9 +21,7 @@
|
||||||
#include "builtin/MapObject.h"
|
#include "builtin/MapObject.h"
|
||||||
#include "builtin/ModuleObject.h"
|
#include "builtin/ModuleObject.h"
|
||||||
#include "builtin/Object.h"
|
#include "builtin/Object.h"
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
#include "builtin/Promise.h"
|
#include "builtin/Promise.h"
|
||||||
#endif
|
|
||||||
#include "builtin/RegExp.h"
|
#include "builtin/RegExp.h"
|
||||||
#include "builtin/SelfHostingDefines.h"
|
#include "builtin/SelfHostingDefines.h"
|
||||||
#include "builtin/SymbolObject.h"
|
#include "builtin/SymbolObject.h"
|
||||||
|
|
|
@ -1640,7 +1640,6 @@ WebAssembly_toSource(JSContext* cx, unsigned argc, Value* vp)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
static bool
|
static bool
|
||||||
Nop(JSContext* cx, unsigned argc, Value* vp)
|
Nop(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
@ -1914,7 +1913,6 @@ WebAssembly_instantiate(JSContext* cx, unsigned argc, Value* vp)
|
||||||
callArgs.rval().setObject(*promise);
|
callArgs.rval().setObject(*promise);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
WebAssembly_validate(JSContext* cx, unsigned argc, Value* vp)
|
WebAssembly_validate(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
@ -1949,10 +1947,8 @@ static const JSFunctionSpec WebAssembly_static_methods[] =
|
||||||
#if JS_HAS_TOSOURCE
|
#if JS_HAS_TOSOURCE
|
||||||
JS_FN(js_toSource_str, WebAssembly_toSource, 0, 0),
|
JS_FN(js_toSource_str, WebAssembly_toSource, 0, 0),
|
||||||
#endif
|
#endif
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
JS_FN("compile", WebAssembly_compile, 1, 0),
|
JS_FN("compile", WebAssembly_compile, 1, 0),
|
||||||
JS_FN("instantiate", WebAssembly_instantiate, 2, 0),
|
JS_FN("instantiate", WebAssembly_instantiate, 2, 0),
|
||||||
#endif
|
|
||||||
JS_FN("validate", WebAssembly_validate, 1, 0),
|
JS_FN("validate", WebAssembly_validate, 1, 0),
|
||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
|
@ -1206,13 +1206,6 @@ xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prin
|
||||||
|
|
||||||
if (!options.globalProperties.DefineInSandbox(cx, sandbox))
|
if (!options.globalProperties.DefineInSandbox(cx, sandbox))
|
||||||
return NS_ERROR_XPC_UNEXPECTED;
|
return NS_ERROR_XPC_UNEXPECTED;
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
// Promise is supposed to be part of ES, and therefore should appear on
|
|
||||||
// every global.
|
|
||||||
if (!dom::PromiseBinding::GetConstructorObject(cx))
|
|
||||||
return NS_ERROR_XPC_UNEXPECTED;
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We handle the case where the context isn't in a compartment for the
|
// We handle the case where the context isn't in a compartment for the
|
||||||
|
|
|
@ -799,7 +799,6 @@ XPCConvert::NativeInterface2JSObject(MutableHandleValue d,
|
||||||
return CreateHolderIfNeeded(flat, d, dest);
|
return CreateHolderIfNeeded(flat, d, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
if (iid->Equals(NS_GET_IID(nsISupports))) {
|
if (iid->Equals(NS_GET_IID(nsISupports))) {
|
||||||
// Check for a Promise being returned via nsISupports. In that
|
// Check for a Promise being returned via nsISupports. In that
|
||||||
// situation, we want to dig out its underlying JS object and return
|
// situation, we want to dig out its underlying JS object and return
|
||||||
|
@ -812,7 +811,6 @@ XPCConvert::NativeInterface2JSObject(MutableHandleValue d,
|
||||||
return CreateHolderIfNeeded(flat, d, dest);
|
return CreateHolderIfNeeded(flat, d, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
// Don't double wrap CPOWs. This is a temporary measure for compatibility
|
// Don't double wrap CPOWs. This is a temporary measure for compatibility
|
||||||
// with objects that don't provide necessary QIs (such as objects under
|
// with objects that don't provide necessary QIs (such as objects under
|
||||||
|
@ -955,7 +953,6 @@ XPCConvert::JSObject2NativeInterface(void** dest, HandleObject src,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
// Deal with Promises being passed as nsISupports. In that situation we
|
// Deal with Promises being passed as nsISupports. In that situation we
|
||||||
// want to create a dom::Promise and use that.
|
// want to create a dom::Promise and use that.
|
||||||
if (iid->Equals(NS_GET_IID(nsISupports))) {
|
if (iid->Equals(NS_GET_IID(nsISupports))) {
|
||||||
|
@ -966,7 +963,6 @@ XPCConvert::JSObject2NativeInterface(void** dest, HandleObject src,
|
||||||
return p && NS_SUCCEEDED(p->QueryInterface(*iid, dest));
|
return p && NS_SUCCEEDED(p->QueryInterface(*iid, dest));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<nsXPCWrappedJS> wrapper;
|
RefPtr<nsXPCWrappedJS> wrapper;
|
||||||
|
|
|
@ -91,7 +91,6 @@ def build_dict(config, env=os.environ):
|
||||||
d['addon_signing'] = substs.get('MOZ_ADDON_SIGNING') == '1'
|
d['addon_signing'] = substs.get('MOZ_ADDON_SIGNING') == '1'
|
||||||
d['require_signing'] = substs.get('MOZ_REQUIRE_SIGNING') == '1'
|
d['require_signing'] = substs.get('MOZ_REQUIRE_SIGNING') == '1'
|
||||||
d['official'] = bool(substs.get('MC_OFFICIAL'))
|
d['official'] = bool(substs.get('MC_OFFICIAL'))
|
||||||
d['sm_promise'] = bool(substs.get('SPIDERMONKEY_PROMISE'))
|
|
||||||
|
|
||||||
def guess_platform():
|
def guess_platform():
|
||||||
if d['buildapp'] in ('browser', 'mulet'):
|
if d['buildapp'] in ('browser', 'mulet'):
|
||||||
|
|
|
@ -468,10 +468,8 @@ CycleCollectedJSContext::~CycleCollectedJSContext()
|
||||||
MOZ_ASSERT(mDebuggerPromiseMicroTaskQueue.empty());
|
MOZ_ASSERT(mDebuggerPromiseMicroTaskQueue.empty());
|
||||||
MOZ_ASSERT(mPromiseMicroTaskQueue.empty());
|
MOZ_ASSERT(mPromiseMicroTaskQueue.empty());
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
mUncaughtRejections.reset();
|
mUncaughtRejections.reset();
|
||||||
mConsumedRejections.reset();
|
mConsumedRejections.reset();
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
JS_DestroyContext(mJSContext);
|
JS_DestroyContext(mJSContext);
|
||||||
mJSContext = nullptr;
|
mJSContext = nullptr;
|
||||||
|
@ -544,12 +542,10 @@ CycleCollectedJSContext::Initialize(JSContext* aParentContext,
|
||||||
|
|
||||||
JS::SetGetIncumbentGlobalCallback(mJSContext, GetIncumbentGlobalCallback);
|
JS::SetGetIncumbentGlobalCallback(mJSContext, GetIncumbentGlobalCallback);
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
JS::SetEnqueuePromiseJobCallback(mJSContext, EnqueuePromiseJobCallback, this);
|
JS::SetEnqueuePromiseJobCallback(mJSContext, EnqueuePromiseJobCallback, this);
|
||||||
JS::SetPromiseRejectionTrackerCallback(mJSContext, PromiseRejectionTrackerCallback, this);
|
JS::SetPromiseRejectionTrackerCallback(mJSContext, PromiseRejectionTrackerCallback, this);
|
||||||
mUncaughtRejections.init(mJSContext, JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(js::SystemAllocPolicy()));
|
mUncaughtRejections.init(mJSContext, JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(js::SystemAllocPolicy()));
|
||||||
mConsumedRejections.init(mJSContext, JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(js::SystemAllocPolicy()));
|
mConsumedRejections.init(mJSContext, JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(js::SystemAllocPolicy()));
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
JS::dbg::SetDebuggerMallocSizeOf(mJSContext, moz_malloc_size_of);
|
JS::dbg::SetDebuggerMallocSizeOf(mJSContext, moz_malloc_size_of);
|
||||||
|
|
||||||
|
@ -975,7 +971,6 @@ CycleCollectedJSContext::EnqueuePromiseJobCallback(JSContext* aCx,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
/* static */
|
/* static */
|
||||||
void
|
void
|
||||||
CycleCollectedJSContext::PromiseRejectionTrackerCallback(JSContext* aCx,
|
CycleCollectedJSContext::PromiseRejectionTrackerCallback(JSContext* aCx,
|
||||||
|
@ -995,7 +990,6 @@ CycleCollectedJSContext::PromiseRejectionTrackerCallback(JSContext* aCx,
|
||||||
PromiseDebugging::AddConsumedRejection(aPromise);
|
PromiseDebugging::AddConsumedRejection(aPromise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
struct JsGcTracer : public TraceCallbacks
|
struct JsGcTracer : public TraceCallbacks
|
||||||
{
|
{
|
||||||
|
|
|
@ -224,12 +224,10 @@ private:
|
||||||
JS::HandleObject aAllocationSite,
|
JS::HandleObject aAllocationSite,
|
||||||
JS::HandleObject aIncumbentGlobal,
|
JS::HandleObject aIncumbentGlobal,
|
||||||
void* aData);
|
void* aData);
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
static void PromiseRejectionTrackerCallback(JSContext* aCx,
|
static void PromiseRejectionTrackerCallback(JSContext* aCx,
|
||||||
JS::HandleObject aPromise,
|
JS::HandleObject aPromise,
|
||||||
PromiseRejectionHandlingState state,
|
PromiseRejectionHandlingState state,
|
||||||
void* aData);
|
void* aData);
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
virtual void TraceNativeBlackRoots(JSTracer* aTracer) { };
|
virtual void TraceNativeBlackRoots(JSTracer* aTracer) { };
|
||||||
void TraceNativeGrayRoots(JSTracer* aTracer);
|
void TraceNativeGrayRoots(JSTracer* aTracer);
|
||||||
|
@ -406,7 +404,7 @@ public:
|
||||||
|
|
||||||
// Storage for watching rejected promises waiting for some client to
|
// Storage for watching rejected promises waiting for some client to
|
||||||
// consume their rejection.
|
// consume their rejection.
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
|
||||||
// Promises in this list have been rejected in the last turn of the
|
// Promises in this list have been rejected in the last turn of the
|
||||||
// event loop without the rejection being handled.
|
// event loop without the rejection being handled.
|
||||||
// Note that this can contain nullptrs in place of promises removed because
|
// Note that this can contain nullptrs in place of promises removed because
|
||||||
|
@ -417,13 +415,7 @@ public:
|
||||||
// (because they were in the above list), but the rejection was handled
|
// (because they were in the above list), but the rejection was handled
|
||||||
// in the last turn of the event loop.
|
// in the last turn of the event loop.
|
||||||
JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>> mConsumedRejections;
|
JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>> mConsumedRejections;
|
||||||
#else
|
|
||||||
// We store values as `nsISupports` to avoid adding compile-time dependencies
|
|
||||||
// from xpcom to dom/promise, but they can really only have a single concrete
|
|
||||||
// type.
|
|
||||||
nsTArray<nsCOMPtr<nsISupports /* Promise */>> mUncaughtRejections;
|
|
||||||
nsTArray<nsCOMPtr<nsISupports /* Promise */ >> mConsumedRejections;
|
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
nsTArray<nsCOMPtr<nsISupports /* UncaughtRejectionObserver */ >> mUncaughtRejectionObservers;
|
nsTArray<nsCOMPtr<nsISupports /* UncaughtRejectionObserver */ >> mUncaughtRejectionObservers;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue