Closed
Bug 1243001
Opened 9 years ago
Closed 9 years ago
Implement DOM support for moving Promise into SpiderMonkey
Categories
(Core :: DOM: Core & HTML, defect)
Core
DOM: Core & HTML
Tracking
()
RESOLVED
FIXED
mozilla47
| Tracking | Status | |
|---|---|---|
| firefox47 | --- | fixed |
People
(Reporter: bzbarsky, Assigned: bzbarsky)
References
Details
Attachments
(9 files, 6 obsolete files)
|
1.77 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
|
7.96 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
|
9.71 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
|
2.05 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
|
5.96 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
|
32.38 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
|
8.01 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
|
1.39 KB,
patch
|
bzbarsky
:
review+
|
Details | Diff | Splinter Review |
|
29.99 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
This is the DOM side of bug 911216.
The general plan of attack is the following. We're going to introduce a SPIDERMONKEY_PROMISE compile-time define which we can use to turn on SpiderMonkey promises. We can also use it to turn them off (e.g. on Aurora/Beta) if it turns out there are problems. For a bit we'll support both modes of operation, by conditioning parts of our Promise impl on this define. Once we've successfully shipped SpiderMonkey promises, we will remove the dead #ifndef SPIDERMONKEY_PROMISE code and probably do a bit more simplification of the Promise bits after that.
An alternative would be to have a totally separate Promise.h/Promise.cpp if SPIDERMONKEY_PROMISE is defined instead of doing ifdefs in a single file. I could do that if people prefer; in the end it turned out that the two Promise versions don't share _that_ much with each other.... There might be a bit more complication with vcs blame this way, of course. Just let me know.
Anyway, the new setup generally works like this: a dom::Promise just points to a SpiderMonkey Promise and delegates everything to it. Creation of a dom::Promise either requires passing in an existing SpiderMonkey Promise or cross-compartment wrapper for one, or will go ahead and create a SpiderMonkey Promise using the nsIGlobalObject dom::Promise is created with. dom::Promise is not wrappercached (because a SpiderMonkey Promise doesn't know how to notify it when it gets moved); it just uses a Heap<> to store the SpiderMonkey Promise. The C++-facing API that people actually use remains, so that changes outside of dom/bindings and dom/promise there are not really needed.
On the Web IDL side, we keep representing Promise as an interface, but make it NoInterfaceObject. When passing Promise arguments, we do the Promise::Resolve thing the spec calls for, which gives us a dom::Promise wrapping stuff up. When doing Promise return values, we take the non-wrappercached object codepath and just hack dom::Promise::WrapObject to return its already-existing SpiderMonkey Promise.
Note that this means that dom::Promise object identity is NOT preserved by a roundtrip through JS. That seems OK to me, honestly; that's basically how IDL callbacks work.
The goal of this bug is to land all the relevant DOM code but all behind SPIDERMONKEY_PROMISE ifdefs. There should therefore be no behavior changes. Once the SpiderMonkey parts of this are also done we'll take a look to see whether we have any try failures.
Till, I assume the relevant SpiderMonkey APIs will end up with clear documentation as to whether they can take references to cross-compartment wrappers to SpiderMonkey Promise objects and how they handle dead object wrappers and so forth. For now I'm assuming they just do sane things: accept cross-compartment wrappers, CheckedUnwrap, if that fails throw. If the result of the unwrap is not a SpiderMonkey Promise, I'm not sure whether we should throw or just assert... If that assumption turns out to be false, I can update these patches as needed.
| Assignee | ||
Comment 1•9 years ago
|
||
Attachment #8712190 -
Flags: review?(peterv)
| Assignee | ||
Updated•9 years ago
|
Assignee: nobody → bzbarsky
Status: NEW → ASSIGNED
| Assignee | ||
Comment 2•9 years ago
|
||
The idea is to not define a "Promise" property on the global and not generate
any of the methods, since SpiderMonkey will implement all of those, but to keep
some of the conversion to/from JS logic and the IDL parser validation bits that
we have right now. Once we can assume SPIDERMONKEY_PROMISE we can probably
change how the "Promise" identifier is handled by the IDL parser and how the
resulting type is handled by codegen, but for now we're aiming for minimal
changes.
Attachment #8712191 -
Flags: review?(peterv)
| Assignee | ||
Comment 3•9 years ago
|
||
These are basically the minimal changes needed to make PromiseDebugging compile
in the new world. It will NOT function correctly (see the XXX comments); Till
will be fixing it up more in bug 911216 as he transitions the relevant bits in
our devtools to work on top of SpiderMonkey promises.
Attachment #8712193 -
Flags: review?(peterv)
| Assignee | ||
Comment 4•9 years ago
|
||
This is the one part of this set of patches that is actually a substantive change
even without SPIDERMONKEY_PROMISE defined. This is being done because I don't
want to create ResolveInternal/RejectInternal methods on dom::Promise in the
new world.
In practice, the difference between MaybeResolve/Reject and
ResolveInternal/RejectInternal is that the former will do nothing if the
Promise is "resolved" in terms of spec terminology: either settled or locked in
to track another Promise. A resolved but still pending Promise can still get
fulfilled (what we call ResolveInternal) or rejected when the promise it's
tracking settles.
So the difference only matters if PromiseWorkerProxy can be working with a
"resolved" Promise (in which case what it's doing now would settle it, while
what I'm switching to would not). But I don't believe PromiseWorkerProxy ever
points to a "resolved" Promise.
Attachment #8712194 -
Flags: review?(peterv)
| Assignee | ||
Comment 5•9 years ago
|
||
This is the bulk of the new dom::Promise implementation. It's using the APIs
that bug 911216 part 1 adds.
Attachment #8712197 -
Flags: review?(peterv)
| Assignee | ||
Comment 6•9 years ago
|
||
This patch introduces a kinda fake IDL interface just to get the benefits of
cycle collection for the JS-to-C++ link we now need for PromiseNativeHandler
(because the SpiderMonkey Promise somehow needs to point to the
PromiseNativeHandler). Now in practice a bunch of our PromiseNativeHandlers
are not cycle collected. That kinda freaks me out, but spot-checking a few
suggests they do not in fact leak (either because they don't form cycles or
because the Promise they're observing always settles and then releases them).
Either way, that's a problem that exists with or without this patch...
Attachment #8712201 -
Flags: review?(peterv)
| Assignee | ||
Comment 7•9 years ago
|
||
nsWrapperCache expects the object it stores to have an ObjectMoved op that will
notify the wrapper cache when the object is moved. SpiderMonkey promises don't
have a way to do this.
Attachment #8712210 -
Flags: review?(peterv)
| Assignee | ||
Comment 8•9 years ago
|
||
This will run the SpiderMonkey promise jobs more or less the same way that we
run Promise jobs right now, including using a Web IDL callback for the actual
invocation.
Attachment #8712211 -
Flags: review?(peterv)
| Assignee | ||
Comment 9•9 years ago
|
||
Comment on attachment 8712210 [details] [diff] [review]
part 7. Stop wrappercaching dom::Promise when SPIDERMONKEY_PROMISE is defined
Oh, I just realized that to make this work we'll also need to fix all the IDL bits that return Promise via nsISupports. Right now that's relying on XPConnect QIing to nsWrapperCache and calling the virtual WrapObject(), but that won't work anymore...
| Assignee | ||
Comment 10•9 years ago
|
||
Attachment #8712396 -
Flags: review?(peterv)
| Assignee | ||
Updated•9 years ago
|
Attachment #8712210 -
Attachment is obsolete: true
Attachment #8712210 -
Flags: review?(peterv)
| Assignee | ||
Comment 11•9 years ago
|
||
I guess one open question is whether a dom::Promise should always store a JS Promise directly or whether it's OK for it to store a cross-compartment wrapper for one. This only matters for Promise::Resolve/Reject called over Xrays, I believe; in all other cases we wouldn't have a cross-compartment wrapper to start with... So we can sort that out once we have the Xray setup in place and I see how it works.
The other thing that needs a bit of clarification is whether the JSContext and JSValue passed to CallOriginalPromiseResolve/Reject are meant to be same-compartment or not. Again, this matters only for the Xray case.
Updated•9 years ago
|
Attachment #8712190 -
Flags: review?(peterv) → review+
Updated•9 years ago
|
Attachment #8712191 -
Flags: review?(peterv) → review+
Comment 12•9 years ago
|
||
Comment on attachment 8712193 [details] [diff] [review]
part 3. Turn off the IDL bits of PromiseDebugging when SPIDERMONKEY_PROMISE is defined
Review of attachment 8712193 [details] [diff] [review]:
-----------------------------------------------------------------
Hmm, this seems a bit useless without the bits from bug 911216.
Attachment #8712193 -
Flags: review?(peterv) → review+
| Assignee | ||
Comment 13•9 years ago
|
||
> Hmm, this seems a bit useless without the bits from bug 911216.
Sure. Everything in this bug is useless without those bits; the later patches don't even compile without them.
That's why we're not going to flip the define until this is all landed and bug 911216 is landed. We could try to do them all in one bug, but it's a bit simpler to just get this stuff in behind the ifdef and then we can do try runs with the patches from bug 911216...
| Assignee | ||
Comment 14•9 years ago
|
||
> the later patches don't even compile without them
I mean if SPIDERMONKEY_PROMISE is actually defined. Without that they compile, of course. :)
| Assignee | ||
Comment 15•9 years ago
|
||
Attachment #8712725 -
Flags: review?(peterv)
| Assignee | ||
Updated•9 years ago
|
Attachment #8712197 -
Attachment is obsolete: true
Attachment #8712197 -
Flags: review?(peterv)
| Assignee | ||
Comment 16•9 years ago
|
||
Attachment #8712733 -
Flags: review?(peterv)
| Assignee | ||
Updated•9 years ago
|
Attachment #8712396 -
Attachment is obsolete: true
Attachment #8712396 -
Flags: review?(peterv)
Comment 17•9 years ago
|
||
Comment on attachment 8712725 [details] [diff] [review]
Part 5 with the right API used on the AutoObjectVector to reserve space
Review of attachment 8712725 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/bindings/Codegen.py
@@ +5194,5 @@
> + if (!global) {
> + promiseRv.Throw(NS_ERROR_UNEXPECTED);
> + promiseRv.MaybeSetPendingException(cx);
> + $*{exceptionCode}
> + }
ws
| Assignee | ||
Comment 18•9 years ago
|
||
> ws
Fixed.
Updated•9 years ago
|
Attachment #8712194 -
Flags: review?(peterv) → review+
| Assignee | ||
Comment 19•9 years ago
|
||
Attachment #8715963 -
Flags: review?(peterv)
| Assignee | ||
Updated•9 years ago
|
Attachment #8712201 -
Attachment is obsolete: true
Attachment #8712201 -
Flags: review?(peterv)
| Assignee | ||
Comment 20•9 years ago
|
||
Attachment #8715964 -
Flags: review?(peterv)
| Assignee | ||
Updated•9 years ago
|
Attachment #8712733 -
Attachment is obsolete: true
Attachment #8712733 -
Flags: review?(peterv)
Comment 21•9 years ago
|
||
Comment on attachment 8712725 [details] [diff] [review]
Part 5 with the right API used on the AutoObjectVector to reserve space
Review of attachment 8712725 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/promise/Promise.cpp
@@ +565,5 @@
> + aRv.NoteJSContextException();
> + return nullptr;
> + }
> +
> + for (auto promise : aPromiseList) {
I think I'd prefer auto& here.
Attachment #8712725 -
Flags: review?(peterv) → review+
Comment 22•9 years ago
|
||
Comment on attachment 8715963 [details] [diff] [review]
Part 6 without the extra object
Review of attachment 8715963 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/promise/Promise.cpp
@@ +792,5 @@
> + if (NS_WARN_IF(!rejectFunc)) {
> + jsapi.ClearException();
> + return;
> + }
> +
Whitespace.
Attachment #8715963 -
Flags: review?(peterv) → review+
| Assignee | ||
Comment 23•9 years ago
|
||
> I think I'd prefer auto& here.
Done.
> Whitespace.
Fixed.
Comment 24•9 years ago
|
||
This was added in bug 1212323.
Attachment #8717473 -
Flags: review?(bzbarsky)
| Assignee | ||
Comment 25•9 years ago
|
||
Comment on attachment 8717473 [details] [diff] [review]
Part 9: Fix Promise usage in nsDOMWindowUtils::GetSupportsHardwareH264Decoding
r=me but I already have that rolled into part 7 locally anyway. I guess that hasn't been reviewed yet, so I should just post an updated version....
Attachment #8717473 -
Flags: review?(bzbarsky) → review+
| Assignee | ||
Comment 26•9 years ago
|
||
nsWrapperCache expects the object it stores to have an ObjectMoved op that will
notify the wrapper cache when the object is moved. SpiderMonkey promises don't
have a way to do this.
The XPCConvert changes are needed to allow code that passes around Promise
objects as nsISupports to continue working instead of ending up with
double-wrapped nsISupports (XPCWrappedNative for an nsISupports XPCWrappedJS)
around the SpiderMonkey Promise.
Attachment #8717486 -
Flags: review?(peterv)
| Assignee | ||
Updated•9 years ago
|
Attachment #8715964 -
Attachment is obsolete: true
Attachment #8715964 -
Flags: review?(peterv)
Comment 27•9 years ago
|
||
Comment on attachment 8717486 [details] [diff] [review]
part 7. Stop wrappercaching dom::Promise when SPIDERMONKEY_PROMISE is defined
Review of attachment 8717486 [details] [diff] [review]:
-----------------------------------------------------------------
The need for the XPCConvert changes is unfortunate :-(.
::: dom/bindings/BindingUtils.h
@@ +1151,5 @@
> return WrapNewBindingNonWrapperCachedObject(cx, scope, value.get(), rval,
> givenProto);
> }
>
> +// Helper for object references (as opposed to pointers.
... pointers).
Attachment #8717486 -
Flags: review?(peterv) → review+
Updated•9 years ago
|
Attachment #8712211 -
Flags: review?(peterv) → review+
| Assignee | ||
Comment 28•9 years ago
|
||
> The need for the XPCConvert changes is unfortunate :-(.
We can try to follow up with making Promise not implement nsISupports and hence catching at least the C++ places that rely on those codepaths... but it's a pretty risky project. :(
Comment 29•9 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/350b09f4cc2b
https://hg.mozilla.org/integration/mozilla-inbound/rev/eb8f560ba9fa
https://hg.mozilla.org/integration/mozilla-inbound/rev/c945faa259ff
https://hg.mozilla.org/integration/mozilla-inbound/rev/bb43bd69d282
https://hg.mozilla.org/integration/mozilla-inbound/rev/d8cfb5df18c3
https://hg.mozilla.org/integration/mozilla-inbound/rev/863f5c3d64a0
https://hg.mozilla.org/integration/mozilla-inbound/rev/5a52f75bbf6b
https://hg.mozilla.org/integration/mozilla-inbound/rev/dae2ed7930f4
Comment 30•9 years ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/350b09f4cc2b
https://hg.mozilla.org/mozilla-central/rev/eb8f560ba9fa
https://hg.mozilla.org/mozilla-central/rev/c945faa259ff
https://hg.mozilla.org/mozilla-central/rev/bb43bd69d282
https://hg.mozilla.org/mozilla-central/rev/d8cfb5df18c3
https://hg.mozilla.org/mozilla-central/rev/863f5c3d64a0
https://hg.mozilla.org/mozilla-central/rev/5a52f75bbf6b
https://hg.mozilla.org/mozilla-central/rev/dae2ed7930f4
Status: ASSIGNED → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla47
Updated•6 years ago
|
Component: DOM → DOM: Core & HTML
You need to log in
before you can comment on or make changes to this bug.
Description
•