Module naming and declarations

classic Classic list List threaded Threaded
152 messages Options
1234 ... 8
Reply | Threaded
Open this post in threaded view
|

Module naming and declarations

Andreas Rossberg-4
The module proposal has made good progress, thanks to the hard work by
Dave & Sam. I'm glad to see it close to the home stretch for the ES6
race (some healthy minor controversies on the side notwithstanding :)
).

However, there is one central part of the design over which we still
do not have agreement: the naming and declaration mechanism for
modules. We did not yet have a serious discussion about it -- and I
fully admit this being my fault as well, since despite my repeated
criticism, I hadn't found the time to put that in a coherent form. I
try to make up for that with this post. :) Summary is that I still
(strongly) believe that adopting what's currently on the table would
be a severe mistake, and that it's best to take a step back and
discuss the motivation as well as alternatives.

My sincere apologies for the excessively long post...


** The problem **

In the original module proposal, modules were declared via ordinary
lexical identifiers, but could also be imported from external sources
denoted by strings. In November, the proposal was changed to use
string-valued "module ids" for both. The motivation was to simplify
the language, and to provide better support for configuration and
concatenation.

Unfortunately, the new scheme leads to a significant conflation of
concerns. In particular, it tries to obscure the fact that there are
fairly fundamental differences between _internal_ names and _external_ ones:

- internal names reference _language entities_, external names
reference _resources_;
- internal references are under control of the language, while
external references are delegated to a platform mechanism (with
potentially platform-dependent interpretations and behaviour);
- internal references are definite, stable, and high-integrity, while
external references are indefinite, late-bound, and can fail or be
clobbered.

As an analogy, take strings. A string may exist inside the language,
as a value bound to a variable. Or it may be stored in some file that
you can access via a file name. Both the variable and the file name
ultimately reference "a string", but in completely different worlds.
Nobody would suggest to use file paths in place of variable
identifiers internally. Yet, that is almost exactly what the proposal
does for modules!

Conflating the two notions may seem tempting and convenient at first,
but it's bad. In the case of the current ES module proposal in
particular, the attempt to do so with the "module id" scheme has all
kinds of awkward consequences:

* As an internal naming mechanisms, it lacks standard scoping semantics.

  As various discussions show, people want and expect scope chain
behaviour, and for very good reasons: e.g. nesting modules, confining
modules to local scope, convenient local names, etc. The module id
approach cannot sanely support that (which is why e.g. nested modules
got pulled from the proposal).

* As an external naming mechanisms, it violates standard relative
path/URL semantics.

  When using paths to actually reference external names, one might
likewise expect certain semantics, e.g., that "a" and "./a" refer to
the same thing, like they usually do on the web or in a file system.
The current mechanism intentionally breaks with this via a
non-standard interpretation of "paths". It implies that a set of
module files, by default, is not relocatable within a project tree, or
across project trees, as the standard idiom for module names actually
denotes semi-absolute paths within a project tree. The main reason for
it is that paths are overloaded to serve both internal and external
naming. (The path semantics is inherited from legacy module frameworks
for JS, such as AMD. It is a fine solution under the constraints that
these frameworks have to operate in -- in particular, the inability to
extend syntax or add new primitives. However, for ES6 most of these
constraints don't apply, and there is no particular reason to limit
the design to making the same compromises.)

* The shared name space between internal and external modules can lead
to incoherent programs.

  Internal and external module definitions can resolve to the same
path. For example. there might be a definition, somewhere, for module
"a/b", but also a file "a/b.js". Which one takes precedence generally
depends on the execution order of a (staged) program (e.g., when
_other_ imports are performed), and can, in fact, differ at different
points in time. It is worth noting that, presumably for this reason,
AMD strongly discourages the use of named module declarations, except
by optimization tools (and Node does not support it at all, AFAICT).
With the ES proposal, however, nifty syntax strongly conveys the
impression that named module declarations are a good and recommended
feature to use manually, instead of discouraging their day-to-day use.

* Likewise, a single global name space for all internally defined
modules can lead to incoherent programs.

  Several internally defined modules can clash arbitrarily, there is
nothing preventing two completely unrelated modules in completely
unrelated files from clobbering the same name and stepping on each
other's feet. Worse, there is no way to confine a module to a local
scope, all definitions _have to be_ globally visible and compete
within the same global name space. (And unlike URLs, this name space
is not particularly structured.) Of course, conventions can help to
work around the problem in practice, but clearly, a well-designed
language mechanism is preferable and more reliable.

* "Local" references are globally overridable.

  Since every reference goes through the loader, there is no way to
have a definite (i.e., static, stable) module reference, even within a
single script or scope. Any other script can come by and _modify the
meaning_ of any seemingly local module reference, either accidentally
or intentionally (unless laboriously sandboxed). This clearly is bad
for abstraction, encapsulation, integrity, security, and all related
notions. And to add insult to injury, the loader also induces
non-trivial runtime cost for a mechanism that isn't even desirable in
these cases. Plain and simple, we repeat the mistake of the JS global
object, but worse, because there is no other scope for modules to
escape to if you care about integrity.

* Internal module definition is coupled with external module
registration, and modules cannot be renamed or re-registered.

  It is not possible to define a module without registering it
globally, and dually, it is not possible to register a module without
defining a new one. In particular, that prevents renaming a module,
and more importantly, registering a module under a different
(external) name than the one under which it was defined/imported. The
latter, however, is needed for some configuration use cases. (In the
current proposal, it has to be simulated awkwardly by "eta-expanding"
the renamed module, i.e., declaring "module 'A' { export * from 'B';
}", which creates a separate module.)

* Language-level naming semantics interferes with file system/URL
naming semantics.

  As other communities have rediscovered many times before, it is a
problem to naively map between internal and external names, because
the meaning of internal definitions or references may then depend on
idiosyncrasies of the hosting environment. For example, it may affect
the program behaviour whether names are case-sensitive in the OS (not
all JS hosts are browsers), or what makes a well-formed file name.
What if you define a module "M" and also have a file "m.js"? Something
else in node.js on Windows than on Linux, potentially. It is best to
minimise the problem by limiting the use of external names to actual
external references.

