Closed
Bug 987512
Opened 11 years ago
Closed 8 years ago
AddonManager APIs should try to support both callbacks and promises
Categories
(Toolkit :: Add-ons Manager, defect)
Toolkit
Add-ons Manager
Tracking
()
RESOLVED
FIXED
mozilla53
Tracking | Status | |
---|---|---|
firefox53 | --- | fixed |
People
(Reporter: Unfocused, Assigned: kmag, Mentored)
References
Details
(Keywords: addon-compat, dev-doc-complete, Whiteboard: [good second bug][lang=js])
Attachments
(6 files)
(deleted),
patch
|
Unfocused
:
feedback+
|
Details | Diff | Splinter Review |
(deleted),
text/x-review-board-request
|
rhelmer
:
review+
|
Details |
(deleted),
text/x-review-board-request
|
rhelmer
:
review+
|
Details |
(deleted),
text/x-review-board-request
|
rhelmer
:
review+
|
Details |
(deleted),
text/x-review-board-request
|
rhelmer
:
review+
|
Details |
(deleted),
text/x-review-board-request
|
rhelmer
:
review+
|
Details |
So, I *think* this should be doable without any observable behaviour change for existing API consumers. For the APIs where we currently expect an callback function to be passed in, if we don't get a callback passed in then we instead return a Promise. Or maybe we just always return a Promise regardless?
Either way, this would cut down on code wrapping AddonManager API calls in functions that convert it to use promises.
Also, pretty sure this is doable entirely from within AddonManager.jsm - without changes to individual providers.
Comment 1•11 years ago
|
||
Yeah I thought about this too and I think we can just always return a promise and just always pass any callback to then.
One crazy thought I had was a slightly more advanced promise with a cancel function so say when the UI is closed it can cancel any pending promises and not have to deal with the possibilities of promises resolving after the UI is closed.
Comment 2•11 years ago
|
||
I'm conflicted (in general, and about this specific API) about having two-faced 'take callback + return promise' APIs; it does give us a gentler transition from one to the other, but it doubles the number of code paths we need to understand.
I've spent a fair bit of time thinking about "cancellable promises" - the first hurdle to get across is that the promise you're holding could be at the end of a long chain including multiple complete, in-progress and not-started-yet operations, and the current Promise data structures don't know anything about their predecessors in the chain. The general case gets even worse, because it's possible for a promise chain to mix implementations - you could have 'DOM promise'.then('Toolkit promise').then('JQuery promise), though with care we can probably avoid needing to solve that for now.
tl;dr I think the benefit of a Promise API to Addon Manager (and XPIProvider) outweighs my concern about multiple code paths, but I'm inclined to not touch the cancel code paths.
Comment 3•11 years ago
|
||
To be clear I would expect cancel() to reject the promise if it hasn't already been completed in some way so it would still uphold the guarantees expected, but I take the point that it may be too much.
I think by making every method effectively:
function getAddonByID(aId, aCallback) {
let deferred = defer();
deferred.promise.then(aCallback);
...
return deferred.promise;
}
we keep the differences between the codepaths minimal.
Updated•11 years ago
|
Whiteboard: [good second bug][lang=javascript]
Assignee | ||
Comment 4•10 years ago
|
||
For what it's worth, I've been using cancellable promises implemented via WeakMaps, and I find it a highly useful feature. It would be nice if our promise implementation supported cancellation by default.
Comment 5•10 years ago
|
||
(In reply to Kris Maglione [:kmag] from comment #4)
> For what it's worth, I've been using cancellable promises implemented via
> WeakMaps, and I find it a highly useful feature. It would be nice if our
> promise implementation supported cancellation by default.
That sounds like something good to file in "async tooling" for when Yoric is back?
Comment 6•10 years ago
|
||
(In reply to Georg Fritzsche [:gfritzsche] from comment #5)
> (In reply to Kris Maglione [:kmag] from comment #4)
> > For what it's worth, I've been using cancellable promises implemented via
> > WeakMaps, and I find it a highly useful feature. It would be nice if our
> > promise implementation supported cancellation by default.
>
> That sounds like something good to file in "async tooling" for when Yoric is
> back?
The FxOS Device storage people are working on an AbortablePromise implementation (for DOM Promises) in bug 1035060, but I don't know of anyone currently working on adding cancellation to Promise.jsm. The current state-of-the-draft spec discussion appears to be https://github.com/promises-aplus/cancellation-spec/issues/6
Flags: needinfo?(dteller)
Comment 7•10 years ago
|
||
The cancellation spec seems to be something that we can implement on top of either Promise.jsm or DOM Promise. I believe that we should wait until we have finally ported Promise.jsm on top of DOM Promise before we proceed in this direction.
Flags: needinfo?(dteller)
Updated•10 years ago
|
Whiteboard: [good second bug][lang=javascript] → [good second bug][lang=js]
Reporter | ||
Comment 8•10 years ago
|
||
Removing [good second bug], as this isn't actionable yet (see comment 7).
Whiteboard: [good second bug][lang=js] → [blocked - see comment 7]
Comment 9•10 years ago
|
||
Well, we could implement cancellation independent of Promises (that's what we have for our callback-based APIs, for the operations we support cancelling), but I agree it would be nice to have a clean way to cancel in-progress AddonManager operations. That said, I think we should take it in steps: implement plain Promises first and then add cancel support.
Reporter | ||
Comment 10•10 years ago
|
||
Ok!
Mentor: bmcbride
Whiteboard: [blocked - see comment 7] → [good second bug][lang=js]
Comment 11•10 years ago
|
||
It is not a complete patch. But I will like to have a feedback on the approach I am using. :)
Attachment #8516202 -
Flags: feedback?(bmcbride)
Assignee | ||
Comment 12•10 years ago
|
||
Comment on attachment 8516202 [details] [diff] [review]
987512_AddonManagerToUsePromise.patch
> if (typeof aCallback != "function")
> throw Components.Exception("aCallback must be a function",
> Cr.NS_ERROR_INVALID_ARG);
This needs ` || aCallback != null`
>+ p.then((value) => saeCall(aCallback, aAddon), null);
This needs `if (aCallback != null)`. Aside from the typo, though, something like the following would be preferable:
if (aCallback != null) {
p.then(value => { safeCall(aCallback, aAddon) })
.then(null, Cu.reportError);
}
This also needs tests to ensure that both forms behave as expected.
In the future, it would be a good idea to test your code before requesting feedback.
Reporter | ||
Comment 13•10 years ago
|
||
Comment on attachment 8516202 [details] [diff] [review]
987512_AddonManagerToUsePromise.patch
Review of attachment 8516202 [details] [diff] [review]:
-----------------------------------------------------------------
This seems ok. I'm not entrirely happy with it, as there's a lot of boilerplate between needing both Promise and AsyncObjectCaller. But I don't see a way to avoid that, other than re-thinking AsyncObjectCaller (which has been discussed, but it's not a simple fix).
Attachment #8516202 -
Flags: feedback?(bmcbride) → feedback+
Reporter | ||
Comment 14•10 years ago
|
||
Akshendra: Are you still working on this?
Flags: needinfo?(akshendra521994)
Comment 15•10 years ago
|
||
Sorry for the delay, have been busy lately with my academics. Will submit a patch within this week.
Flags: needinfo?(akshendra521994)
Comment 16•10 years ago
|
||
Blair,
I am having troubles writing tests. Can you hint me to a test for some insight on this.
Thanks.
Updated•10 years ago
|
Flags: needinfo?(bmcbride)
Reporter | ||
Comment 17•10 years ago
|
||
(In reply to Akshendra Pratap Singh from comment #16)
> I am having troubles writing tests. Can you hint me to a test for some
> insight on this.
You'll want an XPCShell test for this (https://developer.mozilla.org/en-US/docs/Mozilla/QA/Writing_xpcshell-based_unit_tests).
Have a look at test_general.js (http://dxr.mozilla.org/mozilla-central/source/toolkit/mozapps/extensions/test/xpcshell/test_general.js) and base your test on that - we don't need anything overly complex here.
Flags: needinfo?(bmcbride)
Hey Akshendra, did you manage to get these tests written?
Flags: needinfo?(akshendra521994)
Comment 19•10 years ago
|
||
Sorry but I could not manage to write the tests.
Flags: needinfo?(akshendra521994)
Assignee | ||
Updated•8 years ago
|
Assignee: nobody → kmaglione+bmo
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment 25•8 years ago
|
||
mozreview-review |
Comment on attachment 8819043 [details]
Bug 987512: Part 1 - Support both promises and callbacks in the AddonManager API.
https://reviewboard.mozilla.org/r/98906/#review99492
::: toolkit/mozapps/extensions/AddonManager.jsm:226
(Diff revision 1)
> +function promiseOrCallback(promise, callback) {
> + if (!callback)
> + return promise;
> +
> + if (typeof callback !== "function")
> + throw Components.Exception("aCallback must be a function",
It's called `callback` in the function signature and `aCallback` in the exception, pick one? Preferably the former
Attachment #8819043 -
Flags: review?(rhelmer) → review+
Comment 26•8 years ago
|
||
mozreview-review |
Comment on attachment 8819044 [details]
Bug 987512: Part 2 - Remove promise wrappers from AddonTestUtils.
https://reviewboard.mozilla.org/r/98908/#review99532
Attachment #8819044 -
Flags: review?(rhelmer) → review+
Comment 27•8 years ago
|
||
mozreview-review |
Comment on attachment 8819045 [details]
Bug 987512: Part 3 - Support promises in getInstallForFile and getInstallForURL.
https://reviewboard.mozilla.org/r/98910/#review99534
Attachment #8819045 -
Flags: review?(rhelmer) → review+
Comment 28•8 years ago
|
||
mozreview-review |
Comment on attachment 8819046 [details]
Bug 987512: Part 4 - Remove manual AddonManager promise wrappers from test code.
https://reviewboard.mozilla.org/r/98912/#review99536
Attachment #8819046 -
Flags: review?(rhelmer) → review+
Comment 29•8 years ago
|
||
mozreview-review |
Comment on attachment 8819047 [details]
Bug 987512: Part 5 - Remove manual AddonManager promise wrappers.
https://reviewboard.mozilla.org/r/98914/#review99538
Attachment #8819047 -
Flags: review?(rhelmer) → review+
Assignee | ||
Comment 30•8 years ago
|
||
mozreview-review-reply |
Comment on attachment 8819043 [details]
Bug 987512: Part 1 - Support both promises and callbacks in the AddonManager API.
https://reviewboard.mozilla.org/r/98906/#review99492
> It's called `callback` in the function signature and `aCallback` in the exception, pick one? Preferably the former
I went with aCallback because it's still called aCallback in the method signatures in all of the docs. But I suppose I have to update the docs, anyway, so...
Assignee | ||
Comment 31•8 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/fa05269ea601f52c430cc95404e8646c76b2776c
Bug 987512: Part 1 - Support both promises and callbacks in the AddonManager API. r=rhelmer
https://hg.mozilla.org/integration/mozilla-inbound/rev/5087537f8766732337eeaab0a8bee9b58281c3e9
Bug 987512: Part 2 - Remove promise wrappers from AddonTestUtils. r=rhelmer
https://hg.mozilla.org/integration/mozilla-inbound/rev/1dcf79ea901134abe0d967ee95d788c42640e6a2
Bug 987512: Part 3 - Support promises in getInstallForFile and getInstallForURL. r=rhelmer
https://hg.mozilla.org/integration/mozilla-inbound/rev/807adcac28b1b0fb763366a21a7fc149f7a3a57a
Bug 987512: Part 4 - Remove manual AddonManager promise wrappers from test code. r=rhelmer
https://hg.mozilla.org/integration/mozilla-inbound/rev/32ca7dcd1be5a152e49b7a57e78a3b2bb766a423
Bug 987512: Part 5 - Remove manual AddonManager promise wrappers. r=rhelmer
Assignee | ||
Comment 32•8 years ago
|
||
getInstallForURL now calls its callback asynchronously, where it previously apparently always called it synchronously. This broke a couple of tests that relied on the old behavior, so it may break some add-ons as well.
Keywords: addon-compat
Assignee | ||
Comment 33•8 years ago
|
||
(In reply to Kris Maglione [:kmag] from comment #32)
> getInstallForURL now calls its callback asynchronously, where it previously
> apparently always called it synchronously. This broke a couple of tests that
> relied on the old behavior, so it may break some add-ons as well.
I checked DXR and didn't find any add-ons that depend on this behavior, so perhaps it's not worth worrying about.
Assignee | ||
Comment 34•8 years ago
|
||
Noted in:
https://developer.mozilla.org/en-US/Firefox/Releases/53
and basic documentation added to:
https://developer.mozilla.org/en-US/Add-ons/Add-on_Manager/AddonManager
It could use a bit more documentation, but that page is currently broken due to the AMInterface template apparently disappearing, so it will have to wait until that is fixed.
Keywords: dev-doc-complete
Comment 35•8 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/fa05269ea601
https://hg.mozilla.org/mozilla-central/rev/5087537f8766
https://hg.mozilla.org/mozilla-central/rev/1dcf79ea9011
https://hg.mozilla.org/mozilla-central/rev/807adcac28b1
https://hg.mozilla.org/mozilla-central/rev/32ca7dcd1be5
Status: NEW → RESOLVED
Closed: 8 years ago
status-firefox53:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla53
You need to log in
before you can comment on or make changes to this bug.
Description
•