Closed
Bug 974893
Opened 11 years ago
Closed 11 years ago
Remove EnterCompartment and keep the global with the value in Promise
Categories
(Core :: DOM: Core & HTML, defect)
Core
DOM: Core & HTML
Tracking
()
RESOLVED
FIXED
mozilla31
People
(Reporter: baku, Assigned: baku)
References
Details
Attachments
(2 files, 4 obsolete files)
(deleted),
patch
|
bzbarsky
:
review+
|
Details | Diff | Splinter Review |
(deleted),
patch
|
bzbarsky
:
review+
|
Details | Diff | Splinter Review |
This patch is needed for what we discuss about C++ wrapper to support DataStore API on the worker.
Assignee | ||
Comment 1•11 years ago
|
||
Attachment #8378980 -
Flags: review?(bzbarsky)
Comment 2•11 years ago
|
||
Comment on attachment 8378980 [details] [diff] [review]
global.patch
> class PromiseResolverMixin
What keeps the mGlobal member alive? Something needs to do that.
>@@ -484,18 +481,19 @@ Promise::Constructor(const GlobalObject&
>+ JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
>+ JSAutoCompartment ac(cx, global);
Why would "global" be in the same compartment as "value" here? I see no guarantee that it would be.
Maybe what we should do is just go ahead and JS_WrapValue the value into the current compartment of cx here.
> CountdownHolder(const GlobalObject& aGlobal, Promise* aPromise, uint32_t aCountdown)
With this change, aGlobal is unused, no?
But also, what guarantees that the same global will be passed to SetValue for all indices? This patch certainly seems to be depending on that happening, but I don't see why that would be the case.
We really need to write some evil testcases here involving promises from multiple compartments and methods from compartments that don't match the promises...
In any case, probably the right behavior here is actually to create the result array in the right compartment (Which one? The spec doesn't say, but should; known spec bug. Just doing it in the compartment we do it in now is fine.) and then wrapping the values we plan to put into the array into the array's compartment. We already entered that compartment, but then we didn't wrap the values into it.
>@@ -985,77 +985,81 @@ Promise::ResolveInternal(JSContext* aCx,
Nothing guarantees that "exn" is in the compartment of aCx here. Need to JS_WrapValue into that compartment, assuming aCx is in a sane compartment here. Alternately, need to enter the compartment of mGlobal on aCx and wrap into _that_ compartment. Or something.
Really, the only place we should be doing CurrentGlobalOrNull() is when we have a value we expect to be same-compartment with cx right now and want the corresponding global.
Attachment #8378980 -
Flags: review?(bzbarsky) → review-
Comment 3•11 years ago
|
||
Bobby, who's a good person to write some evil tests here?
Flags: needinfo?(bobbyholley)
Comment 4•11 years ago
|
||
(In reply to Boris Zbarsky [:bz] (reviews will be slow; ask someone else) from comment #3)
> Bobby, who's a good person to write some evil tests here?
Baku, I would think, with appropriate guidance and review. ;-)
Flags: needinfo?(bobbyholley)
Comment 5•11 years ago
|
||
Kyle did something interesting at bug 974120, which might help keep the mGlobal here.
Depends on: 974120
Assignee | ||
Comment 6•11 years ago
|
||
I have a few questions about this patch. I don't know if what I'm doing is right. Let's talk on IRC.
Attachment #8378980 -
Attachment is obsolete: true
Attachment #8402610 -
Flags: review?(bzbarsky)
Comment 7•11 years ago
|
||
Comment on attachment 8402610 [details] [diff] [review]
global.patch
The Maybe<JSAutoCompartment> in Constructor is dead code now.
We should document in Constuctor that we basically want the same behavior as this JS implementation:
function Promise(arg) {
try { arg(a, b); } catch (e) { this.reject(e); }
}
and that that implies wrapping the exception into the compartment the constructor call is happening in. Also worth adding an assert that at that point cx and aGlobal.Get() are same-compartment; if that ever changes for Xrays we'll need to decide which one to wrap into.
We should likewise document in the CountdownHolder constructor that the only time aGlobal.GetContext() and aGlobal.Get() are not same-compartment is when we're called via Xrays, and in that situation we in fact want to create the array in the callee compartment (that is, that of aGlobal.Get()).
>+ !JS_DefineElement(cx, mValues, index, aValue, nullptr, nullptr,
>+ JSPROP_ENUMERATE)) {
s/aValue/value/ here, right? Could use a test that would have caught that.
>@@ -992,18 +989,20 @@ Promise::ResolveInternal(JSContext* aCx,
I think I've convinced myself that JS_WrapValue here is correct. Just MOZ_CRASH if that fails, perhaps? Just going ahead with aCx and exn as-is if JS_WrapValue fails seems like a bad idea.
> ResolvePromiseCallback::Call(JS::Handle<JS::Value> aValue)
>+ if (!JS_WrapValue(cx, &value)) {
This part I think is wrong. ThreadsafeAutoSafeJSContext is in no particular compartment, so this should actually crash at runtime at least on mainthread...
What we should be doing instead is that we should be saving an object in ResolvePromiseCallback that tells us what compartment to enter. In the case of Promise::Race, that can probably just be JS::CurrentGlobalOrNull(aCx). In the case of Promise::Then, I'm not sure. Maybe that method should simply request a JSContext from the bindings and use that?
The other option would be to enter the compartment of mPromise->GetOrCreateWrapper before doing the call and wrap the value into that compartment. But I would prefer it if we propagated the caller compartment instead.
Similar for RejectPromiseCallback and WrapperPromiseCallback.
Attachment #8402610 -
Flags: review?(bzbarsky) → review-
Assignee | ||
Comment 8•11 years ago
|
||
Attachment #8402610 -
Attachment is obsolete: true
Attachment #8402744 -
Flags: review?(bzbarsky)
Comment 9•11 years ago
|
||
Comment on attachment 8402744 [details] [diff] [review]
global.patch
>+ MOZ_ASSERT(ok);
No, please actually MOZ_CRASH if !ok.
>+ NS_WARNING("Failed to wrap value in a context.");
Maybe s/in a context/into the right compartment/?
This happens several times.
This is all good, except one thing: you need to trace mGlobal!
Attachment #8402744 -
Flags: review?(bzbarsky) → review-
Assignee | ||
Comment 10•11 years ago
|
||
Attachment #8402744 -
Attachment is obsolete: true
Attachment #8402801 -
Flags: review?(bzbarsky)
Comment 11•11 years ago
|
||
Comment on attachment 8402801 [details] [diff] [review]
global.patch
This is still missing the following:
1) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS in the traverse methods, so
your trace bit will actually be called.
2) Something in unlink that nulls out mGlobal.
3) HoldJSObjects/DropJSObjects calls.
Attachment #8402801 -
Flags: review?(bzbarsky) → review-
Assignee | ||
Comment 12•11 years ago
|
||
Attachment #8402801 -
Attachment is obsolete: true
Attachment #8403123 -
Flags: review?(bzbarsky)
Assignee | ||
Comment 13•11 years ago
|
||
Attachment #8403124 -
Flags: review?(bzbarsky)
Assignee | ||
Comment 14•11 years ago
|
||
https://tbpl.mozilla.org/?tree=Try&rev=ddb0e9acf304
green on try.
Comment 15•11 years ago
|
||
Comment on attachment 8403123 [details] [diff] [review]
global.patch
Great, thanks!
Attachment #8403123 -
Flags: review?(bzbarsky) → review+
Updated•11 years ago
|
Attachment #8403124 -
Flags: review?(bzbarsky) → review+
Assignee | ||
Comment 16•11 years ago
|
||
Comment 17•11 years ago
|
||
Assignee | ||
Comment 18•11 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/84a40e23911c
Merge problem. Landing it again.
Comment 19•11 years ago
|
||
\^O^/ Thanks Andrea so much! Will test if this works for bug 949325.
Comment 20•11 years ago
|
||
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla31
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
•