* Bundling ("concatenation") generally would require embedding
arbitrary string resources, not syntactic modules.

  One powerful feature of loaders is the translation hook. When
importing a module from an external source, there is no restriction on
its syntactic content, since a translation hook can transform it
freely. But if one were to bundle ("concatenate") an application that
actually makes use of this liberty, then the current proposal could
not actually support that consistently. Consequently, if one primary
goal the current proposal is to make module declarations a mechanism
for bundling modules, then they are an incomplete solution. In
general, you'd need to be able to embed arbitrary _resources_ (as
strings), and be able to run translate hooks on those.

* Module "declarations" are not a declarative mechanism, but an operational one.

  Because module declaration is coupled with loader registration, it
has a non-trivial operational effect, and its semantics is in turn
subject to interference from other operational effects from inside and
outside the program (as described above). Yet, it is disguised in a
seemingly innocent declarative syntax. That is likely to create
pitfalls and wrong assumptions (again, like with the global object).


In summary, not only do path-named module declarations lack desirable
expressiveness, regularity, and integrity, they also do not support
more interesting configuration and concatenation use cases, which is
what they were intended for.

Most of the above problems cannot be fixed without adding lexically
scoped modules to the language. It seems very clear that we need
those, rather sooner than later. Also, I think we want a more
structured approach to the global name space for external modules. At
that point, rethinking the proposed approach may be the best idea.


** Proposal **

I think it is highly advisable to follow a simple strategy for the
whole naming business: avoid ad-hoc inventions, stick to
well-established, standard mechanisms.

Specifically:

1. Have a clean separation of concerns between internal and external names.
2. For internal names, use the standard language mechanism: lexical scope.
3. For external names, use the standard web mechanism: URLs.
4. Have a clean separation of concerns between the declarative
_definition_ of a module, and the operational notion of _registering_
it with a loader.

Let me point out again that both lexical scope and URLs are backed by
decades of experience and have proved superior over and over again, in
many, many different languages and environments. _We can only lose if
we try to do "better"_.

More concretely, I envision using lexical module declarations as the
primary means for defining modules (you guessed that from the start :)
). Modules can nest. (Supporting local modules, like Mark suggested,
is more difficult, because of unclear interactions with other
constructs like classes or eval. Certainly not ES6.)

There may (or may not, see below) be a (separate?) pseudo-declarative
form for registering modules as resources with the loader -- however,
if so, it should ideally scale to handle non-ES sources.

Module resources are identified by URLs. Those can be absolute or
relative; relative URLs are interpreted relative to the importing file
(just like HTML links). The loader table only contains absolute URLs.
Likewise, every script is associated with its absolute URL. Any
relative import is first normalised to absolute using the absolute URL
of the importer (plus obvious steps for normalising occurrences of "."
and "..").

A custom loader can, in principle, perform arbitrary interpretation or
rewriting of URLs. In particular, this could be used to implement
interop to absolute repository paths a la AMD or Node, e.g. by
interpreting an "amd:" schema for importing AMD modules that are
relative to a separately configured base URL. In other words, you'd
write

  import M1 from "a/b";  // native ES6 import, relative path
  import M2 from "amd:c/d";  // import of AMD module, relative to AMD base URL

Should we have a declarative form for registering resources, then its
URL would be resolved in the same manner, relative to the path of the
containing file. However, the programmer is free to use an absolute
URL.

At that point, the only remaining purpose for path-named module
declarations would be registering external references. However,
registration is already possible through the loader API. Doing so
requires additional staging (a script setting up the loader before
executing the actual script). But staging is necessary anyway, for
every slightly more interesting configuration case -- e.g. any
scenario that involves loader.ondemand, translation, etc. It is not
clear to me that the remaining cases justify an additional semantic
short cut, and I think there is a case to be made that path-named
module declarations are neither sufficient _nor_ necessary. But that
point is mostly independent from the rest.

Clearly, there are more details to be discussed and worked out. I also
know that Dave & Sam have been over lots of it before. Still, I'm
positive that it is a fairly solvable problem, and will yield a more
well-behaved and more scalable solution. And yes, essentially it means
reverting this part of the module proposal to its earlier stage -- but
the good news is that not much else in the proposal is affected. :)

/Andreas
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Brian Di Palma
I've been following es-discuss for a short amount of time.
I'm a JS dev working on a significant code base, this biases how I
perceive ES6 issues.

From my viewpoint by far the most important advancements provided by
ES6, eclipsing all others,
are modules and classes. This feeling is widely shared among the
developers I work with.

So I'm somewhat surprised at the lack of response to Andreas email.
Firstly I agree with Andreas point about there being an issue with the
naming and declaring of modules.

|  In the original module proposal, modules were declared via ordinary
|  lexical identifiers, but could also be imported from external sources
|  denoted by strings. In November, the proposal was changed to use
|  string-valued "module ids" for both. The motivation was to simplify
|  the language, and to provide better support for configuration and
|  concatenation.

This seems an odd change to make, a backward one in fact.

I presume that the aim of modules is to provide clean
scopes/environments, to prevent global state pollution and to aid in
structuring/separating code. Therefore you would wish modules to
provide an
abstract identifier as opposed to a concrete file path string as its identifier.

module topLevelNamespace.subNamespace {
   export MyClass {
   }
}

|  Nobody would suggest to use file paths in place of variable
|  identifiers internally. Yet, that is almost exactly what the proposal
|  does for modules!

Indeed. Working on a large code base containing hundreds of JS classes
I think it's cleaner to
deal with abstract identifiers which to correspond to namespaces as
opposed to file
locations on disk.

|  As various discussions show, people want and expect scope chain
|  behaviour, and for very good reasons: e.g. nesting modules, confining
|  modules to local scope, convenient local names, etc.

