The "initialization" steps for Web browsers

# Ian Hickson (3 years ago)

I've been working with jorendorff to try to write a description of the Loader part of the ES6 spec, to make sure I have a good grip of what the spec says before I look at how I need to hook into it to define the Web's dependency mechanism in the context of HTML Imports, etc.

As part of this, I'm trying to understand how I should hook the HTML spec into the ES6 spec for the purposes of regular <script> execution.

Is my understanding correct that the HTML spec should invoke this algorithm when the HTML spec creates the Window object? people.mozilla.org/~jorendorff/es6-draft.html#sec-initialization

If so, what should the browser do in step 7? I don't fully understand how this is supposed to work. Suppose a page is just:

<body>
<script> alert(document.body.innerHTML); </script>
<script> alert(document.body.innerHTML); </script>

If I read the #sec-initialization algorithm correctly, the scripts will execute back-to-back with no change in the DOM, so they'll output the same text. But the Web requires that these output different text, since the second <script> element won't be in the DOM when the first executes: software.hixie.ch/utilities/js/live-dom-viewer/saved/3051

Should I just say to invoke that algorithm but skip steps 6-8?

(Also, how could step 6's substeps ever get triggered?)

# Allen Wirfs-Brock (3 years ago)

On Jun 10, 2014, at 11:01 AM, Ian Hickson wrote:

As part of this, I'm trying to understand how I should hook the HTML spec into the ES6 spec for the purposes of regular <script> execution.

The ECMAScript initialization material is brand new, but it is intended to describe how the initial state the ES execution environment is established by a host such as HTML. I don't expect the current material to be totally complete or correct yet but it is a good starting point so I'm glad to see that you are looking at it.

Is my understanding correct that the HTML spec should invoke this algorithm when the HTML spec creates the Window object? people.mozilla.org/~jorendorff/es6-draft.html#sec-initialization

Not exactly, although if you had said "first" Window object then maybe you statement would be correct.

As you know, an ECMAScript environment may have multiple co-existent "global objects". The ES spec. abstracts the concepts associated with each global object as a "Realm". All ECMAScript code execution must take place in the context of a Realm so an initial Realm must be established before any ES code executes.

Section 8.5 defines the initialization process that occurs for an ES engine before any ES code executes. It includes establishing the first Realm. Whether or not that initial Realm actually corresponds to the first "Window" is something you need to decided. For example, I can image that for some hosts the first Realm might actually some sort of utility Realm that is used for loading code and "forking" user Realms.

8.5 can't be performed for each Window object that shares a common ES engine because it essentially restarts the entire ES engine. Instead, I would expect that the steps of InitializeFirstRealm (8.5.1) to be approximately what should be called for each Window object. This suggests that InitializeFirstRealm is poorly named. Perhaps it should be renamed InitializeHostRealm. There may be additional refactoring that is needed between 8.5 and 8.5.1.

If so, what should the browser do in step 7? I don't fully understand how this is supposed to work. Suppose a page is just:

<body>
<script> alert(document.body.innerHTML); </script>
<script> alert(document.body.innerHTML); </script>

If I read the #sec-initialization algorithm correctly, the scripts will execute back-to-back with no change in the DOM, so they'll output the same text. But the Web requires that these output different text, since the second <script> element won't be in the DOM when the first executes:

ES doesn't know anything about the DOM, external script dependencies , etc. The ES model is that it has a simple queue (populated by the host) of script execution tasks and that the execution of the scripts in the queue take place in order.

A simple command-line ES host probably would, as part of step 7, add a ScriptEvaluationTask to the queue for each script file listed on the command-line. They would then be evaluated in sequence.

However, you don't have to do that and step 7 isn't the only place you can add new ScriptEvaluationTasks. I would imaging you would maintain your own queues and dependency algorithms that track order and DOM update dependencies such as between the two script tags in your example. You would then only EnqueueTask a ScriptEvaluationTask when it DOM update dependencies has been satisfied.

Alternatively, you might define a new kind of ES Task, let's call it a SyncDOMTask. Then at step 7 you might EnqueueTask a DOMSyncTask onto the "ScriptTasks" queue between the two ScriptEvaluationTasks.

I understand that this is all pretty vague and leaves a lot up to you. But I need to define ES execution in a host independent manner. I'm trying to provide the building blocks that you and other hosts need to describe how their complex environment-specific semantics integrate with the baseline ES execution semantics.

software.hixie.ch/utilities/js/live-dom-viewer/saved/3051

Should I just say to invoke that algorithm but skip steps 6-8?

(Also, how could step 6's substeps ever get triggered?)

Working backwards, step 5 does many things, some of which are specified as having error conditions and exceptions, so I have to take into account what happens if any errors occur. Step 6, just says that if they do then the startup of the ES environment has failed. If an implementor can prove that they can trigger any of those error conditions then they don't have to worry about it. But for completeness, I do.

It's up to you to define what you initially enqueue in step 7. It could be nothing (step 7 currently says "one or more", it probably should say "zero or more").

Step 8 just says to dispatch the next pending ES Task. You need to do that to actually get things started.

However, step 4 of NextTask is where the next ES Task is actually selected and it leaves it up to the implementation to define how the next Task selection process and what happens if all Task queue are empty. My expectation is that most of the integration work you need to do is in define exactly what the web platform does in NextTask step 4.

It occurs to be that these implementation-specific extension points may be hard to find as they hare buried as steps in several algorithms. in my next revision I see if I can define an abstraction operation corresponding to each extension points. They we will have a list of operations that a host must define.

Hope this helps, keep asking if it doesn't...

# Ian Hickson (3 years ago)

On Tue, 10 Jun 2014, Allen Wirfs-Brock wrote:

Not exactly, although if you had said "first" Window object then maybe you statement would be correct.

As you know, an ECMAScript environment may have multiple co-existent "global objects". The ES spec. abstracts the concepts associated with each global object as a "Realm". All ECMAScript code execution must take place in the context of a Realm so an initial Realm must be established before any ES code executes.

What is an "ECMAScript environment" in this context? Is it the scripting engine behind a unit of related similar-origin browsing contexts? Or is it the scripting engine associated with a particular event loop?

In the case of two pages that are running in different origins, each with their own Window object, does the ES spec attempt to answer the question of how those two scripts should interact if they access each others' Window objects? Or is that something for the HTML spec?

Section 8.5 defines the initialization process that occurs for an ES engine before any ES code executes. It includes establishing the first Realm. Whether or not that initial Realm actually corresponds to the first "Window" is something you need to decide. For example, I can imagine that for some hosts the first Realm might actually some sort of utility Realm that is used for loading code and "forking" user Realms.

Such a "utility Realm" sounds like an implementation detail that wouldn't appear in a spec, though, no? Would it be exposed or detectable in any way from aithor script?

There's not really a "first" Window from the point of view of the HTML spec. I'm not sure how an initial Realm would really map to a browser.

8.5 can't be performed for each Window object that shares a common ES engine because it essentially restarts the entire ES engine. Instead, I would expect that the steps of InitializeFirstRealm (8.5.1) to be approximately what should be called for each Window object.

Ok. I think part of my confusion comes from step 7, then, which says "one or more" scripts. I think if that was changed to "zero or more", I could say in the HTML spec that the Initialization steps run as required by the ES spec, and that in HTML implementations, step 7 must obtain no scripts. Then, separate from this, I would call CreateRealm() to get a realm and then call InitializeFirstRealm(realm) with that realm? Is that right?

This suggests that InitializeFirstRealm is poorly named. Perhaps it should be renamed InitializeHostRealm. There may be additional refactoring that is needed between 8.5 and 8.5.1.

I'm happy to use whatever terms you think are best.

ES doesn't know anything about the DOM, external script dependencies, etc. The ES model is that it has a simple queue (populated by the host) of script execution tasks and that the execution of the scripts in the queue take place in order.

A simple command-line ES host probably would, as part of step 7, add a ScriptEvaluationTask to the queue for each script file listed on the command-line. They would then be evaluated in sequence.

However, you don't have to do that and step 7 isn't the only place you can add new ScriptEvaluationTasks.

If step 7's "one or more" is what is intended (as opposed to the "zero or more", see above), what is the script that a browser obtains in step 7?

I would imagine you would maintain your own queues and dependency algorithms that track order and DOM update dependencies such as between the two script tags in your example. You would then only EnqueueTask a ScriptEvaluationTask when it DOM update dependencies has been satisfied.

Well, we want to make sure that browsers only have one dependency algorithm, we wouldn't want to have redundancy there. See the "Integrating the Webs' dependency systems" thread from a few weeks back. I'm trying to understand how ES6's loading logic works so that I can figure out how to integrate or extend it to handle the more elaborate needs of other parts of the Web platform, so that we can e.g. have image loading handled by the same logic as module loading, since they need to share network resources, can have interdependencies, etc.

Alternatively, you might define a new kind of ES Task, let's call it a SyncDOMTask. Then at step 7 you might EnqueueTask a DOMSyncTask onto the "ScriptTasks" queue between the two ScriptEvaluationTasks.

Are these tasks related in any way to the HTML spec's task queues and event loop mechanism? Should we integrate these somehow also?

I understand that this is all pretty vague and leaves a lot up to you.

That's fine. :-)

I just want to make sure it's all well-defined, I don't mind doing the heavy lifting.

But I need to define ES execution in a host independent manner. I'm trying to provide the building blocks that you and other hosts need to describe how their complex environment-specific semantics integrate with the baseline ES execution semantics.

Cool.

Working backwards, step 5 does many things, some of which are specified as having error conditions and exceptions, so I have to take into account what happens if any errors occur. Step 6, just says that if they do then the startup of the ES environment has failed. If an implementor can prove that they [can't] trigger any of those error conditions then they don't have to worry about it. But for completeness, I do.

Do you have an example of how any of those steps could fail?

It seems to me that if step 6 triggers, the whole scripting engine has failed to start up, which seems like it should be something that is non-conforming. :-)

It's up to you to define what you initially enqueue in step 7. It could be nothing (step 7 currently says "one or more", it probably should say "zero or more").

Zero or more would, I think, fix my confusion here.

Step 8 just says to dispatch the next pending ES Task. You need to do that to actually get things started.

NextTask seems like it is somewhat redundant with the HTML event loop mechanism. Ideally I think I'd like to have the hooks set up so that when a task completes on the ES side, it just returns to the HTML event loop, which then does its stuff, and eventually calls back into the ES spec to run the next script.

It occurs to be that these implementation-specific extension points may be hard to find as they hare buried as steps in several algorithms. in my next revision I see if I can define an abstraction operation corresponding to each extension points. They we will have a list of operations that a host must define.

That would certainly help, yes.

# Domenic Denicola (3 years ago)

Remember that ES tasks === HTML microtasks (in all implementations today; Allen insists they are different since ES tasks are generic and do not have very many requirements, but in reality they are the same).

# Garrett Smith (3 years ago)

On 6/10/14, Ian Hickson <ian at hixie.ch> wrote:

Do you have an example of how any of those steps could fail?

I'm guessing that applies for any early error.

<script>
var tew;
continue; // early error; `tew` is not bound.
</script>

<script>
alert(rrq);
var rrq;
g; // ReferenceError, not an early error; `rrq` is bound.
</script>

The following example results in a ReferenceError. Although gv is defined, that does not occur until the subsequent <script>. After the browser has reached the first </script>, the Program is evaluated, and at that point, the global Lexical Environment Record does not have a gv property. Where and how is this behavior described?

<script>alert(gv); // context to subsequent script is segmented. </script>
<script>var gv;</script>

I vaguely remember seeing examples more complex than the example above, including dealings with the global scope polluter, and with more divergent behavior.

Moving gv to the same script results results in no such runtime error, as is explained in ES3.

<script>
alert(gv); // contiguous context in same script.
var gv;
</script>
# Ian Hickson (3 years ago)

On Tue, 10 Jun 2014, Domenic Denicola wrote:

Remember that ES tasks === HTML microtasks (in all implementations today [...]

That doesn't sound right. If every script is always running on an ES task, then it sounds like an ES task is neither an HTML task nor an HTML microtask. A single HTML task might involve running multiple scripts (some even nested inside each other, with microtasks firing after each of those). For example, consider a task that changes a flag and then fires an event; the event being fired is then handled by a number of event listeners, each of which then fires an ES task to run the script, and after each one there's the microtask queue is flushed, before finally returning back to the main task, and then continuing the event loop.

# Allen Wirfs-Brock (3 years ago)

On Jun 10, 2014, at 2:08 PM, Ian Hickson wrote:

What is an "ECMAScript environment" in this context? Is it the scripting engine behind a unit of related similar-origin browsing contexts? Or is it the scripting engine associated with a particular event loop?

In the case of two pages that are running in different origins, each with their own Window object, does the ES spec attempt to answer the question of how those two scripts should interact if they access each others' Window objects? Or is that something for the HTML spec?

Almost every concept you used in the above two paragraphs are web platform specific concepts that are not even in the normal ECMAScript domain of discourse.

By an ECMAScript Environment (and this is what Ecma-262 defines, although it doesn't actually use that name) I mean a heap of ECMAScript objects (and related values) that may directly reference (point to) each other and a single thread of execution of ECMAScript code. The environment may include multiple "global objects".

In web terms, this could means several (same-origin??) windows and any associated Iframes, as long as there is only a single thread of ES code execution that encompasses them.

It could not include a both the object/script state of Window and of a WebWorker because logically a WebWorker's tobjects may not contain references to the Window's object (and visa-versa) and because both the Window and the Worker have independent and potentially concurrent execution threads for ES code.

While the spec. doesn't directly address this, I also like to assume fault isolation between ES environment. A fault in one ES environment should not be able to directly cause failure of another ES environment. Basically, like a Unix process.

Whether certain Web constructs are modeled by sharing a single ES environment or as separate (but possibly communicating) ES environment is up to you and/or browser implementors.

The possibility of interactions within an ES environment is all at the level of pointers between objects. If ES code has access to an object that contains a pointer to another object, then the code can interact with the second object. You might interpose proxying mechanism to try to isolate subgraphs of objects, but at the level of the ES semantics, such proxies are just additional objects with their own behaviors.

Such a "utility Realm" sounds like an implementation detail that wouldn't appear in a spec, though, no? Would it be exposed or detectable in any way from aithor script?

There's not really a "first" Window from the point of view of the HTML spec. I'm not sure how an initial Realm would really map to a browser.

Such a "utility Realm" doen't appear in the ES spec. But it might have a used in the spec. that defines some specific hosting environment.

I suppose, "first Window" could literally mean the first window opened by a browser. However, a browser like FF that uses JavaScript to implement its chrome might start up a Chrome Realm as its first Realm.

If you want all documents from a given origin to operate within a single ES environment (is that a reasonable model?) then the first time you load a document from a new origin you might launch a new ES Environment with a a new Window object as its first Realm.

Ok. I think part of my confusion comes from step 7, then, which says "one or more" scripts. I think if that was changed to "zero or more", I could say in the HTML spec that the Initialization steps run as required by the ES spec, and that in HTML implementations, step 7 must obtain no scripts. Then, separate from this, I would call CreateRealm() to get a realm and then call InitializeFirstRealm(realm) with that realm? Is that right?

Yes, sounds about right. Particularly if I apply some renaming.

If step 7's "one or more" is what is intended (as opposed to the "zero or more", see above), what is the script that a browser obtains in step 7?

I think it should be zero or more.

Well, we want to make sure that browsers only have one dependency algorithm, we wouldn't want to have redundancy there. See the "Integrating the Webs' dependency systems" thread from a few weeks back. I'm trying to understand how ES6's loading logic works so that I can figure out how to integrate or extend it to handle the more elaborate needs of other parts of the Web platform, so that we can e.g. have image loading handled by the same logic as module loading, since they need to share network resources, can have interdependencies, etc.

We may have some chicken and egg issues to work through.

But, in general the ES spec. only needs to address the semantic issues of things it defines. For example, it cares about the relative ordering of Promise Tasks because that is part of the ES promise emantics. But it doesn't care about the relative ordering of individual PromiseTasks and future cript evaluation tasks because there are no defined semantic dependencies between those. However, as we move more semantics into ES (for example, event callbacks and timeouts are likely future additions) we will probably have more dependencies to specify.

Are these tasks related in any way to the HTML spec's task queues and event loop mechanism? Should we integrate these somehow also?

At our latest TC39 meeting we decided to use the term "Job" for what we had been calling "Task" in the ES spec. Specifically to avoid confusion with the HTML spec.

We need to avoid over-coupling the ES spec. to the HTML spec as ES is used in other host environments. That's why for Tasks(soon to be Jobs) we only define the minimum needed to have a consistent semantics across all ES hosts.

Basically, what you should do is use ES Jobs as the mechanism for saying here is a bit of ES code that needs to be executed before/after/independently from some other bit of code. But the actual criteria for deciding to make such a request needs to be in your spec.

Do you have an example of how any of those steps could fail?

The implementation provided global object could throw during the processing of SetDefualtGlobalBindings

It seems to me that if step 6 triggers, the whole scripting engine has failed to start up, which seems like it should be something that is non-conforming. :-)

Exactly, the spec. essentially says that if exceptions occur during start-up then a conforming implementation must terminate. If we said nothing then an implementation might not check for such exceptions and could start ES code execution with in incompletely initialized set of global bindings.

NextTask seems like it is somewhat redundant with the HTML event loop mechanism. Ideally I think I'd like to have the hooks set up so that when a task completes on the ES side, it just returns to the HTML event loop, which then does its stuff, and eventually calls back into the ES spec to run the next script.

That's pretty much what NextTask is. Steps 1-3 cleans up after the just completed task. Steps 4-5 calls out to the host provided task scheduler. Steps 6-10 initiates execution of the task that was selected by the host. Step 9 is an extra hook that allow the host environment to do additional host-spec processing for each task immediately before it is executed. It's something Boris asked for to manage domain switching issues.

# Allen Wirfs-Brock (3 years ago)

On Jun 10, 2014, at 2:33 PM, Ian Hickson wrote:

On Tue, 10 Jun 2014, Domenic Denicola wrote:

Remember that ES tasks === HTML microtasks (in all implementations today [...]

That doesn't sound right. If every script is always running on an ES task, then it sounds like an ES task is neither an HTML task nor an HTML microtask. A single HTML task might involve running multiple scripts (some even nested inside each other, with microtasks firing after each of those). For example, consider a task that changes a flag and then fires an event; the event being fired is then handled by a number of event listeners, each of which then fires an ES task to run the script, and after each one there's the microtask queue is flushed, before finally returning back to the main task, and then continuing the event loop.

Exactly, a ES Task (now Job) is just an atomic unit of ES code scheduling and executino. I'm not in the business to telling host environments exactly how they should map their abstractions into such Jobs sized units.

# Allen Wirfs-Brock (3 years ago)

On Jun 10, 2014, at 2:31 PM, Garrett Smith wrote:

I'm guessing that applies for any early error.

Early errors are handled as part of ScriptEvaluationTask If an early error is detected the Task competes normally, but without executing any ES code,

<script>
var tew;
continue; // early error; `tew` is not bound.
</script>

<script>
alert(rrq);
var rrq;
g; // ReferenceError, not an early error; `rrq` is bound.
</script>

Everything mentioned below is handled by GlobalDeclarationInstantiation. The order in which this occurs for individual scripts is the order in which the corresponding ScriptEvaluationTasks are are enqueued in the "ScriptTasks" queue. There are different evaluation paths (some of which may still need to be defined) for modules.

# Ian Hickson (3 years ago)

On Tue, 10 Jun 2014, Allen Wirfs-Brock wrote:

By an ECMAScript Environment (and this is what Ecma-262 defines, although it doesn't actually use that name) I mean a heap of ECMAScript objects (and related values) that may directly reference (point to) each other and a single thread of execution of ECMAScript code. The environment may include multiple "global objects".

Ok. Sounds like that mays to an event loop, on the HTML side.

That should be quite workable. I'll invoke 8.5 when I create an event loop (with zero scripts), and I'll invoke CreateRealm() and then 8.5.1 when I create a Window.

I suppose, "first Window" could literally mean the first window opened by a browser.

There might not be one. There's nothing stopping a browser from spawning multiple Windows at once on startup, or, indeed, from restoring old state all the way down to restoring a pre-existing Web page and JS environment. But that's ok, I think if we define things in terms of when the event loop is created, it should work out.

However, a browser like FF that uses JavaScript to implement its chrome might start up a Chrome Realm as its first Realm.

That part of Firefox is an implementation detail; from HTML's point of view, it doesn't exist. There should not be any way to distinguish (and therefore there should not be anything in the specs that would distinguish) a browser that uses JS under the hood and one that doesn't.

We may have some chicken and egg issues to work through.

Don't we always!

But, in general the ES spec. only needs to address the semantic issues of things it defines. For example, it cares about the relative ordering of Promise Tasks because that is part of the ES promise emantics. But it doesn't care about the relative ordering of individual PromiseTasks and future cript evaluation tasks because there are no defined semantic dependencies between those. However, as we move more semantics into ES (for example, event callbacks and timeouts are likely future additions)
we will probably have more dependencies to specify.

Sure. But browsers want to make sure they only implement one dependency mechanism, and so we have to make sure that all the dependency systems we specify can be implemented in terms of a single mechanism. Whether we end up doing this by speccing it as one, or speccing it as one that calls out to another, or whatever, remains to be seen. At this point I'm just trying to learn all I can about the various mechanisms.

At our latest TC39 meeting we decided to use the term "Job" for what we had been calling "Task" in the ES spec. Specifically to avoid confusion with the HTML spec.

Cool.

Basically, what you should do is use ES Jobs as the mechanism for saying here is a bit of ES code that needs to be executed before/after/independently from some other bit of code. But the actual criteria for deciding to make such a request needs to be in your spec.

Right.

Exactly, the spec. essentially says that if exceptions occur during start-up then a conforming implementation must terminate. If we said nothing then an implementation might not check for such exceptions and could start ES code execution with in incompletely initialized set of global bindings.

I think ES should just say that an implementation must not fail on startup. But that's a separate topic. :-)

That's pretty much what NextTask is. Steps 1-3 cleans up after the just completed task. Steps 4-5 calls out to the host provided task scheduler. Steps 6-10 initiates execution of the task that was selected by the host. Step 9 is an extra hook that allow the host environment to do additional host-spec processing for each task immediately before it is executed.

Right, but what I'm saying is that from an editorial perspective it would be simpler for host specs to hook into the ES spec, and would be easier for implementors to understand, if the loop was turned inside-out from what it is now.

Instead of the ES spec having an algorithm that works like this:

   NextTask result:
     handle problems arising from the last job (result)
     stop running code
     get more code to run
     start running code (eventually calls NextTask)

...it would be easier if it was:

   RunCode (code):
     start running code
     stop running code
     let result be the result of running the code
     handle problems arising from the last job (result)
     return to calling algorithm in host spec

...where RunCode is called by the host spec to run code.

On a related note, it would be easier if algorithms that said to "Perform any implementation or host environment defined processing" named the specific steps. For example, in EnqueueTask step 7, it could say "Perform any implementation- or host-environment-defined processing of /pending/ to queue a new task", where "queue a new task" is a magic phrase (hook) that I would then be able to reference in HTML, e.g. by saying "When the ES spec says to queue a new task, follow these steps...".

# Domenic Denicola (3 years ago)

From: Ian Hickson [mailto:ian at hixie.ch]

That doesn't sound right. If every script is always running on an ES task, then it sounds like an ES task is neither an HTML task nor an HTML microtask. A single HTML task might involve running multiple scripts (some even nested inside each other, with microtasks firing after each of those). For example, consider a task that changes a flag and then fires an event; the event being fired is then handled by a number of event listeners, each of which then fires an ES task to run the script, and after each one there's the microtask queue is flushed, before finally returning back to the main task, and then continuing the event loop.

Hmm. How do we reconcile this with the fact that promises use microtasks in all implementations today? Are they nonconformant with the spec? Or is the spec flexible enough that e.g. PromiseTask ES tasks can be put on a HTML microtask queue, while ones involved in the whole script lifecycle business can be put on the HTML task queue? Engine folks, what are your thoughts?

# Boris Zbarsky (3 years ago)

On 6/10/14, 9:04 PM, Domenic Denicola wrote:

How do we reconcile this with the fact that promises use microtasks in all implementations today?

Promises in Gecko don't use microtasks (which don't even really exist in Gecko). They use what HTML calls "tasks" (that is, full-on event loop dispatch).

We'll likely change that at some point, of course. To what is unclear so far.

# Ian Hickson (3 years ago)

On Wed, 11 Jun 2014, Domenic Denicola wrote:

Hmm. How do we reconcile this with the fact that promises use microtasks in all implementations today? Are they nonconformant with the spec? Or is the spec flexible enough that e.g. PromiseTask ES tasks can be put on a HTML microtask queue, while ones involved in the whole script lifecycle business can be put on the HTML task queue?

Where in the ES spec are the ES jobs for promises queued up?

# Domenic Denicola (3 years ago)

From: Ian Hickson [mailto:ian at hixie.ch]

Where in the ES spec are the ES jobs for promises queued up?

people.mozilla.org/~jorendorff/es6-draft.html#sec-triggerpromisereactions and people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.prototype.then; search for EnqueueTask("PromiseTasks".

# Allen Wirfs-Brock (3 years ago)

On Jun 10, 2014, at 7:21 PM, Ian Hickson wrote:

Where in the ES spec are the ES jobs for promises queued up?

(starting now, I'm going to use "Jobs" to mean what the ES6 spec. current calls "Tasks"

The two kinds of promise related Jobs are defined in

They are enqueued from

Regarding, Domenic's and Boris responses, I don't see why ES6 promise related Jobs need to be translated into HTML Tasks/Microtasks at all. The ES6 spec. takes care of creating and queueing its promise related Jobs. The only thing HTML needs to worry about is specify when the ES "PrimiseJobs" queue is serviced in relationship to any other ES Job queues it may use. That means the the HTML scheduling algorithm may impose a scheduling priority of promise Jobs relative to various kinds of HTML Tasks/MicroTask. But it doesn't mean that that promise Jobs have any of the other semantic characteristics of those HTML abstractions.

# Ian Hickson (3 years ago)

On Wed, 11 Jun 2014, Domenic Denicola wrote:

people.mozilla.org/~jorendorff/es6-draft.html#sec-triggerpromisereactions and people.mozilla.org/~jorendorff/es6-draft.html#sec-promise.prototype.then; search for EnqueueTask("PromiseTasks".

EnqueueTask() step 7 is where the HTML spec would hook in and treat different jobs as ending up in different task queues. Presumably, if we want all promise resolutions to be treated as microtasks, then that step would be overridden to queue a microtask when queueName = 'PromiseTasks', and queue a regular task otherwise (or whatever the other queues need), where that task/microtask would trigger the NextTask magic to run the actual job.

(As far as I can tell, in an HTML implementation the only queue name that is used is "PromiseTasks" currently, so maybe EnqueueTask() step 7 would just always queue a microtask. The only other queue name used in the ES spec currently is "ScriptTasks", but that one is never called in a browser environment, according to the discussion in the other fork of this thread, where I was talking about this with Allen.)

# Ian Hickson (3 years ago)

On Tue, 10 Jun 2014, Allen Wirfs-Brock wrote:

Regarding, Domenic's and Boris responses, I don't see why ES6 promise related Jobs need to be translated into HTML Tasks/Microtasks at all.
The ES6 spec. takes care of creating and queueing its promise related Jobs. The only thing HTML needs to worry about is specify when the ES "PrimiseJobs" queue is serviced in relationship to any other ES Job queues it may use. That means the the HTML scheduling algorithm may impose a scheduling priority of promise Jobs relative to various kinds of HTML Tasks/MicroTask. But it doesn't mean that that promise Jobs have any of the other semantic characteristics of those HTML abstractions.

Well presumably if promise resolution job "enqueings" are interleaved with, e.g., table sorting microtasks queueings, they'd need to be executed in that order. So at some point they need to actually interleave with non-ES-driven microtasks.

# Allen Wirfs-Brock (3 years ago)

On Jun 10, 2014, at 7:53 PM, Ian Hickson wrote:

EnqueueTask() step 7 is where the HTML spec would hook in and treat different jobs as ending up in different task queues. Presumably, if we want all promise resolutions to be treated as microtasks, then that step would be overridden to queue a microtask when queueName = 'PromiseTasks', and queue a regular task otherwise (or whatever the other queues need), where that task/microtask would trigger the NextTask magic to run the actual job.

No, that's not the intent of the ES design. The EnqueueTask abstract operations takes the name of a specific Job queue as an argument and always places the newly created PendingJob record into the named queue. It's important because the enqueuing order for a specific queue determine the relative ordering of the Jobs in that queue. The whole reason we have a separate queue for promise Jobs is because we need to preserve that execution ordering.

Step 7 of EnqueueTask is intended for other purposes including managing host environment defined main switches.

(As far as I can tell, in an HTML implementation the only queue name that is used is "PromiseTasks" currently, so maybe EnqueueTask() step 7 would just always queue a microtask. The only other queue name used in the ES spec currently is "ScriptTasks", but that one is never called in a browser environment, according to the discussion in the other fork of this thread, where I was talking about this with Allen.)

No, I think you would still use the "ScriptJobs" queue. It's the only defined way to actually request ES execution of a Script. But you may feed Jobs into it one by one, rather than starting it off with a bunch of pending script execution tasks.

The way I think about it is that HTML schedule queue needs to feed down to ES Job queues because it is the ES Jobs that define the actual execution semantics of ES code. HTML could schedule a microtask into the "PromiseJobs" queue if the microtask needs to be executed after all pending promise Jobs. Or you could define you own ES "MicrotaskJobs" queue and define the ES scheduling relationship between it and the ES "ScriptJobs" and "PromiseJobs" queues.

Finally, not that anything that is internally defined to use promises (for example, module loading phases) will end up getting schedule through the "PromiseJobs" queue as part of the promise resolution processing.

# Ian Hickson (3 years ago)

On Tue, 10 Jun 2014, Allen Wirfs-Brock wrote:

No, that's not the intent of the ES design. The EnqueueTask abstract operations takes the name of a specific Job queue as an argument and always places the newly created PendingJob record into the named queue.
It's important because the enqueuing order for a specific queue determine the relative ordering of the Jobs in that queue. The whole reason we have a separate queue for promise Jobs is because we need to preserve that execution ordering.

Microtasks also preserve execution ordering.

My point is just that we need to maintain more than just promise callback ordering -- we need to maintain the relative order of promise callbacks and all the other things that trigger microtasks.

No, I think you would still use the "ScriptJobs" queue. It's the only defined way to actually request ES execution of a Script.

As far as I can tell, "ScriptTasks" (or "ScriptJobs") isn't actually used anywhere in the spec except in 8.5 Initialization to queue a job. In particular, nothing in NextTask is sensitive to the precise names of the queues, it just grabs tasks from any job queue.

In practice, since we have to coordinate all the other tasks going on, and since script execution for legacy scripts is not queued up in a job queue but is instead done synchronously from HTML tasks, it seems like the simplest way to actually manage this from the HTML side is to just spoon feed the ES algorithms a single job at a time, so than NextTask only ever has one job to chose from.

This also seems like it would be easiest to implement from browsers, since it means they'd only need one task management system (the HTML event loop), and their requirements with respect to NextTask would boil down to just "run this task", with no need to manage any queues at all.

The way I think about it is that HTML schedule queue needs to feed down to ES Job queues because it is the ES Jobs that define the actual execution semantics of ES code.

Well, we need to feed down to the specific algorithms that set up the execution contxts and realms and so on, sure. But that's separate from the job queues per se, no?

HTML could schedule a microtask into the "PromiseJobs" queue if the microtask needs to be executed after all pending promise Jobs. Or you could define you own ES "MicrotaskJobs" queue and define the ES scheduling relationship between it and the ES "ScriptJobs" and "PromiseJobs" queues.

We already have an event loop mechanism, I don't think it makes sense to just recast the whole HTML mechanism into a JS mechanism. (JavaScript is optional in browsers, after all -- we wouldn't want a browser to simply not start up if the user disabled JS!)

Finally, note that anything that is internally defined to use promises (for example, module loading phases) will end up getting schedule through the "PromiseJobs" queue as part of the promise resolution processing.

Yeah. I'm still wrapping my head around exactly how to integrate the module loading stuff with all the other loading and dependency management that HTML does.

# Allen Wirfs-Brock (3 years ago)

On Jun 10, 2014, at 9:35 PM, Ian Hickson wrote:

Microtasks also preserve execution ordering.

My point is just that we need to maintain more than just promise callback ordering -- we need to maintain the relative order of promise callbacks and all the other things that trigger microtasks.

In the ES spec. I can only deal with things that are known to ES. I need to be able to specify relative ordering of promise Jobs. And I (implicitly) say that the ordering of promise jobs relative to script evaluation jobs is unspecified.

I need to be able to expressed at least those concepts, without referring to specific host concepts, such as microtasks.

As far as I can tell, "ScriptTasks" (or "ScriptJobs") isn't actually used anywhere in the spec except in 8.5 Initialization to queue a job. In particular, nothing in NextTask is sensitive to the precise names of the queues, it just grabs tasks from any job queue.

Yes, "ScriptJobs" essentially provides the default mechanism for a host to feed script execution requests to the ES engine. But, a host really doesn't have to use it. A ScriptEvaluationJob can be placed in any queue and dispatched by NextJob.

In practice, since we have to coordinate all the other tasks going on, and since script execution for legacy scripts is not queued up in a job queue but is instead done synchronously from HTML tasks, it seems like the simplest way to actually manage this from the HTML side is to just spoon feed the ES algorithms a single job at a time, so than NextTask only ever has one job to chose from.

But you would still need to respect ordering relationships ES imposes, such as those for promise Jobs. You could in your NextJob extensions remove all entries from the "PromiseJobs" queue and (while preserving relative ordering) move them into your own scheduler. Then feed them back to ES individually when you've decided that it's time to dispatch them.

This also seems like it would be easiest to implement from browsers, since it means they'd only need one task management system (the HTML event loop), and their requirements with respect to NextTask would boil down to just "run this task", with no need to manage any queues at all.

That seems fine, as long as you preserve the ES specified Job orderings.

Well, we need to feed down to the specific algorithms that set up the execution contxts and realms and so on, sure. But that's separate from the job queues per se, no?

Right, that's essentially what the initial and final non-scheduleing related steps of NextJob takes care of.

We already have an event loop mechanism, I don't think it makes sense to just recast the whole HTML mechanism into a JS mechanism. (JavaScript is optional in browsers, after all -- we wouldn't want a browser to simply not start up if the user disabled JS!)

We have Object.observe coming for ES and there is significant interest in having event-loop constructs as part of the core ES host independent environment. Just like for promises, the ES spec. will have to define their semantics and any scheduling requirements for any associated Jobs in a manner that is independent of HTML or any other host environment.

Ideally, we probably should be designing this stuff in the context of several different host environments. You're the HTML integration point, and I try to keep a command-line JS host in mind. Ideally somebody from a a more complex host such as Node should also be playing along.

Yeah. I'm still wrapping my head around exactly how to integrate the module loading stuff with all the other loading and dependency management that HTML does.

Personally, I'd try to keep it all as local as possible. There are many kinds of resources with their own unique dependency semantics and many levels of abstraction where dependencies can occur. I don't know if it is possible to create a single universal dependency management model.

# Ian Hickson (3 years ago)

On Tue, 10 Jun 2014, Ian Hickson wrote:

On Tue, 10 Jun 2014, Allen Wirfs-Brock wrote:

By an ECMAScript Environment (and this is what Ecma-262 defines, although it doesn't actually use that name) I mean a heap of ECMAScript objects (and related values) that may directly reference (point to) each other and a single thread of execution of ECMAScript code. The environment may include multiple "global objects".

Ok. Sounds like that mays to an event loop, on the HTML side.

That should be quite workable. I'll invoke 8.5 when I create an event loop (with zero scripts), and I'll invoke CreateRealm() and then 8.5.1 when I create a Window.

So I started trying to figure out how this would work, but I'm still having trouble (sorry).

When an event loop is created, we invoke the algorithm in 8.5 Initialization, with step 7 set to obtain zero scripts, right?. Now, the user opens a tab or something, and so a Window object needs to be created. What do I do, exactly? Do I need to create a new realm? New execution context? Both? Do I basically do steps 1-5 of the Initialization steps again? I guess I do nothing else until I see a <script>; then what do I

do? do I create a PendingTask record for the execution of the script, push it to the front of the Task Queue, and let 9.5's NextTask call procede with this new task?

# Ian Hickson (3 years ago)

On Mon, 21 Jul 2014, Ian Hickson wrote:

On Tue, 10 Jun 2014, Ian Hickson wrote:

On Tue, 10 Jun 2014, Allen Wirfs-Brock wrote:

By an ECMAScript Environment (and this is what Ecma-262 defines, although it doesn't actually use that name) I mean a heap of ECMAScript objects (and related values) that may directly reference (point to) each other and a single thread of execution of ECMAScript code. The environment may include multiple "global objects".

Ok. Sounds like that mays to an event loop, on the HTML side.

That should be quite workable. I'll invoke 8.5 when I create an event loop (with zero scripts), and I'll invoke CreateRealm() and then 8.5.1 when I create a Window.

So I started trying to figure out how this would work, but I'm still having trouble (sorry).

When an event loop is created, we invoke the algorithm in 8.5 Initialization, with step 7 set to obtain zero scripts, right?. Now, the user opens a tab or something, and so a Window object needs to be created. What do I do, exactly? Do I need to create a new realm? New execution context? Both? Do I basically do steps 1-5 of the Initialization steps again? I guess I do nothing else until I see a <script>; then what do I do? do I create a PendingTask record for the execution of the script, push it to the front of the Task Queue, and let 9.5's NextTask call procede with this new task?

Here's my best guess about how to integrate HTML and ES. So far I've only attempted to describe <script> execution, but the rest should follow

pretty straight-forwardly in theory.

When an event loop is created, invoke the algorithm in 8.5 Initialization. Step 7 should obtain zero scripts. This results in 8.4.2 NextTask being invoked. 8.4.2 NextTask is adjusted as follows:

The "implementation defined unhandled exception processing" in step 1 must be the "report an error" logic in the HTML spec.

The "implementation defined manner" for selecting "a non-empty Task Queue" in step 4 is to return execution to the calling algorithm; subsequent logic in the HTML spec will then resume the NextTask algorithm when a new task has been primed.

When a Window or Worker is created, run 8.5 Initialization steps 1-6, except that in 8.5.1 InitializeFirstRealm, "this implementation requires use of an exotic object object to serve as realm’s global object", namely, the Window or WorkerGlobalScope object. Then, suspend the execution context. Stash the realm in the script settings object for the Window.

When you load a <script>, the browser fetches the file, gets the body, decodes it to Unicode, and then creates a PendingTask record whose [[Task]] is ScriptEvaluationTask, whose [[Arguments]] consists of a list with one member, the Unicode characters obtained earlier, and the [[Realm]] is the object stashed in the script settings object. That record is put in the Task Queue, and then the NextTask algorithm is resumed.

Does anyone see anything problematic here? Does it look ok?

# Allen Wirfs-Brock (3 years ago)

On Jul 21, 2014, at 10:49 AM, Ian Hickson wrote:

On Tue, 10 Jun 2014, Ian Hickson wrote:

On Tue, 10 Jun 2014, Allen Wirfs-Brock wrote:

By an ECMAScript Environment (and this is what Ecma-262 defines, although it doesn't actually use that name) I mean a heap of ECMAScript objects (and related values) that may directly reference (point to) each other and a single thread of execution of ECMAScript code. The environment may include multiple "global objects".

Ok. Sounds like that mays to an event loop, on the HTML side.

That should be quite workable. I'll invoke 8.5 when I create an event loop (with zero scripts), and I'll invoke CreateRealm() and then 8.5.1 when I create a Window.

So I started trying to figure out how this would work, but I'm still having trouble (sorry).

When an event loop is created, we invoke the algorithm in 8.5 Initialization, with step 7 set to obtain zero scripts, right?. Now, the user opens a tab or something, and so a Window object needs to be created. What do I do, exactly? Do I need to create a new realm? New execution context? Both? Do I basically do steps 1-5 of the Initialization steps again? I guess I do nothing else until I see a <script>; then what do I do? do I create a PendingTask record for the execution of the script, push it to the front of the Task Queue, and let 9.5's NextTask call procede with this new task?

The abstract operation InitializeFirstRealm is really about setting up the initial environment that will run for actual"user" script code. In other words it is what you would want to set up when the first tab or whatever is opened. So if there is no ES code to execution prior to that first user action then you might defer the whole 8.5 initialization process until then. However, if there is some other way to acquire and execute ES code prior to such a user action (for example, FF chrome code, a startup script, etc.) when you would have to do 8.5 initialization earlier. You might use the "first Realm" for that code or you might use the "first Realm" as sort of system utility realm, if you have a use for such a thing.

The ES spec. currently only has two places a a complete new Realm is created and initialized with a new global object, etc. The places are 8.5.1 InitializeFirstRealm and 26.2.1.1 the Reflect.Realm constructor. However, 26.2.1.1 would normally be invoked from ES code. 8.5.1 is perhaps misnamed as it provides the default steps that a host would use to initialize any host created realm. In other words, for each window/tab you probably want to follow the steps of 8.5.1 to initialize the associated realm. It sounds like I need to give InitializeFirstRealm a better name, such as InitializeHostDefinedRealm.

You're right that for each new host created realm you want to repeat steps 1-5 of 8.5. You don't need to have an empty execution context stack to do that initialization although that might actually be the case if the engine is idling waiting for some user initialized action. You're also correct about handling scripts. For each <script> that is ready to be processed (the source code has been retrieved) you just enqueue a PendingJob record for a ScriptEvaluationJob (15.1.9) with the realm for the job set to the realm that the <script> runs within. Again, walking through this I can see that I should probably do a little refactoring to make these steps clearer.

# Ian Hickson (3 years ago)

On Mon, 21 Jul 2014, Allen Wirfs-Brock wrote:

Yes, this is pretty much what I had in mind.

Cool, thanks.

I mentioned in other message, I can refractor things a bit to make it a bit easier to express.

Cool, ok. Let me know when I should start speccing things on my end.

However, Realms don't provide the isolation that is required for different origin documents. See the discussion at dslomov-chromium/ecmascript-structured-clone#7

I think this is confusing two things: the same-origin policy, and event loops. Multiple documents with different effective script origins can (and frequently do) share one event loop, with script from one origin on the stack below script from another origin. In single-process browsers, there's only one event loop, even though they support cross-origin iframes, tabs, etc. In fact, to make it worse, scripts can on-the-fly change their origin using document.domain. Exactly how this works isn't exactly defined yet, but the work to define this is described here:

www.w3.org/Bugs/Public/show_bug.cgi?id=20701

It's defined at a level slightly above ES itself. It doesn't re-use the "realm" machinery per se. What prevents two realms from different origins from ever sharing anything isn't anything in ES, it's just that we never actually provide a way for references to make it across (except in edge cases involving document.domain manipulation, though those only allow it for what we call "similar origins").

Event loops, though, are true isolation. If a browser has two documents in two different event loops, they can never share anything. They have different heaps, stacks, etc.

Structured cloning was invented to allow data to be passed between event loops. However, even with one event loop, you still need structured cloning to tranfser data between realms sometimes, because the Web platform logically isolates them, as discussed above.

# Ian Hickson (3 years ago)

On Mon, 21 Jul 2014, Allen Wirfs-Brock wrote:

So if there is no ES code to execution prior to that first user action then you might defer the whole 8.5 initialization process until then.

Well, loading an HTML file involves manipulating the Window global object, so I need the realm initialised before I start that.

However, if there is some other way to acquire and execute ES code prior to such a user action (for example, FF chrome code, a startup script, etc.) when you would have to do 8.5 initialization earlier. You might use the "first Realm" for that code or you might use the "first Realm" as sort of system utility realm, if you have a use for such a thing.

Those are out of scope of the HTML spec. I think the realm created by 8.5, in the context of HTML, will never be used. (I expect implementations just won't create one, in practice, but that's an implementation detail.)

It sounds like I need to give InitializeFirstRealm a better name, such as InitializeHostDefinedRealm. [...] Again, walking through this I can see that I should probably do a little refactoring to make these steps clearer.

Thanks, that would be great.

For each <script> that is ready to be processed (the source code has been retrieved) you just enqueue a PendingJob record for a ScriptEvaluationJob (15.1.9) with the realm for the job set to the realm that the <script> runs within.

Do you have any opinion on how I should handle attribute event handlers? They are conceptually FunctionBodys with specific parameters, and they are parsed the first time they are invoked, but can be reinvoked later without being reparsed. Currently the HTML spec hand-waves this using "code entry points" but those don't really map to anything in ES.

These are the relevant algorithms:

Parsing: www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#getting-the-current-value-of-the-event-handler

Execution: www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#the-event-handler-processing-algorithm

How should I map this to ES6?

# Allen Wirfs-Brock (3 years ago)

On Jul 22, 2014, at 12:32 PM, Ian Hickson wrote:

On Mon, 21 Jul 2014, Allen Wirfs-Brock wrote:

So if there is no ES code to execution prior to that first user action then you might defer the whole 8.5 initialization process until then.

Well, loading an HTML file involves manipulating the Window global object, so I need the realm initialised before I start that.

At the implementation level it may make sense to distinguish between the global Window state and the actual ES Window object.

Don't know whether there might be a reason to do this at the spec. level.

However, if there is some other way to acquire and execute ES code prior to such a user action (for example, FF chrome code, a startup script, etc.) when you would have to do 8.5 initialization earlier. You might use the "first Realm" for that code or you might use the "first Realm" as sort of system utility realm, if you have a use for such a thing.

Those are out of scope of the HTML spec. I think the realm created by 8.5, in the context of HTML, will never be used. (I expect implementations just won't create one, in practice, but that's an implementation detail.)

Or use it for the first window.

Do you have any opinion on how I should handle attribute event handlers? They are conceptually FunctionBodys with specific parameters, and they are parsed the first time they are invoked, but can be reinvoked later without being reparsed. Currently the HTML spec hand-waves this using "code entry points" but those don't really map to anything in ES.

You say: "Event Handler content attributes ... match the FunctionBody production after automatic semicolon insertion." Are you trying to say something special about ASI,. For example, that ASI is not applied when parsing attribute event handlers. Or are you just saying that the normal rules of ASI apply. If the latter, than you probably don't need to say anything because ASI is part of the ES parsing process. If you really mean that ASI rules are not applied you need to be more explicit about that (and it probably raises issues of ES spec. integration).

Also, you defined "internal raw uncompiled handler" as containing a "uncompiled script body". However, in the ES6 spec. ScriptBody is an actual grammar production that is different from FunctionBody. people.mozilla.org/~jorendorff/es6-draft.html#sec-scripts Everything else in this section of your spec. seems to be saying that event handlers are function bodies, so this is hopefully just a terminology issue.

I notice that you currently (step 8 of getting current value of event handler) you parse the function body in isolation from a function expression header. You can't really do that in ES6 as there are early error rules at the level of FunctionExpression that need to be considered with the body. I think, you need to wrap the FunctionBody with the boilerplate source code of a FunctionExpression, including an appropriate formal parameter list. And even with that I'm still uncomfortable will how you are trying to manually wireup the scope of the function using the body.

Perhaps a way out of this is to for Annex B of ES6 people.mozilla.org/~jorendorff/es6-draft.html#sec-additional-ecmascript-features-for-web-browsers to actually define the syntax and semantics of an AttributeEventHandler function and provide abstract the operations you can call to create one. I imagine that we would want to process the creation of these functions similar to an eval call where we synchronously parse/compile and do not go through the async ScriptEvaluationJob mechanism.

I didn't see where in the process of invoking an event handler that you call the [[Call]] internal method of the callback function. This is essential for setting up the local environment of the function you are invoking. You also need to handle any exceptions that come back from the [[Call]]. BTW, I'm also assuming that a batch of events would be handled as a single ES job and that the abstract operation for that job would sequence through setup the the script settings for each event handler and then call it.

Finally, and a bit of an aside, I find it somewhat confusing that there are entities you call objects (for example, script settings objects) that don't seem to actually need to be exposed as ECMAScript objects. It causes me to be continuously asking myself whether something is a real ES object or just part of the specification/platform state that ES code never directly sees. In the ES spec. we deal with this by distinguishing between records and objects. Where records corresponds to state that is never directly exposed to ES code.

Overall, my sense is that we are inching in a good direction but that there is a fair amount of work that is still need to enable the HTML and ES specs to smoothly plug together.

# Boris Zbarsky (3 years ago)

On 7/22/14, 7:21 PM, Allen Wirfs-Brock wrote:

I didn't see where in the process of invoking an event handler that you call the [[Call]] internal method of the callback function.

Yeah, this part needs clarification. Something in here needs to explicitly invoke heycam.github.io/webidl/#es-invoking-callback-functions which will do the [[Call]] bits.

You also need to handle any exceptions that come back from the [[Call]].

This is a bit of a mess in general. :( What should happen, more or less, is that this code just propagates the exception and event dispatch then catches-and-reports it before moving on to the next event listener. The DOM spec doesn't seem to do a very good job of describing what it does with exceptions...

BTW, I'm also assuming that a batch of events would be handled as a single ES job

Hmm... event dispatch can happen synchronously from script like so:

target.dispatchEvent(new Event("foo"));

which will trigger all event listeners for "foo" on the target before the dispatchEvent call returns.

So we're starting out in an ES job here; are you saying the dispatchEvent call creates a new one?

Overall, my sense is that we are inching in a good direction but that there is a fair amount of work that is still need to enable the HTML and ES specs to smoothly plug together.

Agreed.

# Allen Wirfs-Brock (3 years ago)

On Jul 22, 2014, at 7:14 PM, Boris Zbarsky wrote:

BTW, I'm also assuming that a batch of events would be handled as a single ES job

Hmm... event dispatch can happen synchronously from script like so:

target.dispatchEvent(new Event("foo"));

which will trigger all event listeners for "foo" on the target before the dispatchEvent call returns.

So we're starting out in an ES job here; are you saying the dispatchEvent call creates a new one?

No, synchronous dispatchEvent looks like it could just work depending upon how the browser specific contextual state (origin, etc. scripting settings, etc. in the HTML spec.) is modeled. Currently we have a [[HostDefined]] field in a Job record where, based on a previous conversation, you could stash that state when running a script. If dispatchEvent is going to synchronously dispatch event handlers it may have to do browser context switch for each handler. How does it know to do this? Perhaps we also need a [[HostDefined]] field in Realm records? (Each function is associated with a realm, so it is a good place to put context that is shared by all functions for a specific realm).

In my original comment above I was thinking about handling asynchronous events. I was assuming that you would create a separate job that would fire the handlers triggered async events.

# Boris Zbarsky (3 years ago)

On 7/23/14, 12:02 PM, Allen Wirfs-Brock wrote:

No, synchronous dispatchEvent looks like it could just work depending upon how the browser specific contextual state (origin, etc. scripting settings, etc. in the HTML spec.) is modeled.

It's modeled as "settings objects" (settings records, if you prefer). Mostly. "origin" and "effective script origin" are computed from stuff in the settings record.

If dispatchEvent is going to synchronously dispatch event handlers it may have to do browser context switch for each handler. How does it know to do this?

Web IDL callbacks store the info they need to set up the call.

Perhaps we also need a [[HostDefined]] field in Realm records? (Each function is associated with a realm, so it is a good place to put context that is shared by all functions for a specific realm).

In practice, each Realm has a unique global and the HTML spec ends up hanging its stuff off there as far as I can tell.

# Allen Wirfs-Brock (3 years ago)

On Jul 23, 2014, at 9:31 AM, Boris Zbarsky wrote:

On 7/23/14, 12:02 PM, Allen Wirfs-Brock wrote:

No, synchronous dispatchEvent looks like it could just work depending upon how the browser specific contextual state (origin, etc. scripting settings, etc. in the HTML spec.) is modeled.

It's modeled as "settings objects" (settings records, if you prefer). Mostly. "origin" and "effective script origin" are computed from stuff in the settings record.

If dispatchEvent is going to synchronously dispatch event handlers it may have to do browser context switch for each handler. How does it know to do this?

Web IDL callbacks store the info they need to set up the call.

Perhaps we also need a [[HostDefined]] field in Realm records? (Each function is associated with a realm, so it is a good place to put context that is shared by all functions for a specific realm).

Yes, but how does that then map into the ES invocation model. If even handlers are just ordinary ES functions with an ordinary [[Call]] how do you ensure that the necessary browser context is established when they are invoked from an arbitrary place?

In practice, each Realm has a unique global and the HTML spec ends up hanging its stuff off there as far as I can tell.

I added [[HostDefined]] to jobs after we had a conversation that I believe was about maintaining a dynamic stack of script origins as code executes. At the time, you indicated tht you thought it was a sufficient hook. Do you still think that? It's not clear to me how what we are discussing now relates to that.

# Boris Zbarsky (3 years ago)

On 7/23/14, 12:45 PM, Allen Wirfs-Brock wrote:

Yes, but how does that then map into the ES invocation model. If even handlers are just ordinary ES functions with an ordinary [[Call]]

They're not. They're Web IDL callback objects constructed from such ES functions. So this would be handled by heycam.github.io/webidl/#es-invoking-callback-functions and the "callback context" bits it talks about, I would htink.

I added [[HostDefined]] to jobs after we had a conversation that I believe was about maintaining a dynamic stack of script origins as code executes. At the time, you indicated tht you thought it was a sufficient hook. Do you still think that?

I think so, yes

It's not clear to me how what we are discussing now relates to that.

Me neither, honestly. :( There are too many pieces here, all of them changing in parallel, and I'm not quite sure how they fit together right this second. :( I'm hoping Ian is keeping track of all of them and will figure out how they interact.

# Allen Wirfs-Brock (3 years ago)

On Jul 23, 2014, at 9:52 AM, Boris Zbarsky wrote:

On 7/23/14, 12:45 PM, Allen Wirfs-Brock wrote:

Yes, but how does that then map into the ES invocation model. If even handlers are just ordinary ES functions with an ordinary [[Call]]

They're not. They're Web IDL callback objects constructed from such ES functions. So this would be handled by heycam.github.io/webidl/#es-invoking-callback-functions and the "callback context" bits it talks about, I would htink.

Earlier in this thread we were originally talking about "event handler content attributers" and the possibility of doing something in ES Annex B to help define them. But if they are WebIDL exotic functions then maybe that doesn't make so much sense.

I added [[HostDefined]] to jobs after we had a conversation that I believe was about maintaining a dynamic stack of script origins as code executes. At the time, you indicated tht you thought it was a sufficient hook. Do you still think that?

I think so, yes

It's not clear to me how what we are discussing now relates to that.

Me neither, honestly. :( There are too many pieces here, all of them changing in parallel, and I'm not quite sure how they fit together right this second. :( I'm hoping Ian is keeping track of all of them and will figure out how they interact.

My sense is that what we are missing is an "architecture" that actually defines how HTML and ES integrates.

# Ian Hickson (3 years ago)

On Tue, 22 Jul 2014, Allen Wirfs-Brock wrote:

Do you have any opinion on how I should handle attribute event handlers? They are conceptually FunctionBodys with specific parameters, and they are parsed the first time they are invoked, but can be reinvoked later without being reparsed. Currently the HTML spec hand-waves this using "code entry points" but those don't really map to anything in ES.

(Just to clarify: the text in the HTML spec right now is clearly bogus and needs rewriting. My questions here are just an attempt to find out what it should be rewritten to.)

You say: "Event Handler content attributes ... match the FunctionBody production after automatic semicolon insertion." Are you trying to say something special about ASI,. For example, that ASI is not applied when parsing attribute event handlers. Or are you just saying that the normal rules of ASI apply.

I mean that you take the FunctionBody production, adjust it to include the logic for automatic semicolon insertion, and then that's what an Event Handler content attribute needs to match. Note that the text you quote here is a document conformance criteria, not a user-agent conformance criteria, so it doesn't imply anything about what browsers do.

If the latter, than you probably don't need to say anything because ASI is part of the ES parsing process.

What I'm trying to say in the text you quote is whether or not something is valid. I can't just say that it has to match the FunctionBody production, because when ES parses it inserts semicolons, so the strings don't always actually match the productions per se. I could also phrase it using terminology more like what ScriptEvaluationJob step 2 does, would that be better? I'd ideally like to avoid having to mention either semicolons or early errors or any of that stuff.

Also, you defined "internal raw uncompiled handler" as containing a "uncompiled script body". However, in the ES6 spec. ScriptBody is an actual grammar production that is different from FunctionBody.

"uncompiled script body" is an opaque term unrelated to "ScriptBody".

I notice that you currently (step 8 of getting current value of event handler) you parse the function body in isolation from a function expression header. You can't really do that in ES6 as there are early error rules at the level of FunctionExpression that need to be considered with the body. I think, you need to wrap the FunctionBody with the boilerplate source code of a FunctionExpression, including an appropriate formal parameter list.

I can't do that, because that would enable people to do things like end their code with a "//" and have it comment out the trailing "}", or put a "} function () {" in the middle of their code and have it somehow parsed into two functions, or whatnot. In general I think trying to take the author's input and manipulate it ends up being a really dangerous practice. Better to imply it somehow in prose, IMHO.

And even with that I'm still uncomfortable will how you are trying to manually wireup the scope of the function using the body.

Me too.

Perhaps a way out of this is to for Annex B of ES6 people.mozilla.org/~jorendorff/es6-draft.html#sec-additional-ecmascript-features-for-web-browsers to actually define the syntax and semantics of an AttributeEventHandler function and provide abstract the operations you can call to create one.

That would be fantastic, sure! Is that an option?

I imagine that we would want to process the creation of these functions similar to an eval call where we synchronously parse/compile and do not go through the async ScriptEvaluationJob mechanism.

Well, the difficult thing here is that the parsing and the execution have to be quite separate. The parsing has to happen just once. If it happens as part of event handling, then that will also involve execution; but it can also happen as part of just the author getting the value of the handler. In either case, if the value is subsequently fetched, the same Function object must be returned each time. Also, when creating the Function object it's important that we construct the lexical scope carefully, and the arguments differ based on context.

When it comes to executing it, it should just be equivalent to normal browser-to-script function callbacks.

If you can provide a mechanism that parses the function body, I'd be happy to defer to it. The inputs to this would be the string to parse as the function body, the names of the argument(s), and a Lexical Environment. The output would be a Function object or an error.

I didn't see where in the process of invoking an event handler that you call the [[Call]] internal method of the callback function.

That's the open issue that says "In this step, invoke means to run the jump to a code entry-point algorithm". The "jump to a code entry-point" algorithm is here:

www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#jump-to-a-code-entry-point

The line that calls [[Call]] is "Make the appropriate script execution environment specified by context execute the s's code entry-point". I can't actually mention [[Call]] explicitly because it might not be JavaScript that I'm executing.

I'm hoping we can more explicitly glue this together at some point, maybe with WebIDL defining a generic term that is then explicitly mapped to [[Call]] in the ECMAScript/WebIDL binding in the WebIDL spec.

BTW, I'm also assuming that a batch of events would be handled as a single ES job and that the abstract operation for that job would sequence through setup the the script settings for each event handler and then call it.

Nah, that's all handled by the DOM spec. It can't be all a single ES job because, if nothing else, it could be interleaving ES and non-ES handlers.

Finally, and a bit of an aside, I find it somewhat confusing that there are entities you call objects (for example, script settings objects) that don't seem to actually need to be exposed as ECMAScript objects.

Unfortunately the English language has too few nouns. :-) This problem occurs all the time. For example, ES uses the term "element" for things that aren't HTML Elements; CSS uses "properties" for things that aren't JS properties; the word "attribute" is used for both WebIDL attributes and HTML content attributes, which are distinct even though there's usually a 1:1 mapping between them; the term "media type" means something different in a MIME context than a CSS context, the term "selector" is used in the ES grammar to mean something unrelated to CSS Selectors; the word "resource" means something different in almost every Web spec; the word "character" sometimes means multiple different things within a single spec (and rarely does it mean what it sounds like it means -- ES is a particularly prominent offender in that realm!); the terms "user" and "author" mean different things in different specs, etc...

As far as "object" goes, you can pretend that all things called "objects" in the HTML spec are ES Objects of one kind or another, and it's just that some of them aren't exposed to author script.

# Boris Zbarsky (3 years ago)

On 7/23/14, 1:29 PM, Allen Wirfs-Brock wrote:

Earlier in this thread we were originally talking about "event handler content attributers" and the possibility of doing something in ES Annex B to help define them. But if they are WebIDL exotic functions then maybe that doesn't make so much sense.

No, no. They're actual honest to God ES functions. You can get them from page script and call them as functions, etc. And we need to define how those ES functions are created given the input, which is a string for the function body.

It's just that during event dispatch they're invoked via a Web IDL EventHandler which handles things like invoking their [[Call]] and the like.

My sense is that what we are missing is an "architecture" that actually defines how HTML and ES integrates.

Yep.