simpler, sweeter syntax for modules

John J Barton johnjbarton at johnjbarton.com
Fri Mar 23 08:06:08 PDT 2012


On Thu, Mar 22, 2012 at 10:32 AM, Brendan Eich <brendan at mozilla.org> wrote:

> John J Barton wrote:
>
>> I guess you mean:  a special form evaluated before the outer function
>> runs? Surely this form is not off-line.
>>
> No, before anything in the containing Program (up to the <script>
> container) runs. Modules are prefetched, not loaded by a nested event loop
> that violates run-to-completion (or unthinkable: starves the
> same-page-context UI to preserve r-t-c by queueing events).


I replied to this once already, learning a bit more about async load and
learning that import is only valid at the top level. However, I am still
confused on the runtime model for import.

Brendan, your argument above makes it sound like
   import x from "Bar.js"
does not block and thus would not starve the UI rendering. How can that be?

Here is my model for what has to happen:

The browser parses the html document and encounters the <script> tag; UI
progress stops.
It passes the tag contents to the JS engine which encounters the import
statement.
Bar.js is fetched; UI progress is blocked.
Next we parse Bar.js for imports and pre-fetch the modules and recurse; UI
progress is blocked.
Once we reach the end of the DAG we compile the first module and execute
its outer function.
Then the UI progress continues.

The browser's JS engine has no way to know which dependencies to load
without parsing the dependents. So it has to load all of the dependencies
before continuing. The load behavior will be just like <script> tags today.

To avoid starving the UI thread, developers must load the first module
within each subsystem with system.load() calls, not imports.  Based on our
experience with require.js, we will have to either change the specification
of the "load" event or develop a set of ad hoc practices to deal with the
race between the asynchronous script loading and the UI load.  Any JS
intended to run on 'load' must block the UI.

If import semantics allowed control-flow to select modules, then the total
time the UI would be blocked would be not more and could be less than the
current definition. This is simply because the control-flow selection could
load less code.

If the model above is correct, I don't see how UI
starvation/run-to-completion has any role in selecting the import
semantics, other than favoring control-flow selection.

On the other hand, now that it is clear that developers will need to
carefully apply system.load() anyway, that tool will deal with control-flow
selection of modules. Limiting 'import' to top level simplifies and helps
organize reading the code.
It also makes developers who come from static language backgrounds more
comfortable since variables will be er less variable ;-).

Again if this model is correct, then I think ES should *not* specify module
load timing. That is, the spec should not insist that all modules are
fetched and analyzed before the first one is compiled and run.  The
control-flow-free import semantics allows pre-fetch but it also allows
loading to be interleaved with compile and execution. That would be very
desirable for performance.  Perhaps there are other reasons to force
pre-fetch?

Is the model above not correct?

jjb
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120323/789d56c2/attachment.html>


More information about the es-discuss mailing list