Yes. If we create private packages in our frameworks/libraries I see
no reason for any end consumer
to have access to these internal artifacts. This is all about working
with large code bases,
privacy and integrity are very helpful in those situations.

|  (The path semantics is inherited from legacy module frameworks
|  for JS, such as AMD. It is a fine solution under the constraints that
|  these frameworks have to operate in -- in particular, the inability to
|  extend syntax or add new primitives. However, for ES6 most of these
|  constraints don't apply, and there is no particular reason to limit
|  the design to making the same compromises.)

To produce such a design purely to serve the needs of old module
systems seems a poor choice to me.
Over time the standard mechanism will eclipse all other module systems
even if it provides no upgrade
path for the old systems purely because it is the standard system. As
long as it is not a totally broken
design. The only time I would be willing to invest learning about the
old module systems would be when
I want to convert an old module to the new system so I can dump the old system.

There is far more code that is not using modules than code that is.

The focus should be on creating the best possible module system not
the best possible system that
smoothly accommodates AMD modules!

|  A custom loader can, in principle, perform arbitrary interpretation or
|  rewriting of URLs. In particular, this could be used to implement
|  interop to absolute repository paths a la AMD or Node, e.g. by
|  interpreting an "amd:" schema for importing AMD modules that are
|  relative to a separately configured base URL. In other words, you'd
|  write
|
|    import M1 from "a/b";  // native ES6 import, relative path
|    import M2 from "amd:c/d";  // import of AMD module, relative to
AMD base URL

Schema handlers for non standard resources seems like an excellent idea.
Neat, clean and easy to identify. I would support that, it could also
be used to load non JS resources.

Thank you Andreas for highlighting these niggles I do hope there is
more interest in them then the lack of response indicates.

- Brian Di Palma.

On Wed, Apr 24, 2013 at 1:28 PM, Andreas Rossberg <[hidden email]> wrote:

