Version 0.8.5 — Long Traces — Roadmap

42 views
Skip to first unread message

Kris Kowal

unread,
May 15, 2012, 10:21:39 PM5/15/12
to Q Continuum
Version 0.8.5 is tagged, published in NPM, and is bundled with updated
builds of q.min.js and q.min.js.gz. This adds preliminary support for
much anticipated "long traces" on V8. If an exception makes it to the
"end" of a promise chain, the stack trace will include a shallow trace
of the events leading up to the exception. Long traces do not
presently trace previous steps in the promise chain, but that is on
the roadmap. I am expecting that this will have rough edges, so be
prepared for a rapid v0.8.6.

Upcoming version 0.9 will probably break your program. For now, the
only action necessary on your part is to make sure that your Q
dependency in package.json is either to a specific version, or to a
version less than "0.9". This will ensure that you will be opting-in
when the time comes. Please check this. I do not want to
inadvertently break your world.

When you have more time, take a look at CHANGES.md to see what you
need to change for your application to run on v0.9.0, or even check
out the v0.9 branch and try your programs out.


## Version 0.8.5

Again, with thanks to Domenic Denicola, we now have long traces. They
look like this:

Error: Broken
at temp.js:7:11
From previous event:
at Object.<anonymous> (temp.js:6:2)

I also ported our unit tests to the Jasmine testing framework so we
can get a better look at how we’re faring on browsers. With several
fixes, we now have verified support for:

- Internet Explorers 7–9. Again, with thanks to Domenic.
- Firefox 12
- Safari 5.1.5
- Chrome 18

If you have a rejected promise, you can now inspect its wrapped
exception in the same turn of the event loop:

if (Q.isRejected(promise)) {
var exception = promise.valueOf().exception;
}

If you are on SpiderMonkey, we now have a future-proof shim that will
let you return a value from a Q.async generator (with thanks to Forbes
Lindesay for reporting the idea as issue #62).

var promiseNextNumber = Q.async(function (handle) {
var previousNumber = yield promisePreviousNumber(handle);
Q.return(previousNumber + 1);
});

I have deprecated "call", "apply", and "bind". Use "fcall", "fapply",
and "fbind" instead. These new functions do not require a "thisp",
which should not be entrained into Q’s protocol anyway, with thanks to
both Alex Rauschmeyer and Mark Miller for hints to this effect. This
also will eliminate name collisions with Function.prototype. In
v0.9.0, the "call", "apply", and "bind" functions will be removed and
"Q" will be a function, equivalent to our "Q.resolve".


## Upcoming

I’m gradually attempting to converge with Mark Miller’s specification
and implementation, makeQ (and he likewise is bending the
specification to match some of our needs today, like compromising on
variadic arguments). You will see little bits and pieces pointing in
this direction in the code, like support for using cajaVM.def, SES
checks, and exporting makeQ instead of Q if "ses" is defined. None of
this has been tested, mind, but I’m making the baby steps.

An unintended side-effect of renaming the Function.prototype analogues
is that Q will be able to become a function, per Mark’s specification
and implementation.

While I would like to, I will not be attempting to replace Q’s guts
with a WeakMap-based implementation. I looked into this, but the
WeakMap implementation used by makeQ does not shim pre-ES5 browsers.
The scope of this project is to serve as a gateway drug for the Q
interface. As such, I’m targeting API compatibility in the v0.9
timeline, but retaining a broad base of browser support and
no-dependencies to encourage adoption.

I have already changed the promise duck-type in the v0.9 branch:

- promise.promiseSend(op, resolved, ...args);
- promise.promiseDispatch(resolve, op, args);

The important thing to note is that arguments are no longer variadic.
This greatly reduces the amount of arguments wrangling internally.

- promise.send(op, ...args) has also been removed in favor of:
- promise.dispatch(op, args)

This liberates the "send" name, which may be repurposed. MarkM’s
specification uses "send" for our current "invoke".

I will also be introducing "Q.nearer(promise)", which is equivalent to
our current "promise.valueOf()". I have not yet added
"promise.nearer()", but it would make sense. "nearer()" may even
replace "valueOf()".


# Fin

Thanks for all the support!

Kris Kowal

Mark Miller

unread,
May 23, 2012, 2:19:30 AM5/23/12
to q-con...@googlegroups.com, Google Caja Discuss
Hi Kris, I appreciate this. I've just updated the specification at 
<http://code.google.com/p/es-lab/source/detail?r=681#> to make Q.race and Q.all no longer be variadic. I left Q.join variadic as the two-arg case seems like the one that will be used almost always. It's kinda like having a language with a variadic plus, where you expect plus to be used almost always with two arguments. Even without "...", it would be wrong to make plus take a list of addends. Please let me know if this creates a problem for you.

Cajadores, I have not yet submitted a CL to make the corresponding change to the makeQ.js and makeSimpleAMDLoader.js in the Caja distribution. Would this change be at all disruptive right now, considering current deployments and customers?



--
Text by me above is hereby placed in the public domain

  Cheers,
  --MarkM

Kris Kowal

unread,
May 23, 2012, 1:08:35 PM5/23/12
to q-con...@googlegroups.com, Google Caja Discuss
On Tue, May 22, 2012 at 11:19 PM, Mark Miller <eri...@gmail.com> wrote:
Hi Kris, I appreciate this. I've just updated the specification at 
<http://code.google.com/p/es-lab/source/detail?r=681#> to make Q.race and Q.all no longer be variadic. I left Q.join variadic as the two-arg case seems like the one that will be used almost always. It's kinda like having a language with a variadic plus, where you expect plus to be used almost always with two arguments. Even without "...", it would be wrong to make plus take a list of addends. Please let me know if this creates a problem for you.

Q does not presently have the "join" method, but when we do, I’ll follow your lead on making it a binary operator. There’s always [].reduce(Q.join) for the variadic case.

Kris Kowal

Mark Miller

unread,
May 23, 2012, 1:22:40 PM5/23/12
to q-con...@googlegroups.com, Google Caja Discuss
Hi Kris, perhaps you misunderstood. I left Q.join variadic rather than making it take a list, since the binary cases will dominate usage, but there's no reason to restrict it to binary. Please have a look.

Kris Kowal

unread,
May 23, 2012, 1:28:58 PM5/23/12
to q-con...@googlegroups.com
On Wed, May 23, 2012 at 10:22 AM, Mark Miller <eri...@gmail.com> wrote:
> Hi Kris, perhaps you misunderstood. I left Q.join variadic rather than
> making it take a list, since the binary cases will dominate usage, but
> there's no reason to restrict it to binary. Please have a look.

I think we are on the same page. This is the implementation that we
will adopt, which varies insubstantially from the concurrency
strawman:

Q.join = function(xP, yP) {
return Q.all([xP, yP]).spread(function(x, y) {
if (Object.is(x, y)) {
return x;
} else {
throw new Error("Not the same");
}
});
};

Which means that if you have an array of promises that should resolve
to an identical object, you could do this:

[a, b, c].reduce(Q.join)

…to get a promise for the resolution of all three, or a rejection if
any of them differ.

Kris Kowal
Reply all
Reply to author
Forward
0 new messages