Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Promise.jsm and the predefined Promise object

70 views
Skip to first unread message

Paolo Amadini

unread,
Mar 29, 2014, 8:55:22 AM3/29/14
to
With bug 988122 landing soon, you'll now find a "Promise" object
available by default in the global scope of JavaScript modules.

However, this default implementation is still limited, and you're
strongly recommended to import Promise.jsm explicitly in new modules:

Cu.import("resource://gre/modules/Promise.jsm");

This will give you a number of advantages, among others:
- Errors don't risk disappearing silently (bug 966452)
- Tests will fail if errors are accidentally uncaught (bug 976205)
- You can inspect the current state in the debugger (bug 966471)
- You can see registered "then" handlers (bug 966472)
- You get better performance on long Promise chains

Promise.jsm and Promise are still interoperable from the functional
point of view, the difference is in the above non-functional
characteristics. Promise.jsm also has better performance due to the
fact that it avoids the JavaScript / C++ / JavaScript turnaround
time on chain resolution, with an optimized resolution loop handling,
but I don't think this performance part should prevent us from
migrating to C++ Promises when the other limitations are addressed.

Cheers,
Paolo

Gregory Szorc

unread,
Mar 29, 2014, 2:33:12 PM3/29/14
to Paolo Amadini, dev-pl...@lists.mozilla.org
If Promise.jsm is obviously superior, why don't we expose that version
to chrome-privileged global scopes by default? One less footgun.

Boris Zbarsky

unread,
Mar 29, 2014, 4:51:02 PM3/29/14
to
On 3/29/14 8:55 AM, Paolo Amadini wrote:
> - You get better performance on long Promise chains

Do we have hard data on this? I would be very interested in testcases
that show performance issues with the Promise objects we're shipping on
the web.

-Boris

Boris Zbarsky

unread,
Mar 29, 2014, 4:57:13 PM3/29/14
to
On 3/29/14 2:33 PM, Gregory Szorc wrote:
> If Promise.jsm is obviously superior

It's not, as far as I can tell. Nor is it fully API-compatible with the
Promise spec. For example, it has no Promise.race and no
Promise.prototype.catch. So code that expects per-spec behavior may not
work with the Promise exported by Promise.jsm.

-Boris

Boris Zbarsky

unread,
Mar 29, 2014, 5:00:24 PM3/29/14
to
On 3/29/14 4:57 PM, Boris Zbarsky wrote:
> For example, it has no Promise.race and no
> Promise.prototype.catch.

And Promise.resolve() can throw in the case of Promise.jsm (which it can
never do per spec). I didn't dig into the details of the implementation
to look for any other incompatibilities, btw; just did a cursory look
over the exposed API.

-Boris

David Rajchenbach-Teller

unread,
Mar 29, 2014, 5:02:55 PM3/29/14
to Gregory Szorc, Paolo Amadini, dev-pl...@lists.mozilla.org
On 3/29/14 7:33 PM, Gregory Szorc wrote:
> If Promise.jsm is obviously superior, why don't we expose that version
> to chrome-privileged global scopes by default? One less footgun.

If we did this, we would end up with two distinct Promise globals, with
two distinct semantics. This seems to me like the bigger footgun.

Also, keeping the necessity to import Promise.jsm will make it easier to
eventually migrate from Promise.jsm to [a superset of] DOM Promise once
we consider that everything is ready for that migration.

Cheers,
David

--
David Rajchenbach-Teller, PhD
Performance Team, Mozilla

Paolo Amadini

unread,
Mar 30, 2014, 6:00:11 AM3/30/14
to Boris Zbarsky
On 29/03/2014 21.57, Boris Zbarsky wrote:
> For example, it has no Promise.race and no Promise.prototype.catch.

It does, as soon as bug 941920 lands. We were holding it off due to
compatibility concerns, but the general availability of the DOM Promise
object changes the landscape and we're crash-landing it (I'd have
appreciated some coordination on this, but bug 988122 was off radar).

To add more complexity to the mix, there is still the presence of
legacy Add-on SDK Promises that don't have a "catch" method and
resolve synchronously. Most notably, until bug 887923 lands,
Task.jsm is still using those. Updating legacy promises tends to
block on the synchronous behavior that most tests expect.

This is a just a portion of the complex situation we have with
Promises. I was planning on doing a dev.platform post for a status
update next week, but this landing changed things and I chose to
communicate one specific aspect first, that is the purpose of
Promise.jsm and the need to do some work to make DOM Promises on par.

For details on in-progress work, you can refer to the unsorted
dependency tree of the Promises tracking bug:

https://bugzilla.mozilla.org/showdependencytree.cgi?id=856878&hide_resolved=1