> The module proposal has made good progress, thanks to the hard work by
> Dave & Sam. I'm glad to see it close to the home stretch for the ES6
> race (some healthy minor controversies on the side notwithstanding :)
> ).
>
> However, there is one central part of the design over which we still
> do not have agreement: the naming and declaration mechanism for
> modules. We did not yet have a serious discussion about it -- and I
> fully admit this being my fault as well, since despite my repeated
> criticism, I hadn't found the time to put that in a coherent form. I
> try to make up for that with this post. :) Summary is that I still
> (strongly) believe that adopting what's currently on the table would
> be a severe mistake, and that it's best to take a step back and
> discuss the motivation as well as alternatives.
>
> My sincere apologies for the excessively long post...
>
>
> ** The problem **
>
> In the original module proposal, modules were declared via ordinary
> lexical identifiers, but could also be imported from external sources
> denoted by strings. In November, the proposal was changed to use
> string-valued "module ids" for both. The motivation was to simplify
> the language, and to provide better support for configuration and
> concatenation.
>
> Unfortunately, the new scheme leads to a significant conflation of
> concerns. In particular, it tries to obscure the fact that there are
> fairly fundamental differences between _internal_ names and _external_ ones:
>
> - internal names reference _language entities_, external names
> reference _resources_;
> - internal references are under control of the language, while
> external references are delegated to a platform mechanism (with
> potentially platform-dependent interpretations and behaviour);
> - internal references are definite, stable, and high-integrity, while
> external references are indefinite, late-bound, and can fail or be
> clobbered.
>
> As an analogy, take strings. A string may exist inside the language,
> as a value bound to a variable. Or it may be stored in some file that
> you can access via a file name. Both the variable and the file name
> ultimately reference "a string", but in completely different worlds.
> Nobody would suggest to use file paths in place of variable
> identifiers internally. Yet, that is almost exactly what the proposal
> does for modules!
>
> Conflating the two notions may seem tempting and convenient at first,
> but it's bad. In the case of the current ES module proposal in
> particular, the attempt to do so with the "module id" scheme has all
> kinds of awkward consequences:
>
> * As an internal naming mechanisms, it lacks standard scoping semantics.
>
>   As various discussions show, people want and expect scope chain
> behaviour, and for very good reasons: e.g. nesting modules, confining
> modules to local scope, convenient local names, etc. The module id
> approach cannot sanely support that (which is why e.g. nested modules
> got pulled from the proposal).
>
> * As an external naming mechanisms, it violates standard relative
> path/URL semantics.
>
>   When using paths to actually reference external names, one might
> likewise expect certain semantics, e.g., that "a" and "./a" refer to
> the same thing, like they usually do on the web or in a file system.
> The current mechanism intentionally breaks with this via a
> non-standard interpretation of "paths". It implies that a set of
> module files, by default, is not relocatable within a project tree, or
> across project trees, as the standard idiom for module names actually
> denotes semi-absolute paths within a project tree. The main reason for
> it is that paths are overloaded to serve both internal and external
> naming. (The path semantics is inherited from legacy module frameworks
> for JS, such as AMD. It is a fine solution under the constraints that
> these frameworks have to operate in -- in particular, the inability to
> extend syntax or add new primitives. However, for ES6 most of these
> constraints don't apply, and there is no particular reason to limit
> the design to making the same compromises.)
>
> * The shared name space between internal and external modules can lead
> to incoherent programs.
>
>   Internal and external module definitions can resolve to the same
> path. For example. there might be a definition, somewhere, for module
> "a/b", but also a file "a/b.js". Which one takes precedence generally
> depends on the execution order of a (staged) program (e.g., when
> _other_ imports are performed), and can, in fact, differ at different
> points in time. It is worth noting that, presumably for this reason,
> AMD strongly discourages the use of named module declarations, except
> by optimization tools (and Node does not support it at all, AFAICT).
> With the ES proposal, however, nifty syntax strongly conveys the
> impression that named module declarations are a good and recommended
> feature to use manually, instead of discouraging their day-to-day use.
>
> * Likewise, a single global name space for all internally defined
> modules can lead to incoherent programs.
>
>   Several internally defined modules can clash arbitrarily, there is
> nothing preventing two completely unrelated modules in completely
> unrelated files from clobbering the same name and stepping on each
> other's feet. Worse, there is no way to confine a module to a local
> scope, all definitions _have to be_ globally visible and compete
> within the same global name space. (And unlike URLs, this name space
> is not particularly structured.) Of course, conventions can help to
> work around the problem in practice, but clearly, a well-designed
> language mechanism is preferable and more reliable.
>
> * "Local" references are globally overridable.
>
>   Since every reference goes through the loader, there is no way to
> have a definite (i.e., static, stable) module reference, even within a
> single script or scope. Any other script can come by and _modify the
> meaning_ of any seemingly local module reference, either accidentally
> or intentionally (unless laboriously sandboxed). This clearly is bad
> for abstraction, encapsulation, integrity, security, and all related
> notions. And to add insult to injury, the loader also induces
> non-trivial runtime cost for a mechanism that isn't even desirable in
> these cases. Plain and simple, we repeat the mistake of the JS global
> object, but worse, because there is no other scope for modules to
> escape to if you care about integrity.
>
> * Internal module definition is coupled with external module
> registration, and modules cannot be renamed or re-registered.
>
>   It is not possible to define a module without registering it
> globally, and dually, it is not possible to register a module without
> defining a new one. In particular, that prevents renaming a module,
> and more importantly, registering a module under a different
> (external) name than the one under which it was defined/imported. The
> latter, however, is needed for some configuration use cases. (In the
> current proposal, it has to be simulated awkwardly by "eta-expanding"
> the renamed module, i.e., declaring "module 'A' { export * from 'B';
> }", which creates a separate module.)
>
> * Language-level naming semantics interferes with file system/URL
> naming semantics.
>
>   As other communities have rediscovered many times before, it is a
> problem to naively map between internal and external names, because
> the meaning of internal definitions or references may then depend on
> idiosyncrasies of the hosting environment. For example, it may affect
> the program behaviour whether names are case-sensitive in the OS (not
> all JS hosts are browsers), or what makes a well-formed file name.
> What if you define a module "M" and also have a file "m.js"? Something
> else in node.js on Windows than on Linux, potentially. It is best to
> minimise the problem by limiting the use of external names to actual
> external references.
>
> * Bundling ("concatenation") generally would require embedding
> arbitrary string resources, not syntactic modules.
>
>   One powerful feature of loaders is the translation hook. When
> importing a module from an external source, there is no restriction on
> its syntactic content, since a translation hook can transform it
> freely. But if one were to bundle ("concatenate") an application that
> actually makes use of this liberty, then the current proposal could
> not actually support that consistently. Consequently, if one primary
> goal the current proposal is to make module declarations a mechanism
> for bundling modules, then they are an incomplete solution. In
> general, you'd need to be able to embed arbitrary _resources_ (as
> strings), and be able to run translate hooks on those.
>
> * Module "declarations" are not a declarative mechanism, but an operational one.
>
>   Because module declaration is coupled with loader registration, it
> has a non-trivial operational effect, and its semantics is in turn
> subject to interference from other operational effects from inside and
> outside the program (as described above). Yet, it is disguised in a
> seemingly innocent declarative syntax. That is likely to create
> pitfalls and wrong assumptions (again, like with the global object).
>
>
> In summary, not only do path-named module declarations lack desirable
> expressiveness, regularity, and integrity, they also do not support
> more interesting configuration and concatenation use cases, which is
> what they were intended for.
>
> Most of the above problems cannot be fixed without adding lexically
> scoped modules to the language. It seems very clear that we need
> those, rather sooner than later. Also, I think we want a more
> structured approach to the global name space for external modules. At
> that point, rethinking the proposed approach may be the best idea.
>
>
> ** Proposal **
>
> I think it is highly advisable to follow a simple strategy for the
> whole naming business: avoid ad-hoc inventions, stick to
> well-established, standard mechanisms.
>
> Specifically:
>
> 1. Have a clean separation of concerns between internal and external names.
> 2. For internal names, use the standard language mechanism: lexical scope.
> 3. For external names, use the standard web mechanism: URLs.
> 4. Have a clean separation of concerns between the declarative
> _definition_ of a module, and the operational notion of _registering_
> it with a loader.
>
> Let me point out again that both lexical scope and URLs are backed by
> decades of experience and have proved superior over and over again, in
> many, many different languages and environments. _We can only lose if
> we try to do "better"_.
>
> More concretely, I envision using lexical module declarations as the
> primary means for defining modules (you guessed that from the start :)
> ). Modules can nest. (Supporting local modules, like Mark suggested,
> is more difficult, because of unclear interactions with other
> constructs like classes or eval. Certainly not ES6.)
>
> There may (or may not, see below) be a (separate?) pseudo-declarative
> form for registering modules as resources with the loader -- however,
> if so, it should ideally scale to handle non-ES sources.
>
> Module resources are identified by URLs. Those can be absolute or
> relative; relative URLs are interpreted relative to the importing file
> (just like HTML links). The loader table only contains absolute URLs.
> Likewise, every script is associated with its absolute URL. Any
> relative import is first normalised to absolute using the absolute URL
> of the importer (plus obvious steps for normalising occurrences of "."
> and "..").
>
> A custom loader can, in principle, perform arbitrary interpretation or
> rewriting of URLs. In particular, this could be used to implement
> interop to absolute repository paths a la AMD or Node, e.g. by
> interpreting an "amd:" schema for importing AMD modules that are
> relative to a separately configured base URL. In other words, you'd
> write
>
>   import M1 from "a/b";  // native ES6 import, relative path
>   import M2 from "amd:c/d";  // import of AMD module, relative to AMD base URL
>
> Should we have a declarative form for registering resources, then its
> URL would be resolved in the same manner, relative to the path of the
> containing file. However, the programmer is free to use an absolute
> URL.
>
> At that point, the only remaining purpose for path-named module
> declarations would be registering external references. However,
> registration is already possible through the loader API. Doing so
> requires additional staging (a script setting up the loader before
> executing the actual script). But staging is necessary anyway, for
> every slightly more interesting configuration case -- e.g. any
> scenario that involves loader.ondemand, translation, etc. It is not
> clear to me that the remaining cases justify an additional semantic
> short cut, and I think there is a case to be made that path-named
> module declarations are neither sufficient _nor_ necessary. But that
> point is mostly independent from the rest.
>
> Clearly, there are more details to be discussed and worked out. I also
> know that Dave & Sam have been over lots of it before. Still, I'm
> positive that it is a fairly solvable problem, and will yield a more
> well-behaved and more scalable solution. And yes, essentially it means
> reverting this part of the module proposal to its earlier stage -- but
> the good news is that not much else in the proposal is affected. :)
>
> /Andreas
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Kevin Smith


