mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1170760 part 12. Rip out the promise-resolved-with-promise fast path. r=baku
This commit is contained in:
parent
44566b8a83
commit
f07e814e4e
@ -9149,26 +9149,6 @@ class CGStaticMethodJitinfo(CGGeneric):
|
|||||||
IDLToCIdentifier(method.identifier.name))))
|
IDLToCIdentifier(method.identifier.name))))
|
||||||
|
|
||||||
|
|
||||||
class CGMethodIdentityTest(CGAbstractMethod):
|
|
||||||
"""
|
|
||||||
A class to generate a method-identity test for a given IDL operation.
|
|
||||||
"""
|
|
||||||
def __init__(self, descriptor, method):
|
|
||||||
self.method = method
|
|
||||||
name = "Is%sMethod" % MakeNativeName(method.identifier.name)
|
|
||||||
CGAbstractMethod.__init__(self, descriptor, name, 'bool',
|
|
||||||
[Argument('JS::Handle<JSObject*>', 'aObj')])
|
|
||||||
|
|
||||||
def definition_body(self):
|
|
||||||
return dedent(
|
|
||||||
"""
|
|
||||||
MOZ_ASSERT(aObj);
|
|
||||||
return js::IsFunctionObject(aObj) &&
|
|
||||||
js::FunctionObjectIsNative(aObj) &&
|
|
||||||
FUNCTION_VALUE_TO_JITINFO(JS::ObjectValue(*aObj)) == &%s_methodinfo;
|
|
||||||
""" % IDLToCIdentifier(self.method.identifier.name))
|
|
||||||
|
|
||||||
|
|
||||||
def getEnumValueName(value):
|
def getEnumValueName(value):
|
||||||
# Some enum values can be empty strings. Others might have weird
|
# Some enum values can be empty strings. Others might have weird
|
||||||
# characters in them. Deal with the former by returning "_empty",
|
# characters in them. Deal with the former by returning "_empty",
|
||||||
@ -11800,8 +11780,6 @@ class CGDescriptor(CGThing):
|
|||||||
cgThings.append(CGMemberJITInfo(descriptor, m))
|
cgThings.append(CGMemberJITInfo(descriptor, m))
|
||||||
if props.isCrossOriginMethod:
|
if props.isCrossOriginMethod:
|
||||||
crossOriginMethods.add(m.identifier.name)
|
crossOriginMethods.add(m.identifier.name)
|
||||||
if m.getExtendedAttribute("MethodIdentityTestable"):
|
|
||||||
cgThings.append(CGMethodIdentityTest(descriptor, m))
|
|
||||||
# If we've hit the maplike/setlike member itself, go ahead and
|
# If we've hit the maplike/setlike member itself, go ahead and
|
||||||
# generate its convenience functions.
|
# generate its convenience functions.
|
||||||
elif m.isMaplikeOrSetlike():
|
elif m.isMaplikeOrSetlike():
|
||||||
|
@ -4805,7 +4805,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
|||||||
identifier == "CheckAnyPermissions" or
|
identifier == "CheckAnyPermissions" or
|
||||||
identifier == "CheckAllPermissions" or
|
identifier == "CheckAllPermissions" or
|
||||||
identifier == "BinaryName" or
|
identifier == "BinaryName" or
|
||||||
identifier == "MethodIdentityTestable" or
|
|
||||||
identifier == "StaticClassOverride"):
|
identifier == "StaticClassOverride"):
|
||||||
# Known attributes that we don't need to do anything with here
|
# Known attributes that we don't need to do anything with here
|
||||||
pass
|
pass
|
||||||
|
@ -278,48 +278,6 @@ private:
|
|||||||
NS_DECL_OWNINGTHREAD;
|
NS_DECL_OWNINGTHREAD;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fast version of PromiseResolveThenableJob for use in the cases when we know we're
|
|
||||||
// calling the canonical Promise.prototype.then on an actual DOM Promise. In
|
|
||||||
// that case we can just bypass the jumping into and out of JS and call
|
|
||||||
// AppendCallbacks on that promise directly.
|
|
||||||
class FastPromiseResolveThenableJob final : public nsRunnable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FastPromiseResolveThenableJob(PromiseCallback* aResolveCallback,
|
|
||||||
PromiseCallback* aRejectCallback,
|
|
||||||
Promise* aNextPromise)
|
|
||||||
: mResolveCallback(aResolveCallback)
|
|
||||||
, mRejectCallback(aRejectCallback)
|
|
||||||
, mNextPromise(aNextPromise)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aResolveCallback);
|
|
||||||
MOZ_ASSERT(aRejectCallback);
|
|
||||||
MOZ_ASSERT(aNextPromise);
|
|
||||||
MOZ_COUNT_CTOR(FastPromiseResolveThenableJob);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual
|
|
||||||
~FastPromiseResolveThenableJob()
|
|
||||||
{
|
|
||||||
NS_ASSERT_OWNINGTHREAD(FastPromiseResolveThenableJob);
|
|
||||||
MOZ_COUNT_DTOR(FastPromiseResolveThenableJob);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
NS_IMETHOD
|
|
||||||
Run() override
|
|
||||||
{
|
|
||||||
NS_ASSERT_OWNINGTHREAD(FastPromiseResolveThenableJob);
|
|
||||||
mNextPromise->AppendCallbacks(mResolveCallback, mRejectCallback);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
RefPtr<PromiseCallback> mResolveCallback;
|
|
||||||
RefPtr<PromiseCallback> mRejectCallback;
|
|
||||||
RefPtr<Promise> mNextPromise;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A struct implementing
|
// A struct implementing
|
||||||
// <http://www.ecma-international.org/ecma-262/6.0/#sec-promisecapability-records>.
|
// <http://www.ecma-international.org/ecma-262/6.0/#sec-promisecapability-records>.
|
||||||
// While the spec holds on to these in some places, in practice those places
|
// While the spec holds on to these in some places, in practice those places
|
||||||
@ -2018,35 +1976,25 @@ Promise::ResolveInternal(JSContext* aCx,
|
|||||||
// This is the then() function of the thenable aValueObj.
|
// This is the then() function of the thenable aValueObj.
|
||||||
JS::Rooted<JSObject*> thenObj(aCx, &then.toObject());
|
JS::Rooted<JSObject*> thenObj(aCx, &then.toObject());
|
||||||
|
|
||||||
// Add a fast path for the case when we're resolved with an actual
|
// We used to have a fast path here for the case when the following
|
||||||
// Promise. This has two requirements:
|
// requirements held:
|
||||||
//
|
//
|
||||||
// 1) valueObj is a Promise.
|
// 1) valueObj is a Promise.
|
||||||
// 2) thenObj is a JSFunction backed by our actual Promise::Then
|
// 2) thenObj is a JSFunction backed by our actual Promise::Then
|
||||||
// implementation.
|
// implementation.
|
||||||
//
|
//
|
||||||
// If those requirements are satisfied, then we know exactly what
|
// But now that we're doing subclassing in Promise.prototype.then we would
|
||||||
// thenObj.call(valueObj) will do, so we can optimize a bit and avoid ever
|
// also need the following requirements:
|
||||||
// entering JS for this stuff.
|
//
|
||||||
Promise* nextPromise;
|
// 3) Getting valueObj.constructor has no side-effects.
|
||||||
if (PromiseBinding::IsThenMethod(thenObj) &&
|
// 4) Getting valueObj.constructor[@@species] has no side-effects.
|
||||||
NS_SUCCEEDED(UNWRAP_OBJECT(Promise, valueObj, nextPromise))) {
|
// 5) valueObj.constructor[@@species] is a function and calling it has no
|
||||||
// If we were taking the codepath that involves PromiseResolveThenableJob and
|
// side-effects (e.g. it's the canonical Promise constructor) and it
|
||||||
// PromiseInit below, then eventually, in PromiseResolveThenableJob::Run, we
|
// provides some callback functions to call as arguments to its
|
||||||
// would create some JSFunctions in the compartment of
|
// argument.
|
||||||
// this->GetWrapper() and pass them to the PromiseInit. So by the time
|
//
|
||||||
// we'd see the resolution value it would be wrapped into the
|
// Ensuring that stuff while not inside SpiderMonkey is painful, so let's
|
||||||
// compartment of this->GetWrapper(). The global of that compartment is
|
// drop the fast path for now.
|
||||||
// this->GetGlobalJSObject(), so use that as the global for
|
|
||||||
// ResolvePromiseCallback/RejectPromiseCallback.
|
|
||||||
JS::Rooted<JSObject*> glob(aCx, GlobalJSObject());
|
|
||||||
RefPtr<PromiseCallback> resolveCb = new ResolvePromiseCallback(this, glob);
|
|
||||||
RefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(this, glob);
|
|
||||||
RefPtr<FastPromiseResolveThenableJob> task =
|
|
||||||
new FastPromiseResolveThenableJob(resolveCb, rejectCb, nextPromise);
|
|
||||||
DispatchToMicroTask(task);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PromiseInit> thenCallback =
|
RefPtr<PromiseInit> thenCallback =
|
||||||
new PromiseInit(nullptr, thenObj, mozilla::dom::GetIncumbentGlobal());
|
new PromiseInit(nullptr, thenObj, mozilla::dom::GetIncumbentGlobal());
|
||||||
|
@ -30,7 +30,7 @@ interface _Promise {
|
|||||||
|
|
||||||
// The [TreatNonCallableAsNull] annotation is required since then() should do
|
// The [TreatNonCallableAsNull] annotation is required since then() should do
|
||||||
// nothing instead of throwing errors when non-callable arguments are passed.
|
// nothing instead of throwing errors when non-callable arguments are passed.
|
||||||
[NewObject, MethodIdentityTestable]
|
[NewObject]
|
||||||
Promise<any> then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
|
Promise<any> then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
|
||||||
[TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
|
[TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user