> So code that expects per-spec behavior may not
> work with the Promise exported by Promise.jsm.

In most cases, code will work exactly in the same way. If it doesn't,
that is a Promise.jsm bug to be fixed. I'm not talking about code
designed to rely on edge cases - passing the full DOM Promise test
suite is a non-goal for Promise.jsm. The goal is to be able to switch
to DOM Promises as a drop-in replacement for Promise.jsm, when ready.

The "Cannot resolve a promise with an async function." error is
an example of a non-compliant behavior we've introduced to help
programmers avoid footguns. I'd add this to the list of reasons to
recommend "Promise.jsm", though obviously we will (rightfully)
lose this error when switching to the compliant implementation.

Making Promise.jsm developer-friendly was a significant investment of
time and effort under Mozilla's Performance and Async projects, and we
want to be sure we can capitalize on that experience while moving
forward to ES6/DOM Promises.

Cheers,
Paolo

Boris Zbarsky

unread,
Mar 30, 2014, 4:10:40 PM3/30/14
to
On 3/30/14 6:00 AM, Paolo Amadini wrote:
> It does, as soon as bug 941920 lands. We were holding it off due to
> compatibility concerns, but the general availability of the DOM Promise
> object changes the landscape and we're crash-landing it (I'd have
> appreciated some coordination on this, but bug 988122 was off radar).

Hmm. I don't think it was clear to anyone working on the DOM/ES6
promises that were were trying to treat them as "do not use" kind of things.

We should work on fixing the issues you pointed out, and I would _still_
like hard data on the performance problems you claim with long Promise
chains.... Presumably we have measurements we've done here?

> In most cases, code will work exactly in the same way.

Sure. But the reason we in my opinion can't just default all scopes to
Promise.jsm is that it in fact does _not_ work in exactly the same way
in all cases, and people writing green-field code will likely assume a
spec-compliant Promise implementation, not just something kinda similar.

> The goal is to be able to switch
> to DOM Promises as a drop-in replacement for Promise.jsm, when ready.

Can we define "ready"? Is the list of issues you listed in your post at
the start of this thread the full list of blockers for dropping Promise.jsm?

> The "Cannot resolve a promise with an async function." error is
> an example of a non-compliant behavior we've introduced to help
> programmers avoid footguns. I'd add this to the list of reasons to
> recommend "Promise.jsm"

It's a reason we can't just default to Promise.jsm, though... For
example, would it be sufficiently developer-friendly to log something in
this case but proceed instead of throwing? If so, is that something
that would make sense to do for ES6 promises as well? Logging things to
console is obviously not defined by any specs, so we have wide latitude
here.

-Boris

smaug

unread,
Mar 31, 2014, 7:34:31 AM3/31/14
to
On 03/29/2014 02:55 PM, Paolo Amadini wrote:
> With bug 988122 landing soon, you'll now find a "Promise" object
> available by default in the global scope of JavaScript modules.
>
> However, this default implementation is still limited, and you're
> strongly recommended to import Promise.jsm explicitly in new modules:
>
> Cu.import("resource://gre/modules/Promise.jsm");
>
> This will give you a number of advantages, among others:
> - Errors don't risk disappearing silently (bug 966452)
> - Tests will fail if errors are accidentally uncaught (bug 976205)
> - You can inspect the current state in the debugger (bug 966471)
> - You can see registered "then" handlers (bug 966472)
> - You get better performance on long Promise chains
>
> Promise.jsm and Promise are still interoperable from the functional
> point of view, the difference is in the above non-functional
> characteristics. Promise.jsm also has better performance due to the
> fact that it avoids the JavaScript / C++ / JavaScript turnaround
> time on chain resolution,
Has this shown up in profiles? If so, could you please give links to the profiles, since
we should get fast promise handling to the web platform.


> with an optimized resolution loop handling
How is this different to the C++ implementation?
Based on the code inspection both seem to do pretty much the same thing.
Post a runnable to the event loop and then process all the callbacks in
on batch.

David Rajchenbach-Teller

unread,
Mar 31, 2014, 7:42:04 AM3/31/14
to smaug, dev-pl...@lists.mozilla.org
On 3/31/14 1:34 PM, smaug wrote:
>> Promise.jsm and Promise are still interoperable from the functional
>> point of view, the difference is in the above non-functional
>> characteristics. Promise.jsm also has better performance due to the
>> fact that it avoids the JavaScript / C++ / JavaScript turnaround
>> time on chain resolution,
> Has this shown up in profiles? If so, could you please give links to the
> profiles, since
> we should get fast promise handling to the web platform.

I don't remember that we did any benchmark on this. I seem to remember
that this was an assumption based on a discussion with bz a long time
ago, but it might have been someone else.