The focus should be on creating the best possible module system not
the best possible system that
smoothly accommodates AMD modules!

Amen to that!  I would add "or Node modules" to your last sentence above.  The Node ship sailed, by my count, about three years ago.  Competing feature-by-feature with AMD/Node modules should be an explicit non-goal.  As should interoperability, for reasons which we could go into in another post.

{ Kevin }


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Sam Tobin-Hochstadt
In reply to this post by Brian Di Palma


On Apr 25, 2013 4:00 AM, "Brian Di Palma" <[hidden email]> wrote:
>
> I've been following es-discuss for a short amount of time.
> I'm a JS dev working on a significant code base, this biases how I
> perceive ES6 issues.
>
> From my viewpoint by far the most important advancements provided by
> ES6, eclipsing all others,
> are modules and classes. This feeling is widely shared among the
> developers I work with.
>
> So I'm somewhat surprised at the lack of response to Andreas email.

On this point, Andreas wrote a long email, which I'm sure he spent time on. A response deserves similar consideration. I'm sure you'll see some soon.

Sam


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Andreas Rossberg-4
In reply to this post by Kevin Smith
On 25 April 2013 14:56, Kevin Smith <[hidden email]> wrote:
>> The focus should be on creating the best possible module system not
>> the best possible system that
>> smoothly accommodates AMD modules!
>
> Amen to that!  I would add "or Node modules" to your last sentence above.
> The Node ship sailed, by my count, about three years ago.  Competing
> feature-by-feature with AMD/Node modules should be an explicit non-goal.  As
> should interoperability, for reasons which we could go into in another post.

I would actually disagree with that. I think interoperability is an
important goal. But making interoperability maximally convenient less
so, and in particular, it should not be a reason to heavily compromise
on the design.

