On Oct 14, 2014, at 7:50 PM, Boris Zbarsky wrote:

> On 9/26/14, 10:03 PM, Boris Zbarsky wrote:
>> 2)  Say someone runs this in a web page:
>> 
>>   (function f() Promise.resolve().then(f))()
>> 
>> what should happen when the user navigates away from that web page and why?
> 
> Given the lack of response from other implementors, I guess we'll just 
> implement whatever is simplest in Gecko for now...

From an ECMAScript  perspective we need to reason about this in terms of realms 
and vats and ES jobs.

As a reminder:

A Vat is what ECMA262 defines. It is a self contained ES 
environment/processor/object space that has a single execution thread that runs 
ECMAScript evaluation "jobs" to completion. A  Vat has a set of job queues 
containing jobs that are waiting to execute.  When the current job is completed 
another waiting job is started.  A Vat is a serialization boundary. Object 
references (ie, pointers) can not be directly exchanged/shared between Vats.  
Some sort of serialization/proxy mechanism needs to be used to communicate 
between Vats.

A Realm represents an  ECMAScript GlobalEnviroment/ global object and all 
functions object whose scope includes that set of globals. A Vat may contain 
multiple Realms. Object references may be freely exchanged between Realms 
within the same Vat. 

So, let's see if we can describe the behavior of:
   (function f() Promise.resolve().then(f))()
in these terms:

The above expression must be evaluated as part of some job running in a Vat V. 
The code of the expression must be associated with some Realm R within V.
The function expression creates a new function object (let's call it f0) that 
is associated with Realm R this means that the reference to 'Promise' within 
its body will resolve to the Promise Global provided by Realm R. 
The immediate call starts evaluating the body of f0 as part of the current job.
A new, already resolved (it's state is "fulfilled") promise (let's call it 
p0.0) is created.
Invoking the 'then' method on p0.0 notices that p.0.0 is in the "fulfilled" 
state, so it enqueues on V's PromiseJobs job queue a PromiseReactionJob with f0 
as its reaction function. Let's call that pending job J0
'then' returns a new promise, p0.1 as the result of the 'then' method.  p0.1 is 
in the "pending" state.  It is the promise that will be resolved when the 
PromiseReactoinJob created in step 4 completes.
The returned reference to p0.1 is discarded, so no subsequent code can invoke 
methods on it and it has no PromiseReactions registered on it. So, when p0.1 is 
ultimately resolved, nothing will happen.
The current invocation of f0 returns and execution of the current job continues 
to completion.
A new job is selected from V's job queues and executed.  This may occur 0 or 
more times until ultimately...
...eventually J0 is selection as the next job and execution of it starts
J0, as a PromiseReactionJob, invokes f0 as its handler, this starts evaluation 
of the the body of f0 as part of the current job
A new, already resolved (it's state is "fulfilled") promise (let's call it 
p1.0) is created.
Invoking the 'then' method on p1.0 notices that p.1.0 is in the "fulfilled" 
state, so it enqueues on V's PromiseJobs job queue a PromiseReactionJob with f0 
as its reaction function. Let's call that pending job J1.
'then' returns a new promise, p1.1 as the result of the 'then' method.  p1.1 is 
in the "pending" state.  It is the promise that will be resolved when the 
PromiseReactoinJob created in step 12 completes.
The returned reference to p1.1 is discarded, so no subsequent code can invoke 
methods on it and it has no PromiseReactions registered on it. So, when p1.1 is 
ultimately resolved, nothing will happen.
The current invocation of f0 initiated in step 10 returns and execution of the 
current PromiseReactionJob completes.  There are no longer any reachable 
references to p0.1 so it may not be garbage collected.
A new job is selected for execution from V's job queues.  Eventually that will 
be J1.
Execution continues in this manner (essentially looping steps 8-16 with new Jn 
jobs) as long as V continues to execute jobs.

So, the basic question becomes one how the browser maps web pages to Vats. If 
each pages get a separate Vat then the above loop would presumably terminate 
when the user navigates away. If several "web pages" share a Vat then the loop 
would continue as long as any of those pages remained active. If the entire 
browser environment was represent as one vat then the loop continues as long as 
the browser is running. If a single Vat is used for multiple pages, a browser 
also has flexibility in how (and if) it selects ES jobs for execution, so it 
might impose some additional metadata and management policies on the Jn jobs. 
For example, perhaps it could purge all Jn jobs if Realm R is destroyed.

So, it all comes back to what is the mapping between various browser concepts 
and the above ES concepts.  BTW, I'm not saying that the ES model can't evolve 
to make it easier to describe browser semantics, but this is our starting point 
for discussion.

Allen




_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to