Numbers would be interesting, though. Paolo, do you have plans to
perform benchmarking?

Paolo Amadini

unread,
Mar 31, 2014, 8:18:57 AM3/31/14
to Boris Zbarsky
On 30/03/2014 22.10, Boris Zbarsky wrote:
> Hmm. I don't think it was clear to anyone working on the DOM/ES6
> promises that were were trying to treat them as "do not use" kind of
> things.

Obviously, that is not what anyone is proposing here :-) DOM Promises
are already enabled by default in content, thanks to the great work that
has been done on both implementation and specification. We should make
sure that chrome code can fully benefit from that work as soon as
possible. (We're already seeing a partial benefit, since Promise.jsm
is still based on the DOM Promises specification work.)

>> In most cases, code will work exactly in the same way.
>
> Sure. But the reason we in my opinion can't just default all scopes to
> Promise.jsm is that it in fact does _not_ work in exactly the same way
> in all cases, and people writing green-field code will likely assume a
> spec-compliant Promise implementation, not just something kinda similar.

I also want to clarify that I don't think Promise.jsm should be imported
by default in chrome code at this point, despite its advantages.

> Can we define "ready"? Is the list of issues you listed in your post at
> the start of this thread the full list of blockers for dropping
> Promise.jsm?

I've edited bug 939636 to depend on three key issues out of the list
I posted before. I think that once those are addressed, there will be
no reason to stick to Promise.jsm any longer.

> It's a reason we can't just default to Promise.jsm, though... For
> example, would it be sufficiently developer-friendly to log something in
> this case but proceed instead of throwing? If so, is that something
> that would make sense to do for ES6 promises as well? Logging things to
> console is obviously not defined by any specs, so we have wide latitude
> here.

That looks like a good idea to me.

Cheers,
Paolo

Paolo Amadini

unread,
Mar 31, 2014, 8:28:37 AM3/31/14
to David Rajchenbach-Teller, smaug, dev-pl...@lists.mozilla.org
On 31/03/2014 13.42, David Rajchenbach-Teller wrote:
> I don't remember that we did any benchmark on this. I seem to remember
> that this was an assumption based on a discussion with bz a long time
> ago, but it might have been someone else.

Yes, memory was my source too.

On 31/03/2014 13.34, smaug wrote:
> Based on the code inspection both seem to do pretty much the same thing.
> Post a runnable to the event loop and then process all the callbacks in
> on batch.

And if that's the case, and the C++ / JavaScript transition does not
cost a lot, probably our assumption on performance was wrong.

On 31/03/2014 13.42, David Rajchenbach-Teller wrote:
> Numbers would be interesting, though. Paolo, do you have plans to
> perform benchmarking?

Not at present. I'd like to focus on the blockers, and as I already
said I don't think performance is a hard blocker, even if it might be
different from one implementation to the other.

Cheers,
Paolo

Boris Zbarsky

unread,
Mar 31, 2014, 11:05:45 AM3/31/14
to
On 3/31/14 8:18 AM, Paolo Amadini wrote:
> I've edited bug 939636 to depend on three key issues out of the list
> I posted before. I think that once those are addressed, there will be
> no reason to stick to Promise.jsm any longer.

Thanks. I'll see what I can do about getting these knocked out.

That said, we should probably track all the "parity" bugs in that bug.
Maybe a separate bug on "things blocking the switch"?

>> It's a reason we can't just default to Promise.jsm, though... For
>> example, would it be sufficiently developer-friendly to log something in
>> this case but proceed instead of throwing?
>
> That looks like a good idea to me.

I filed bug 990043 on investigating the DOM side of this. Not marking
that as blocking bug 939636 for now, but per above I think it probably
should.

-Boris

Paolo Amadini

unread,
Mar 31, 2014, 8:28:37 AM3/31/14
to David Rajchenbach-Teller, smaug, dev-pl...@lists.mozilla.org
On 31/03/2014 13.42, David Rajchenbach-Teller wrote:
> I don't remember that we did any benchmark on this. I seem to remember
> that this was an assumption based on a discussion with bz a long time
> ago, but it might have been someone else.

Yes, memory was my source too.

On 31/03/2014 13.34, smaug wrote:
> Based on the code inspection both seem to do pretty much the same thing.
> Post a runnable to the event loop and then process all the callbacks in
> on batch.

And if that's the case, and the C++ / JavaScript transition does not
cost a lot, probably our assumption on performance was wrong.

On 31/03/2014 13.42, David Rajchenbach-Teller wrote:
> Numbers would be interesting, though. Paolo, do you have plans to
> perform benchmarking?

0 new messages