Having said that, interoperability with existing module systems was
not the main motivation for the change in the proposal, as far as I
can tell. It rather was simplicity (which is debatable, as I hope I've
made clear), and convenient support for common configuration and
concatenation use cases. You could count the latter as "easy
interoperability with an existing deployment tool like `cat'", if you
are so inclined. Notably, though, that doesn't work with AMD either.

/Andreas
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Brian Di Palma
In reply to this post by Sam Tobin-Hochstadt
Sam, I hope that will be the case, that's why I mentioned that I've
only been following es-discuss for a short amount of time. I wasn't
sure about the speed of response to such a substantial argument. I
waited a day to see if anyone was interested or if it generated a
discussion.

I agree that interoperability with older module systems is desirable
and that it should not come at the cost of a better standard ES6
module system.

B.

On Thu, Apr 25, 2013 at 2:46 PM, Sam Tobin-Hochstadt <[hidden email]> wrote:

>
> On Apr 25, 2013 4:00 AM, "Brian Di Palma" <[hidden email]> wrote:
>>
>> I've been following es-discuss for a short amount of time.
>> I'm a JS dev working on a significant code base, this biases how I
>> perceive ES6 issues.
>>
>> From my viewpoint by far the most important advancements provided by
>> ES6, eclipsing all others,
>> are modules and classes. This feeling is widely shared among the
>> developers I work with.
>>
>> So I'm somewhat surprised at the lack of response to Andreas email.
>
> On this point, Andreas wrote a long email, which I'm sure he spent time on.
> A response deserves similar consideration. I'm sure you'll see some soon.
>
> Sam
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Sam Tobin-Hochstadt
In reply to this post by Andreas Rossberg-4
First, I appreciate you setting your thoughts down in detail.  I think
this will help us move forward in the discussion.

You write in a later message:

> Having said that, interoperability with existing module systems was
> not the main motivation for the change in the proposal, as far as I
> can tell. It rather was simplicity (which is debatable, as I hope I've
> made clear), and convenient support for common configuration and
> concatenation use cases.

I don't think this is right, and I think this is the heart of the
issue. Let me back up a bit to explain this.

Module names play a role in three processes, in general:

1. As a way to identify local components.
2. As a way to find the physical resource that is the source code (or
object code) of the module.
3. As a way for two separately developed components to coordinate
about which module they mean.

In the current design, the internal names (eg, "jquery") serve role 1,
and URLs (as generated by the loader hooks) serve role 2. The
coordination role is played by internal names in a shared registry.

To pick another example (at random :), take SML with CM [1].  Here,
lexically-bound module name serve role 1, and CM serves role 2.
Coordination is managed by the ML toplevel, and files are typically
open in the sense that they refer to modules that will ultimately be
bound at the top level during the compilation process.

The system you outline at the end of your message, and the similar
system that Dave and I originally proposed, doesn't have anything that
really fulfills role 3.  That's why we changed the design.

This is perhaps easiest to understand with an example.  Imagine you're
developing a library, which will depend on jQuery, but you're not
shipping jQuery with your library (this is how Ember works, as do
a lot of other libraries).  Then you have to write something like
this:

    // in ember.js
    import "jquery" as $;

That's what you'd write in the current design.

In the design you're proposing, there are a few choices.  You can give
up on allowing people choose where they load jQuery from, and hardcode
a dependency on a specific URL in the Ember source code.  This is
obviously not ok.

You could decide that instead there's a single well-known URL that
everyone is going to identify with jQuery.  This is basically using
the URL namespace as keys in the module registry of the current
design, except without separating logical names from URLs. Then your
program looks like this:

   // in ember.js
   module jquery = "http://code.jquery.com/jquery-1.9.1.js";
   import jquery as $;

Of course, even though that looks like a URL, it isn't being used to
fetch anything, and everyone has to use some form of loader hook to
map it to where they actually keep jQuery.  Moreover, not everyone
will have the resources or want to take the trouble to register a
domain to publish their library.

Or you could settle on a local URL to use in the same way, again as
basically a registry key.

   // in ember.js
   module jquery = "scripts/jquery.js";
   import jquery as $;

Again, this thing that looks like a URL isn't being fetched, instead
it will have to be rewritten to some other URL.  And again, we have
the same division into internal names that are in a registry, and
external URLs that are actually for fetching the resource, except now
because your proposal tries to abolish this distinction, it's much
harder to manage.

In other words, we are now manually simulating the registry, and it's
more painful and problematic for exactly the reasons that manually
simulating things on top of abstractions that don't support them
always is.

In contrast, the current design factors these two concerns, so that
this configuration is about the mapping from internal names (like
"jquery") to external names (like "http://....").

#### The key takeaway

The key takeaway here is this: in the current design, different
modules from different developers can coordinate based on the
*internal* names of their dependencies. In your lexical proposal, it's
not possible to coordinate globally on internal names, because they're
lexical.  So instead developers would have to coordinate on *external*
names.  This is fundamentally flawed, because external names are about
where to get bits, not which abstraction a name represents.

Supporting this use case properly is what led us to realize that the
earlier lexically-named proposal was flawed.

Note that none of this is about concatenation.  We've made some
particular design decisions where concatenation played a role, but it
wasn't a part of the reason we moved away from lexical modules.

#### Some smaller points

> * As an external naming mechanisms, it violates standard relative
> path/URL semantics.

This isn't done particularly to be compatible, and node or AMD could
have required "/" in front of absolute paths.  But since that's an
important use case, we don't think it's a good idea to tax it with
extra typing.  This convention has become popular in JS for a reason.

> * The shared name space between internal and external modules can lead
> to incoherent programs.

I've already pointed out above how these namespaces aren't shared, and
in fact their separation is an important reason for the current
design.  Also, the incoherent programs you refer to are ruled out by a
suggestion (of yours!) that we adopted at the last meeting:
declarative module forms that define a module that already exists are
a static error.

> * Likewise, a single global name space for all internally defined
> modules can lead to incoherent programs.

I would be more worried about this if (a) we didn't provide convenient
ways to structure this name space and (b) it wasn't already an
existing successful approach in real-world JS systems.

> * "Local" references are globally overridable.

This is only true in the sense that executing first lets you define
the meaning of particular modules.  But this is a *feature*.  This is
just another way to describing configuration.  It's not reasonable to
think that we can decide for everyone what will need configuration and
what won't.

> * Internal module definition is coupled with external module
> registration, and modules cannot be renamed or re-registered.

These are not "external" names, but it is true that declaring a module
registers it.  It's possible to take it out of the table afterward, or
give it a new name, or have it share multiple names, all by using the
loader API in very easy ways.  I don't think these will be common
operations, and this seems like a reasonable tradeoff.

> * Language-level naming semantics interferes with file system/URL
> naming semantics.

While it's sad that everyone doesn't use the same filesystem ;), this
is inevitable unless we force everyone to write *both* internal and
external names explicitly for every module; that's clearly more
user-hostile than the alternative.  Lots of languages (Java, Node,
...) manage a default mapping to the file system while making Windows
and Mac filesystems work sensibly.

> * Bundling ("concatenation") generally would require embedding
> arbitrary string resources, not syntactic modules.

The reason to use concatenation is to avoid consuming excessive client
resources -- in this setting of course you won't want to run
translation on the client side.  Translation hooks are important (a)
in less perf-sensitive settings like development and (b) for isolating
remotely-loaded code, neither of which require concatenation.

> * Module "declarations" are not a declarative mechanism, but an operational one.

This comes back to my original point.  Registration of module names is
about coordination, and thus this is an import feature, not a problem.

This is again long, but I hope it's clarified why the current design
is the way it is, and why the alternative you propose doesn't solve
the use cases we need to address.

Sam

[1] http://www.smlnj.org/doc/CM/ for those following along at home.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Claus Reinke
> Module names play a role in three processes, in general:
>
> 1. As a way to identify local components.
> 2. As a way to find the physical resource that is the source code (or
> object code) of the module.
> 3. As a way for two separately developed components to coordinate
> about which module they mean.
>
> In the current design, the internal names (eg, "jquery") serve role 1,
> and URLs (as generated by the loader hooks) serve role 2. The
> coordination role is played by internal names in a shared registry.

You argue for a two-level system of non-lexical names to support
configuration - okay. But why does that imply you have to drop
the lexical naming altogether, instead of using a three-level system
(from external to internal to lexical names)?

Also, in a two-level system of external and lexical names, could one
not model the coordination level by a registry/configuration module?

// using loose syntax
module registry {
module jquery = <external remote or local path>
export jquery
}

module client {
import {jquery: $} from registry
}

Claus
 
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Dave Herman
On Apr 25, 2013, at 4:08 PM, Claus Reinke <[hidden email]> wrote:

> You argue for a two-level system of non-lexical names to support
> configuration - okay. But why does that imply you have to drop
> the lexical naming altogether, instead of using a three-level system
> (from external to internal to lexical names)?

You don't, it's an orthogonal concern. Note that Sam was *not* arguing against the existence of lexical modules.

But it's not nearly as important as the rest of the core system -- as Sam describes, coordination and separate development are the most important piece that the module system needs to address. We dropped lexical modules mostly in the interest of working out the core and eliminating parts that weren't necessary for ES6. Kevin's been urging us to reconsider dropping them, and I'm open to that in principle. In practice, however, we have to ship ES6.

But let's keep the question of having lexical *private* modules separate from this thread, which is about Andreas's suggestion to have lexical modules be the central way to define *public* modules.

> Also, in a two-level system of external and lexical names, could one
> not model the coordination level by a registry/configuration module?

No, it would be too hard to get this expressive enough to satisfy the web platform's polyfilling needs.

Dave

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Claus Reinke
>> You argue for a two-level system of non-lexical names to support
>> configuration - okay. But why does that imply you have to drop
>> the lexical naming altogether, instead of using a three-level system
>> (from external to internal to lexical names)?
>
> You don't, it's an orthogonal concern. Note that Sam was *not* arguing
> against the existence of lexical modules.

Good to hear that confirmed.

> But it's not nearly as important as the rest of the core system -- as Sam
> describes, coordination and separate development are the most important
> piece that the module system needs to address. We dropped lexical
> modules mostly in the interest of working out the core and eliminating
> parts that weren't necessary for ES6. Kevin's been urging us to reconsider
> dropping them, and I'm open to that in principle. In practice, however, we
> have to ship ES6.
>
> But let's keep the question of having lexical *private* modules separate
> from this thread, which is about Andreas's suggestion to have lexical
> modules be the central way to define *public* modules.

There are a couple of problems I see with that: it proposes adding yet
another imperative API to JS where a declarative API would do (adding
modules to the internal registry instead of the local scope); and it misses
the big-rewrite-barrier that is going to accompany ES6 introduction -
modules are the most urgent of ES6 improvements, but do you think
users are going to rewrite their code bases twice just because modules
are going to be delivered in two stages?

You believe you have worked out the core parts that caused you to
postpone lexical modules, and you had a lexical module proposal
before that. What is standing in the way of re-joining those two parts?

Claus
 
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Kevin Smith
In reply to this post by Sam Tobin-Hochstadt
Hi Sam,

Thanks for this long explanation.  I have several thoughts, but I'd like to ask one thing in particular.

What you propose, with "logical names", is a global namespace of short human-readable names with *no* conflict resolution authority.  How do you see that working?  From a namespace perspective, how is that any different than hanging identifiers off of the global object, as we do today?  I'm not understanding how this strategy will facilitate namespace coordination.  I can only see it leading to namespace confusion.

Thanks!

{ Kevin }

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: Module naming and declarations

Domenic Denicola-2
From: Kevin Smith [[hidden email]]

> What you propose, with "logical names", is a global namespace of short human-readable names with *no* conflict resolution authority.  How do you see that working?  From a namespace perspective, how is that any different than hanging identifiers off of the global object, as we do today?  I'm not understanding how this strategy will facilitate namespace coordination.  I can only see it leading to namespace confusion.

Indeed, I must second this question. (This causes me some cognitive dissonance, since from a Node.js/AMD perspective that I work in daily, string IDs seem great, so I'm not sure what I'm arguing for ^_^.)

The way I think of this is that it's conflating packages and modules. In current practice, packages have names that are registered in a global registry, and they are represented in the module system by a "main module" for that package. The wiring that allows `"${packageName}"` to resolve to the URL for the main module of `packageName` is part of the loader; in Node.js for example it does directory climbing through `node_modules` and inspects `package.json`s for their `"main"` values.

In this way, modules do not have any globally-known names at all; their names are derived entirely from URLs (in the form of relative file paths).

I made this point in [a recent presentation on client-side packages](http://www.slideshare.net/domenicdenicola/client-side-packages), slides 6 and 7.

Curious if others agree with this or if I'm totally off base as to how this fits into the discussion...
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Dave Herman
In reply to this post by Claus Reinke
On Apr 26, 2013, at 7:20 AM, Claus Reinke <[hidden email]> wrote:

> You believe you have worked out the core parts that caused you to
> postpone lexical modules,

We're still on the hook to finish a "wiki-complete" design of the core by the May meeting. I'm a busy guy.

Dave

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Dave Herman
In reply to this post by Kevin Smith
On Apr 26, 2013, at 7:27 AM, Kevin Smith <[hidden email]> wrote:

> What you propose, with "logical names", is a global namespace of short human-readable names with *no* conflict resolution authority.  How do you see that working?  From a namespace perspective, how is that any different than hanging identifiers off of the global object, as we do today?  I'm not understanding how this strategy will facilitate namespace coordination.  I can only see it leading to namespace confusion.

Well first, it's much cleaner than the global object, because it does not involve the mess of prototype chains and sharing space with a DOM object's properties and methods.

There is, of course, a need for people to agree on common naming for shared modules. If they want to use conventions to avoid name collisions, there's in fact nothing preventing them from doing something like Java's reverse-DNS:

    import spawn from "org/calculist/taskjs";
    import Promise from "io/tilde/RSVP";

And note that Java also does not mandate reverse-DNS, it's just a convention. But in fact, that convention is really annoying and people hate it. Node uses much simpler global names that are reserved via NPM. This does lead to collisions and some people don't like that; an alternative system could use usernames. These are all viable alternatives, and what will really be needed will be package management systems like NPM for the web. What we are creating here is the basic semantics that provides a way for people to refer to shared modules. People can and should build package management systems, including tools, servers, and web sites, on top of this.

Dave

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Sam Tobin-Hochstadt
On Fri, Apr 26, 2013 at 7:17 PM, David Herman <[hidden email]> wrote:
> On Apr 26, 2013, at 7:27 AM, Kevin Smith <[hidden email]> wrote:

> > I'm not understanding how this strategy will facilitate namespace coordination.  I can
> > only see it leading to namespace confusion.
>
> There is, of course, a need for people to agree on common naming for shared modules.

One additional point on this topic. Even on the web, where there isn't
something like NPM as an arbiter for names, the JS community has
managed to use shared resources like the global object and the AMD
module name space effectively.  And as Dave points out, building tools
like NPM for web JavaScript will improve upon this further. We
shouldn't bake in a harder-to-use system up front when JS is doing
well as it is.

Sam
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Brendan Eich-3
In reply to this post by Claus Reinke
Claus Reinke wrote:
> but do you think
> users are going to rewrite their code bases twice just because modules
> are going to be delivered in two stages?

What are you talking about?

People are not going to rewrite more than once. Current NPM/AMD modules
do not nest, so there's no basis for asserting they'll be rewritten
twice, first to ES6-as-proposed modules, then to add lexical naming and
nesting.

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Kevin Smith
In reply to this post by Dave Herman

And note that Java also does not mandate reverse-DNS, it's just a convention. But in fact, that convention is really annoying and people hate it. Node uses much simpler global names that are reserved via NPM. This does lead to collisions and some people don't like that; an alternative system could use usernames. These are all viable alternatives, and what will really be needed will be package management systems like NPM for the web. What we are creating here is the basic semantics that provides a way for people to refer to shared modules. People can and should build package management systems, including tools, servers, and web sites, on top of this.


Let see how we might build package systems on top of this.  Let's say that I want to create a package management system named "browserpm".  Now, since I don't want any of my names conflicting with some other PM's names, the logical name for modules within my registry will need to include the registry name itself:

    import something from "browserpm/taskjs";

This looks *almost* like a real URL.  Why not just use a URL instead?

    import something from "//browserpm.org/taskjs";

I could even serve the source code directly from the "browserpm.org" site.  If we want to load scripts from our local server, we would just override the module URL resolution algorithm:


It seems to me that, *long term*, URLs provide all of the advantages of "logical names", without the downside of sacrificing one of the core principles of the web:  namely, that resources are represented by URLs.

{ Kevin }


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Kevin Smith
In reply to this post by Sam Tobin-Hochstadt


One additional point on this topic. Even on the web, where there isn't
something like NPM as an arbiter for names, the JS community has
managed to use shared resources like the global object and the AMD
module name space effectively.  

Facility of scale.  If done correctly, we ought to hope that the global module namespace will be far larger than anything AMD or the global object has had to deal with.  We can't assume that solutions which are effective at small scales will be effective at larger scales.

{ Kevin }

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Sam Tobin-Hochstadt
In reply to this post by Kevin Smith
On Sat, Apr 27, 2013 at 12:22 AM, Kevin Smith <[hidden email]> wrote:

>
>> And note that Java also does not mandate reverse-DNS, it's just a
>> convention. But in fact, that convention is really annoying and people hate
>> it. Node uses much simpler global names that are reserved via NPM. This does
>> lead to collisions and some people don't like that; an alternative system
>> could use usernames. These are all viable alternatives, and what will really
>> be needed will be package management systems like NPM for the web. What we
>> are creating here is the basic semantics that provides a way for people to
>> refer to shared modules. People can and should build package management
>> systems, including tools, servers, and web sites, on top of this.
>>
>
> Let see how we might build package systems on top of this.  Let's say that I
> want to create a package management system named "browserpm".  Now, since I
> don't want any of my names conflicting with some other PM's names, the
> logical name for modules within my registry will need to include the
> registry name itself:
>
>     import something from "browserpm/taskjs";

Why would you need to worry about this, though? I've never seen a
language (or other software infrastructure) where people built systems
using multiple package managers at once. For example, Macs have an
unfortunate multiplicity of package systems, but you don't have a brew
package depend on a macports package. The point of a package system is
to fetch and setup the code, not to sit there in the names of your
modules.  This is made especially clear if you think about the source
of a library.  Is every library going to be rewritten for every
package manager?

Certainly, existing JS package management systems don't work this way.

I've in fact worked with a system that was a lot like this, in that
the package manager was part of the import statement.  We didn't like
it, and we're replacing it with a more NPM-like system.

> This looks *almost* like a real URL.  Why not just use a URL instead?
>
>     import something from "//browserpm.org/taskjs";
>
> I could even serve the source code directly from the "browserpm.org" site.
> If we want to load scripts from our local server, we would just override the
> module URL resolution algorithm:
>
>     "//browserpm.org/taskjs" => "/modules/browserpm.org/taskjs";
>
> It seems to me that, *long term*, URLs provide all of the advantages of
> "logical names", without the downside of sacrificing one of the core
> principles of the web:  namely, that resources are represented by URLs.

The URLs you're proposing here just *are* logical names, and they
aren't in most cases being dereferenced to produce resources, which is
the core point of URLs on the web. They're just inconvenient logical
names.

Sam
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Module naming and declarations

Claus Reinke
In reply to this post by Brendan Eich-3
>> users are going to rewrite their code bases twice just because modules
>> are going to be delivered in two stages?
>
> What are you talking about?
>
> People are not going to rewrite more than once. Current NPM/AMD
> modules do not nest, so there's no basis for asserting they'll be rewritten
> twice, first to ES6-as-proposed modules, then to add lexical naming and
> nesting.

Talking for myself, I've been using node modules, AMD modules, my
own module loader, and have even tried, on occasion, to make my
code loadable in two module systems (though I've shied away from
the full complexity of UMD). I'm tired of that needless complexity - I
want to build on modules, not fight with them (and I don't want tool
builders having to guess what kind of module system a given code
base might be using and what its configuration rules might be).

I have high hopes for getting to use ES6 modules early, via transpilers,
but that cannot happen until that spec settles down - we have users
of implementations that are waiting for that spec to tell them what
to converge on.

As soon as the dust settles, I'll try to stop using legacy modules
directly, switching to ES6 modules, transpiled to whatever (until the
engines catch up).

But what I really want are lexical modules as the base case. The
use cases that led to the new design are important, so a design
not covering them would be incomplete, but if ES6 modules are
not lexical, I'll be rewriting my code again once ES7 true modules
come out. That is twice for me, and I doubt there is anything
untypical about me in this situation.

I understand that David is snowed under (he has an unfortunate
habit of taking on too much interesting work?-) but given the
importance of this particular feature, perhaps more of tc39 could
give a helping hand? The earlier and the more complete that
spec is, the earlier there will be user feedback, and the greater
the chance that ES6, or at least ES6.1, will have a module system
that works in practice.

Claus
 
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
1234 ... 8