modules proposal

๏̯͡๏ Jasvir Nagra jasvir at gmail.com
Thu May 20 16:24:04 PDT 2010


I've been following the modules strawman proposals from the sidelines and I
like many properties of this one.  Can you clarify the following use case
(inspired in part by the discussion of  programming in the small on the
earlier thread):

Suppose a.js and b.js use jquery and they import it from the containing
modules context.

module Foo {
  module JQ = load 'http://....';
  module Drawing = load 'http://.../gun.js'; // gun.js exports gun shooting
method "draw"
  module A = load 'http://.../a.js';  // a.js imports JQ and Drawing
  module B = load 'http://.../b.js';  // b.js imports JQ
}

Each of A and B get the shared frozen (but not transitively frozen) JQ and
all is well.  Module A also needs the gun drawing module Drawing which it
uses to draw and shoot guns.  Unbeknownst to Foo (since the contract between
Foo and B isn't explicit) and the internet is in flux, B also starts
importing Drawing expecting a GUI drawing method.

module Foo {
  module JQ = load 'http://....';
  module Drawing = load 'http://.../gun.js';
  module A = load 'http://.../a.js';
  module B = load 'http://.../b.js';  // b.js imports JQ AND *Drawing*
expecting something that draws graphics
}

Since there happens to be a Drawing module floating around, it gets handed
that module and sadness happens instead of an error message.

The problem occurs because although the scopes are lexical, the textual
content of the load call - the content that is pulled into the current scope
is not under the control of the author of Foo.  The modules that A or B uses
and has access to are not apparent to the author of Foo.  As a result, the
problems are similar to the problems you suffer from with dynamic rather
than lexical scopes.

I can see at least two ways the simple modules proposal can handle the
problem.  One is to recognize that a contract between two modules has two
parts - what the module requests (in the case of A, JQ and Drawing) and what
the container module provides (in the case of A, JQ and Drawing and in the
case of B, JQ only).  Currently the imports of a module are explicit but the
objects that the container provides are implicit.  One solution is for the
syntax of load to be explicit about what it is providing to the module being
loaded (crappy syntax aside):

module Foo {
  module JQ = load 'http://....';
  module Drawing = load 'http://.../gun.js';
  module GUI = load 'http://.../gui.js';

  module A = load 'http://.../a.js', {JQ: JQ, Drawing: Drawing}; // in
module A, uttering Drawing gets you Drawing
  module B = load 'http://.../b.js', {JQ: JQ, Drawing: GUI }; // in module
B, uttering Drawing gets you GUI
}

The other is to limit the scope from which the imported modules imports get
selected to the current scope:

module Fribble {}

module Foo {
  module JQ = load 'http://....';
  module Drawing = load 'http://.../gun.js';
  module A = load 'http://.../a.js';
}

module Bar {
  module JQ = load 'http://....';
  module Drawing = load 'http://.../gui.js';
  module B = load 'http://.../b.js'; // module B gets JQ and Drawing but it
can't utter something to get it the shared Fribble
}

This problem can probably be ignored for systems designed for
programming-in-the-small.

Regards
Jasvir



> From: *David Herman* <dherman at mozilla.com>
> Date: Thu, May 13, 2010 at 4:41 PM
> To: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Hello!
>
> I've updated the strawman proposals for static modules and dynamic module
> loaders and would love to get feedback from the es-discuss community.
>
> * Static modules:
>
>    http://wiki.ecmascript.org/doku.php?id=strawman:simple_modules
>    http://wiki.ecmascript.org/doku.php?id=strawman:simple_modules_examples
>
> Briefly, the proposal provides a static module form:
>
>    module Widgets { ... }
>
> The declaration binds the module name lexically. Modules declared at the
> same scope can be mutually recursive. They can also be loaded from external
> URL's:
>
>    module Even = "http://example.com/even.js";
>    module Odd = "http://example.com/odd.js";
>
> The body of a module contains nothing in scope except for outer module
> bindings. Modules are truly lexically scoped, with no global object
> pollution. Modules can easily import bindings from other modules, either by
> dereferencing the modules that are in scope directly:
>
>    module Client { ... Widgets.messageBox("hello!"); ... }
>
> or by importing them explicitly:
>
>    module Client {
>        import Widgets.messageBox;
>        ...
>        messageBox("hello!");
>        ...
>    }
>
> Although modules are static entities, they can be dynamically reflected as
> objects.
>
> There's plenty more details on the wiki page.
>
> * Dynamic module loaders:
>
>    http://wiki.ecmascript.org/doku.php?id=strawman:module_loaders
>
> These provide an API for dynamically loading and evaluating modules, and
> creating separate isolated contexts in which modules can be evaluated. You
> can create a separate module loader that shares no module instances with the
> current module loader; this could be used e.g. by an IDE (such as Bespin)
> that wants to run client code without letting the client code affect the
> running environment of the IDE itself. You can also share some module
> instances, to have finer-grained control over the sharing between module
> loaders.
>
> There are some API notes on the wiki page. I expect it'll be revised and
> refined over time. Feedback welcome!
>
> Thanks,
> Dave
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
> ----------
> From: *Erik Arvidsson* <erik.arvidsson at gmail.com>
> Date: Thu, May 13, 2010 at 11:39 PM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> This looks really good. I hope we can move this from strawman into
> proposals at the next face to face meeting.
>
> --
> erik
>
> ----------
> From: *Alex Russell* <alex at dojotoolkit.org>
> Date: Sat, May 15, 2010 at 12:08 AM
> To: Erik Arvidsson <erik.arvidsson at gmail.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Agreed, this looks really strong. I particularly like the local renaming
> ability. I hope this can be discussed and adopted very quickly.
>
> Regards
>
> --
> Alex Russell
> slightlyoff at google.com
> alex at dojotoolkit.org BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723
>
> ----------
> From: *P T Withington* <ptw at pobox.com>
> Date: Sat, May 15, 2010 at 4:53 AM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Looks great!
>
> I wonder if you considered having an export list, rather than tagging the
> individual exports?  I think that makes it easier to see/document the public
> API of a module.  You could at the same time allow renaming on export.
>
>  module Cowboy {
>    export {draw: d, shoot: s};
>    function d () { ... };
>    function s () { d(); };
>  }
>
> FWIW, the rename on import looked "backwards" to me at first glance, but I
> think I can learn.
>
> Do we really need to say `.*` for all?  We couldn't just say `import Math`?
>
> ----------
> From: *Ash Berlin* <ash_js at firemirror.com>
> Date: Sat, May 15, 2010 at 5:09 AM
> To: es-discuss <es-discuss at mozilla.org>
>
>
> If you wan't the exported symbols from the Math module to be available as
> (for example) just `pi` and not `Math.pi`, then yes, you need the `.*`. IIRC
> this is very similar to how python and java behave w.r.t imports and I think
> its the right way.
>
> Thought looking at the syntax section it seems that `import Math;` isn't
> valid and instead you do it as `module Math = Math`. Why not use import here
> as well? My first instinct here is `module` is for defining a module and
> `import` is importing it - instead `module` serves a dual function. Is there
> any reasoning for this behaviour that I might have missed?
>
> -ash
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
> ----------
> From: *Dmitry A. Soshnikov* <dmitry.soshnikov at gmail.com>
> Date: Sat, May 15, 2010 at 5:20 AM
> To: es-discuss at mozilla.org
>
>
> Yep, I also thought. Cons: we should repeat method name twice (and in the
> worth case -- three times) and can forget to export something (as e.g.
> Erlang programmers sometimes where should be -export([...]) statement(s) at
> the top of a source file). On the other hand (without common "export"), we
> should repeat the "export" keyword every time. As a variation, naming
> convention, thus the system can understand automatically what should be
> exported (as an example on Rhino: http://gist.github.com/363056). But,
> because of backward compatibility this is not acceptable (although, is
> convenient). It can be done for shortness e.g. or naming preferences of an
> author (maybe he doesn't like "Math" name ;)). But usually, yes, it is
> useful "backwards". If some module has been rewritten, then the old one can
> be named with "old" prefix. Thus, a user shouldn't rename it in all files
> but just (example from Python's django): "import oldforms as forms" and
> after that continue to use this "forms" name. Yep, ".*" seems obsolete,
> although, the reason is to be consistent I guess.
>
> Another proposal:
>
> import Geometry.{draw: drawShape};
>
> How about:
>
> import  Geometry:{draw: drawShape};
>
> colon apt more for "from" word. Another variations:
>
> from Geometry import: {draw: drawShape};
>
> or
>
> from Geometry import: {draw as drawShape, ...};
>
> from Geometry import {draw as drawShape, ...}; // without colon at all
>
> Cons:  additional/obsolete "from" and "as" keywords.
>
> P.S.: small off-topic/proposal (just again saw this usage):
>
> module JSON = load('JSON'  ||'http://json.org/modules/json2.js');
>
>
> How about a small syntactic sugar for useful and widespread construction:
>
> x = x || 10
>
> to remove this repetition from the right side:
>
> x ||= 10.
>
> module JSON ||= load(...);
>
> Dmitry.
>
> ----------
> From: *Jürg Lehni* <lists at scratchdisk.com>
> Date: Sat, May 15, 2010 at 5:28 AM
> To: "Dmitry A. Soshnikov" <dmitry.soshnikov at gmail.com>
> Cc: es-discuss at mozilla.org
>
>
> I do not mean to hijack this thread about what seems a very good modules
> proposal. But this operator is something I have wished for many times when
> writing ES code. So it would be a very welcome addition, and the
> construction is indeed in very widespread use.
>
> Jürg
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Sat, May 15, 2010 at 7:53 AM
> To: P T Withington <ptw at pobox.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Yes, this is a good point. We chose inline-export for convenience, but I
> don't see any reason not to allow both.
> Yeah, I'm not thrilled about how hard it is to remember which way it goes.
> I meant for it to be consistent with the syntax of destructuring:
>
>    let { draw: d } = obj;
>    import M.{ draw: d };
> The proposal originally left out the '.*' and others didn't like it. But
> more importantly, this has subtler implications for nested modules, e.g.
> what the meaning of the following example is:
>
>    module Outer { module Inner { ... } }
>    import Outer.Inner;
>
> The way we've written the proposal, any time you import a path without the
> '.{...}' syntax, you're importing a single binding. So import Outer.Inner is
> the same as
>
>    import Outer.{Inner};
>
> That is, it binds Inner locally to the Outer.Inner module instance.
>
> Alternatively, we could a) disallow leaving off the '.{...}' for importing
> a single binding and 'import x1.---.xn' would only be allowed to specify a
> module-binding and would import all its exports, or b) allow leaving off the
> '.{...}' but specify that it imports just the single binding when it's a
> value-binding and imports-all when the path indicates a module-binding. I am
> a little concerned that the former is too restrictive and the latter too
> subtle. IMO. the extra '.*' is only a two-character hardship and EIBTI.
>
> Dave
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Sat, May 15, 2010 at 8:03 AM
> To: Ash Berlin <ash_js at firemirror.com>
> Cc: es-discuss <es-discuss at mozilla.org>
>
>
> That's not quite right; 'module' is for creating a module *binding*. I.e.,
> all the forms start with 'module m' and create a lexical binding of 'm' to a
> statically known module.
> The idea is that 'module' creates module bindings and 'import' creates
> value bindings. So you can create a statically bound module binding via:
>
>    module M = MyLib.Math; // M is now a module binding that aliases
> MyLib.Math
>    import M.*; // import all bindings from MyLib.Math
>
> whereas 'import' always creates a value binding:
>
>    import MyLib.Math; // Math is now a value binding
>    import Math.*; // error: Math is not a module binding
>
> Since we are allowing dynamic reflection of modules, a goal of this
> proposal is to keep the distinction between static module bindings and
> dynamic module values as firm as possible, while still making it as
> convenient as possible to reflect modules as values.
>
> Dave
>
> ----------
> From: *Brendan Eich* <brendan at mozilla.com>
> Date: Sat, May 15, 2010 at 8:22 AM
> To: es-discuss Steen <es-discuss at mozilla.org>
>
>
> +1 on an export form that takes a list of already-declared names. One has
> to grok destructuring, but once past that, this is the only sane way. The
> shorthand applies.
>
> http://wiki.ecmascript.org/doku.php?id=harmony:destructuring +1, or more
> -- agree on always requiring .{x} for lone x being too restrictive, and the
> subtlety of .x meaning import-all sometimes, import just x from left-context
> module other times, is even worse! EIBTI FTW ;-)
>
> /be
>
> ----------
> From: *P T Withington* <ptw at pobox.com>
> Date: Sat, May 15, 2010 at 9:13 AM
> To: Brendan Eich <brendan at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> [...]
> Ah, destructing `.`, I missed that.  Perhaps I would have gotten it with a
> closer parallel like
>
>  let { draw: d } = import M;
>
> or
>
>  import { draw: d } from M;
> I guess `.*` is there for a purpose:  to remind me that it's very likely I
> don't want to say that.  :)
>
> ----------
> From: *Kam Kasravi* <kamkasravi at yahoo.com>
> Date: Sat, May 15, 2010 at 9:58 AM
> To: P T Withington <ptw at pobox.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Along these lines of imports, a regex would allow partial imports.
>
> ----------
> From: *Erik Arvidsson* <erik.arvidsson at gmail.com>
> Date: Sat, May 15, 2010 at 2:33 PM
> To: "Dmitry A. Soshnikov" <dmitry.soshnikov at gmail.com>
> Cc: es-discuss at mozilla.org
>
>
> Off topic but see
> http://wiki.ecmascript.org/doku.php?id=harmony:parameter_default_values
>
> --
> erik
>
> ----------
> From: *Dmitry A. Soshnikov* <dmitry.soshnikov at gmail.com>
> Date: Sat, May 15, 2010 at 2:36 PM
> To: Erik Arvidsson <erik.arvidsson at gmail.com>
> Cc: es-discuss at mozilla.org
>
>
> Ah, thanks for info, didn't see it (I have to find the time to check all
> proposal specs).
>
> Dmitry.
>
> ----------
> From: *Erik Arvidsson* <erik.arvidsson at gmail.com>
> Date: Sat, May 15, 2010 at 2:49 PM
> To: P T Withington <ptw at pobox.com>
> Cc: Brendan Eich <brendan at mozilla.com>, es-discuss Steen <
> es-discuss at mozilla.org>
>
>
> I'm happy this is finally receiving some comments. This is at the top
> of my wish list for ESH.
>
> I do agree that the current syntax seemed a bit off at first glance.
> Now that Brendan pointed out that it is the destructuring pattern it
> seems slightly better but still not perfect.
>
> I also agree with others that having an explicit export list would be
> useful. It is good practice to declare your imports and exports at the
> top of the file.
> I don't like this since it makes it look like (import M) is an
> expression that returns an object that is later destructured.
> import {drawShape: draw} from Geometry;
> import {drawGun: draw} from Cowboy;
> import * from Math;
>
> I like it. I think this one is clearer than the proposed "import
> Geometry.{drawShape: draw}".
>
> --
> erik
>
> ----------
> From: *Brendan Eich* <brendan at mozilla.com>
> Date: Sat, May 15, 2010 at 4:47 PM
> To: Erik Arvidsson <erik.arvidsson at gmail.com>
> Cc: P T Withington <ptw at pobox.com>, es-discuss Steen <
> es-discuss at mozilla.org>
>
>
> Agreed. The exported name is draw, the rename target is drawShape, so you
> want
>
> import {draw: drawShape} from Geometry.
>
> Compare destructuring:
>
> let {draw: drawGun} = cowboy;
> drawGun();
>
> /be
>
> ----------
> From: *Erik Arvidsson* <erik.arvidsson at gmail.com>
> Date: Sat, May 15, 2010 at 10:52 PM
> To: Brendan Eich <brendan at mozilla.com>
> Cc: P T Withington <ptw at pobox.com>, es-discuss Steen <
> es-discuss at mozilla.org>
>
>
> See, even after I knew the rules it was too confusing. Can we go back
> to using "as"?
>
> import draw as drawGun from Cowboy;
>
> --
> erik
>
> ----------
> From: *Dmitry A. Soshnikov* <dmitry.soshnikov at gmail.com>
> Date: Sun, May 16, 2010 at 9:32 AM
> To: es-discuss at mozilla.org
>
>
> Besides, the variation with
>
> export all; // or export "all";
>
> can be considered. It can be useful for debug.
>
> Or, simply -- to omit export statement. Thus, if there will be no local
> export statement for some function, it means that all functions/properties
> are exported. Although, it breaks the first design where by default methods
> are private for a module.
>
> Excluding:
>
> export all except [intrinsic, builder]; // if we don't want to write 20 of
> 22 methods to be exported
>
> Dmitry.
>
> ----------
> From: *Brendan Eich* <brendan at mozilla.com>
> Date: Sun, May 16, 2010 at 11:11 AM
> To: "Dmitry A. Soshnikov" <dmitry.soshnikov at gmail.com>
> Cc: es-discuss at mozilla.org
>
>
> Debugging is good.
>
> This is a minor point, but rather than all, we'd use * instead, to mirror
> import M.* or M.{*} or import * from M; whatever it ends up being. Sorry,
> the idea of implicit everything-exported is a footgun. Just say no. This is
> overdesign. By far the most common case is explicit export of a select list
> of API functions and consts.
>
> /be
>
> ----------
> From: *Charles Jolley* <charles at sproutit.com>
> Date: Sun, May 16, 2010 at 11:15 AM
> To: Brendan Eich <brendan at mozilla.com>
> Cc: "es-discuss at mozilla.org" <es-discuss at mozilla.org>
>
>
> I am unclear from this proposal.  What would happen if I declared the same
> module twice?  Would it reopen the module and add the extra declarations?
>
> -Charles
>
> ----------
> From: *Dmitry A. Soshnikov* <dmitry.soshnikov at gmail.com>
> Date: Sun, May 16, 2010 at 11:19 AM
> To: Brendan Eich <brendan at mozilla.com>
> Cc: es-discuss at mozilla.org
>
>
> Ah, sorry, yes. * on import covers this need, so "all" is obsolete on
> export. Yep, I thought so too after that, so forget about this. The main
> purpose of a general export at the top of a file is a quick look on what are
> being exported (and convenience to write the only export statement) and
> "except" concept from this viewpoint is less informative. Moreover, again *
> on import eliminates this need.
>
> Dmitry.
>
> ----------
> From: *Brendan Eich* <brendan at mozilla.com>
> Date: Sun, May 16, 2010 at 11:25 AM
> To: Charles Jolley <charles at sproutit.com>
> Cc: "es-discuss at mozilla.org" <es-discuss at mozilla.org>
>
>
> The simple modules proposal makes it an error to export twice. This is a
> bit implicit in
>
>
> http://wiki.ecmascript.org/doku.php?id=strawman:simple_modules#export_declarations
>
> That you get an error on duplicate export is a good point to make
> explicitly.
>
> Not sure if you meant Dmitry's "export *;" idea. That would export
> everything, but again if something was already exported, then there was
> already a const binding in the module's exports and you'd get an error.
>
> /be
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Sun, May 16, 2010 at 1:22 PM
> To: Brendan Eich <brendan at mozilla.com>, Charles Jolley <
> charles at sproutit.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> I think Charles means examples like:
>
>    module Foo {
>        export var x = 1;
>    }
>
>    module Foo {
>        export var y = 2;
>    }
>
> The answer is that this is a static error. Modules are not open and
> extensible. You can't declare the same module name twice in the same scope.
> (This should be made clearer in the subsection "Module binding and
> resolution," thanks for asking about it.)
>
> You can redeclare a new module with the same name at a different level of
> scope:
>
>    module Foo {
>        export var x = 1;
>    }
>
>    module Bar {
>        module Foo {
>            export var y = 2;
>        }
>        import Foo.x; // error: no such binding
>    }
>
> Since modules are bound in the scope chain like everything else, the
> semantics is just the same as all other lexical scope: the innermost binding
> of Foo wins.
>
> Dave
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Sun, May 16, 2010 at 1:32 PM
> To: Brendan Eich <brendan at mozilla.com>
> Cc: es-discuss at mozilla.org
>
>
> Agreed.
>
> As for the meaning: from my experience with PLT Scheme it works well for
> "export *;" to export everything that's defined in the module, but not
> re-export any imports. For that you'd have to explicitly re-export them. I
> think either semantics (import "all defined here" vs. "all in scope here")
> works fine, but the common case of importing is for private use, and
> re-exporting is the less common case.
>
> On a related note, I forgot to stipulate in the proposal what happens with
> diamond imports. For example:
>
>    module Shared {
>        export var x = ...
>    }
>
>    module Lib1 {
>        import Shared.x;
>        export x;
>    }
>
>    module Lib2 {
>        import Shared.x;
>        export x;
>    }
>
>    module Client {
>        import Lib1.*;
>        import Lib2.*;
>        ... x ... // error or no error?
>    }
>
> Because module bindings are static, it's straightforward to determine that
> both Lib1.x and Lib2.x point to the same binding (Shared.x). So I claim that
> we should loosen the error condition to the following:
>
> It is a static error to import the same name from two different modules
> *unless both bindings are the same*.
>
> Dave
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Sun, May 16, 2010 at 1:36 PM
> To: Kam Kasravi <kamkasravi at yahoo.com>
> Cc: P T Withington <ptw at pobox.com>, es-discuss Steen <
> es-discuss at mozilla.org>
>
>
> I'm a little hesitant on this idea; on the one hand it's nice that we
> already have literal support for regexps, so it's not a huge conceptual or
> syntactic overhead. OTOH, like Brendan suggested for "export all except" it
> smacks of over-design.
>
> Dave
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Sun, May 16, 2010 at 1:42 PM
> To: Erik Arvidsson <erik.arvidsson at gmail.com>
> Cc: Brendan Eich <brendan at mozilla.com>, P T Withington <ptw at pobox.com>,
> es-discuss Steen <es-discuss at mozilla.org>
>
>
> This is an incomplete suggestion. What do you want the full syntax to be
> for multiple imports? Force the user to write a separate one on each line?
> Bracket them? Comma-separate without bracketing?
>
> Whatever syntax you pick, "as" starts upping the syntactic overhead. The
> destructuring notation is pleasantly terse and consistent with
> destructuring.
>
> [FWIW, here's how I would conceptually distinguish the two sides of the ":"
> token. The LHS is a fixed label. When you write an object literal, you're
> creating a property with that fixed label. When you are destructuring an
> object, you are selecting out that fixed label. When you are importing, you
> are requesting the import with that fixed label. The RHS is the varying
> part.]
>
> Dave
>
> ----------
> From: *Brendan Eich* <brendan at mozilla.com>
> Date: Sun, May 16, 2010 at 2:59 PM
> To: David Herman <dherman at mozilla.com>, Kam Kasravi <kamkasravi at yahoo.com>
> Cc: P T Withington <ptw at pobox.com>, es-discuss Steen <
> es-discuss at mozilla.org>
>
>
> RegExp literal expressions evaluate to mutable object values, per ES5 and
> reality (ES3 got this wrong, making an object per literal lexeme -- not per
> evaluated expression).
>
> Modules are static. Do we really want to drag in some of the runtime
> (RegExps) just to filter imports? This seems not only like over-design, but
> also the wrong design.
>
> /be
>
> ----------
> From: *Kevin Curtis* <kevinc1846 at gmail.com>
> Date: Sun, May 16, 2010 at 3:00 PM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Stupid question - is the following form of (Python-ish) import
> possible (from the grammar it doesn't look like it):
>
> <script type="harmony">
> import Math; // Math module declared above
>
> alert("2π = " + Math.sum(pi, pi));
> </script>
>
> Or is it the case that with a module {...} declaration the module is
> immediately accessible in the scope it was declared in - and no import
> required if module.function syntax is used:
>
> <script type="harmony">
> // Math module declared above - no import needed
>
> alert("2π = " + Math.sum(pi, pi));
> </script>
>
> --
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Sun, May 16, 2010 at 7:18 PM
> To: Brendan Eich <brendan at mozilla.com>
> Cc: P T Withington <ptw at pobox.com>, es-discuss Steen <
> es-discuss at mozilla.org>
>
>
> Yes, but there's no reason to assume a RegExp token would be a RegExp
> literal expression.
> Import/export declarations are distinguished contexts; there's no need to
> introduce runtime evaluation. A sensible design for import/export
> declaration with a RegExp would simply be run a regular expression at
> compile time, with no ES object creation involved.
>
> I'm not advocating the feature, but if we did include it, ISTM the benefit
> of using regexps is precisely their limited power.
>
> Dave
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Sun, May 16, 2010 at 7:27 PM
> To: Kevin Curtis <kevinc1846 at gmail.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> > [snip]
> The latter, yes. Since modules are bound in the scope chain, they're
> already available for use as values.
>
> This makes it very convenient to reflect them as first-class values:
>
>    var x = Math;
>    alert(x["sum"]); // function(x,y) { ... }
>    alert(x["thisIsNotDefined"]); // undefined
>
> But since module instance objects are immutable, it's also easy for
> implementations to make static uses, such as your example above, as
> efficient as if they had been explicitly imported.
>
> Dave
>
> ----------
> From: *Brendan Eich* <brendan at mozilla.com>
> Date: Sun, May 16, 2010 at 8:00 PM
> To: David Herman <dherman at mozilla.com>
> Cc: P T Withington <ptw at pobox.com>, es-discuss Steen <
> es-discuss at mozilla.org>
>
>
> The reader of the source might assume exactly that. One regexp looks like
> another, and might be expected to quack like any other. That's possible, and
> desirable in practice: regexps have effects in real-world implementations
> (the unspecified but still used RegExp.$_, RegExp.$1, etc. properties). If
> written with /y or /g they mutate there own lastIndex property and use it
> for subsequent matches (how many times is /.*\.js$/g evaluated in that
> import directive?). You'd have to limit that power from what it is today in
> terms of effects (including those pesky de-facto standard effects).
>
> Another unwanted power is that these NFAs misnamed "regular expressions"
> can blow up with O(exp(n)) complexity due to backtracking. This is enough of
> a problem that we're about to try throwing an exception when JS regexp exec
> complexity measured in terms of active backtrack states compared to target
> string length seems to be worse than O(n^3) (see
> https://bugzilla.mozilla.org/show_bug.cgi?id=452451 and bugs it cites).
>
> Making some tamed, quasi-regexp-just-for-import seemed not what Kam
> proposed, but anyway undesirable on its face. I mean, the taming attempt is
> desirable ignoring the big picture, but the whole idea seems misbegotten. My
> two cents.
>
> /be
>
> ----------
> From: *Kevin Curtis* <kevinc1846 at gmail.com>
> Date: Sun, May 16, 2010 at 9:15 PM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Whats the difference between:
> var x = Math; // or: const x = Math;
>
> And:
> module x = Math;
>
> Thanks.
> --
>
> ----------
> From: *Kam Kasravi* <kamkasravi at yahoo.com>
> Date: Sun, May 16, 2010 at 9:37 PM
> To: Brendan Eich <brendan at mozilla.com>, David Herman <dherman at mozilla.com>
> Cc: P T Withington <ptw at pobox.com>, es-discuss Steen <
> es-discuss at mozilla.org>
>
>
> Thanks Brendan, David.
> A few comments below.
>
> ------------------------------
> *From:* Brendan Eich <brendan at mozilla.com>
> *To:* David Herman <dherman at mozilla.com>
> *Cc:* Kam Kasravi <kamkasravi at yahoo.com>; P T Withington <ptw at pobox.com>;
> es-discuss Steen <es-discuss at mozilla.org>
> *Sent:* Sun, May 16, 2010 8:00:35 PM
> *Subject:* Re: modules proposal
>
> [kam] My use case is the regex would be evaluated server-side with no
> client-side eval at runtime or compile time. This pertains more to the
> dynamic loader but what I was after was an ability to partially import a
> module in those cases where the entire module was not needed.
> But in reality, its likely the entire module would be fetched and
> evaluated. I do think that module authors would package modules and nested
> modules in ways where the server could optimize what was returned to
> minimize additional trips if regex's were allowed.
> [kam] An example might be something like SVG.*Filter* where the importer
> was interested in retrieving only filter related features within a SVG
> module. Brendan's point is valid, if the regex is 'quasi' or treated
> differently than true regex expressions
> then the use case(s) need to be convincing.
>
> /be
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Sun, May 16, 2010 at 10:02 PM
> To: Kevin Curtis <kevinc1846 at gmail.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> This was the point I was explaining here:
>
>    https://mail.mozilla.org/pipermail/es-discuss/2010-May/011162.html
>
> Modules are static entities, whose structure is known at compile-time. The
> "module" form creates these static bindings. But they can be reflected as
> first-class values. (Similar to e.g. classes in Java and proposed ES4.)
>
> The "import" form, like "var" and "const" and "function" creates a binding
> to a first-class value, whereas the "module" form creates a static module
> binding.
>
> So when you write:
>
>    var x = Math;
>
> you create a variable binding to the reflected first-class module value.
> Whereas when you write:
>
>    module x = Math;
>
> you are creating a static module binding x which is bound to the static
> module bound to Math.
>
> Dave
>
> ----------
> From: *Kevin Curtis* <kevinc1846 at gmail.com>
> Date: Sun, May 16, 2010 at 10:31 PM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> OK. On the simple_modules_examples wiki page:
>
> Reflecting module instances as first-class objects
>
> <script type="harmony">
> // a static module reference
> module M = Math;
>
> // reify M as an immutable "module instance object"
> alert("2π = " + M.sum(M.pi, M.pi));
> </script>
>
> Q: Why does referencing the module M's functions/constants - M.sum and
> M.pi - 'reify' M as an object.(Is this the same process as generating
> a 'reflected first-class module value'?)
>
> I get the difference between lexical/source vs first class - but this
> comment 'reify' genuinely confuses me. Why isn't the call to M.sum()
> static - known at compile time.
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Sun, May 16, 2010 at 10:40 PM
> To: Kevin Curtis <kevinc1846 at gmail.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Yeah, sorry, that example went through several iterations as the modules
> proposal evolved, and now it's kind of muddled. I'll update it tomorrow.
>
> Since the reference to the module is used in an expression, it could
> technically be thought of as reflecting the module as an object and pulling
> out its property. But the system is designed so that such uses can be
> guaranteed to have the same performance as if "sum" and "pi" were explicitly
> imported. I'll clarify that example and add another example that's truly
> dynamic, such as:
>
>    function inspect(m) {
>        for (key in m) {
>            if (m.hasOwnProperty(key))
>                alert("found export: " + key);
>        }
>    }
>    inspect(Math);
>
> Dave
>
> ----------
> From: *Kevin Curtis* <kevinc1846 at gmail.com>
> Date: Sun, May 16, 2010 at 10:52 PM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> No worries - the examples page is very useful.
>
> In your original email:
> Is the load keyword missing:
> module Even = load "http://example.com/even.js";
>
> ----------
> From: *Kevin Curtis* <kevinc1846 at gmail.com>
> Date: Sun, May 16, 2010 at 10:57 PM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> A couple more questions:
>
> In strawman:simple_modules_examples - Remote modules on the web (1):
>
> <script type=”harmony”>
> // loading from a URL
> module JSON = load 'http://json.org/modules/json2.js';
>
> alert(JSON.stringify({'hi': 'world'}));
> </script>
>
> 1) Does - or must - the file json2.js contain only a single top level
> module declaration:
>
> module JSON {
>   ...source...
> }
>
> (Can js source files contain multiple top level modules?)
>
> 2) If so, is the load statement equivalent to:
>
> <script type="harmony" src="http://json.org/modules/json2.js"></script>
>
> Apart from:
> - The script tag will make the module globally available to subsequent
> script tags. Whereas, the load form makes the module available only
> within the script tag load is called from.
> - the load form can parallelize the fetching and compilation of source
> more efficiently.
>
> --
>
> ----------
> From: *Mike Wilson* <mikewse at hotmail.com>
> Date: Mon, May 17, 2010 at 5:44 AM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss at mozilla.org
>
>
> Hi David, and thanks for putting in this work. I have a few
> questions below.
>
> Cyclic dependencies
> -------------------
>
> From the "Dependencies" section:
>
>  | This allows cyclic dependencies between any two modules
>  | in a single scope
>
> 1) Is this to say that cycles are allowed, or not allowed, in
> other scenarios? (f ex remote or filesystem-loaded modules)
>
> Import loads on demand
> ----------------------
>
> From the "Filesystem modules for offline ES" example:
>
>  | // compiler/Lexer.js
>  | module Lexer { ... }
>  | ...
>  | // Main.js
>  | import compiler.Lexer.*;
>
> 2) Am I understanding this correctly as the module loader
> fetching and registering Lexer.js "on demand" if not already
> present in its registry mapping?
>
> 3) Is Lexer.js required to contain exactly one module
> declaration that must match the filename, or otherwise an
> exception is thrown?
>
> 4) Would this on demand loading functionality be present
> also on the web platform?
>
> 5) If so, would then the uses in main1 and main2 be equivalent
> wrt binding MyLib names in the example below?
>
>  // lib/MyLib.js
>  module MyLib { export doStuff() ... }
>
>  // main1.js
>  import lib.MyLib.*;
>  doStuff();
>
>  // main2.js
>  module wrapper = load "lib/MyLib.js";
>  import wrapper.MyLib.*;
>  doStuff();
>
> "Importing" module level
> ------------------------
>
> 6) If I want to change the previous example to instead expose
> MyLib's names inside a MyLib module name, would I then do
> the following? :
>
>  // main1.js
>  module MyLib = lib.MyLib;
>  MyLib.doStuff();
>
>  // main2.js
>  module wrapper = load "lib/MyLib.js";
>  module MyLib = wrapper.MyLib;
>  MyLib.doStuff();
>
> Wrapper module on loaded scripts
> --------------------------------
>
> In the "Remote modules on the web (1)" example we have:
> 7) Am I understanding correctly that this is pointing to a
> plain script (without module decls) which is wrapped inside
> the JSON module we specify?
>
> 8) Imagine a json2mod.js with an embedded:
>
>  module JSON { ... }
>
> which would result in:
>
>  module JSON = load 'http://json.org/modules/json2mod.js';
>  alert(JSON.JSON.stringify({'hi': 'world'}));
>
> Is this assumption correct?
>
> 9) If so, what syntax could be used to avoid the extra wrapper
> module at load? Could there f ex be a standalone load syntax
> that evaluates straight into the current scope:
>
>  load 'http://json.org/modules/json2mod.js';
> (disclaimer: haven't thought much about implications of this)
>
> MRLs
> ----
>
> In the "Static module detection" example we have:
>
>  | // compiler tries each in order
>  | module JSON = load ('JSON' || 'http://json.org/modules/json2.js');
>
> 10) Does this syntax mix module identifiers and MRLs? (the
> 'JSON' item looks very much like a pre-registered module in
> the module registry?)
>
> 11) [Excuse my poor BNF] What is the +(',') for in:
>
>  | ModuleDeclaration ::= 'module' Identifier '=' 'load' MRL+(',') ';'
>
> Best regards
> Mike Wilson
>
> ----------
> From: *Mike Shaver* <mike.shaver at gmail.com>
> Date: Mon, May 17, 2010 at 5:59 AM
> To: Kam Kasravi <kamkasravi at yahoo.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>, Brendan Eich <
> brendan at mozilla.com>, P T Withington <ptw at pobox.com>
>
>
> For this, I would rather let the exporter define named export lists,
> so that there's better future proofing.  I would hate to be the person
> adding something to the SVG module knowing that there were a bunch of
> regexps floating around the web that might cause me to clobber
> something unexpected.
>
> Given Foo.* meaning what it will, I suspect we would see people
> writing exactly what you did above, and being surprised that they
> didn't get what they wanted: they want globs, not regexps, for that.
> ("*Filter*" isn't even a legal regexp, so they'd get a compilation
> error, but when you have to write SVG..*Filter.*, I think it gets to
> be pretty unwieldy.)
>
> Mike
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Mon, May 17, 2010 at 8:07 AM
> To: Kevin Curtis <kevinc1846 at gmail.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Yes, sorry for another inconsistency there. FWIW, I'm not married to that
> particular syntax. I put the "load" keyword into the proposal just to
> emphasize that these strings correspond to a compile-time action (loading
> the bits). For example, consider:
>
>    module M = load "http://example.com/foo.js";
>    module N = load "http://example.com/foo.js";
>
> These two modules are loaded from the exact same MRL, but the module system
> treats them as two completely separate, independent modules. (Even custom
> module loaders shouldn't be able to change this fact, since all they can do
> is deliver the bits of a module resource.)
>
> The reason for this is that on the web, there's just no way to know that
> two URL's point to the "same" resource-- fetching the bit-for-bit-same URL
> even microseconds apart can result in completely different data, since web
> servers are free to deliver whatever they want. So the module loading
> semantics is resolutely non-clever about interpreting MRL's.
>
> Dave
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Mon, May 17, 2010 at 8:19 AM
> To: Kevin Curtis <kevinc1846 at gmail.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> No. The file json2.js contains the *body* of the JSON module. It can
> declare as many modules, variables, and functions as it likes.
>
> This is less brittle (doesn't require careful coordination between client
> and library), and crucially it gives the client control over module naming,
> so that if two vendors produce a module called SuperWidgets, then the client
> can do:
>
>    module Acme = "http://acme.com/superwidgets.js";
>    module Haxx0rz = "http://haxx0rz.com/superwidgets.js";
>
>    import Acme.SuperWidgets.foo;
>    import Haxx0rz.SuperWidgets.bar;
>
>    // ...
>
> It's also more convenient for library writers, who don't have to wrap their
> entire top-level source file with an annoying boilerplate module
> declaration.
> That's mostly true, except for the fact that the <script> tag doesn't wrap
> the contents in a module. Thanks for bringing this up, it's a good point. It
> might suggest an extra HTML attribute to go that last step:
>
>    <script type="harmony" module="JSON" src="
> http://json.org/modules/json2.js"></script>
>
> (Which is of course, out of our jurisdiction to specify here, but
> coordination with other web standards will at some point be necessary, and
> it's helpful to have at least plausible recommendations.)
>
> However, I believe it should also still be possible for browsers to
> prefetch and parallelize the compilation of source from within module
> declarations with MRL's, too. This is something we need to experiment with
> in real implementations, though.
>
> Dave
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Mon, May 17, 2010 at 8:22 AM
> To: Mike Shaver <mike.shaver at gmail.com>
> Cc: Brendan Eich <brendan at mozilla.com>, P T Withington <ptw at pobox.com>,
> es-discuss Steen <es-discuss at mozilla.org>
>
>
> This gets to my main issue with regexps (aside from the YAGNI aspect) -- it
> puts too much significance into variable names, and becomes a refactoring
> hazard.
> FWIW, you could distinguish this with the regexp syntax, for example:
>
>    import SVG./.*Filter.*/;
>    import /.*Filter.*/ from SVG;
>
> But ... um, well, yeah.
>
> Dave
>
> ----------
> From: *Kam Kasravi* <kamkasravi at yahoo.com>
> Date: Mon, May 17, 2010 at 10:30 AM
> To: David Herman <dherman at mozilla.com>, Mike Shaver <mike.shaver at gmail.com
> >
> Cc: Brendan Eich <brendan at mozilla.com>, P T Withington <ptw at pobox.com>,
> es-discuss Steen <es-discuss at mozilla.org>
>
>
> Thanks Mike, David.
>
> I agree with the conclusion that regex probably isn't the best way to
> tackle these problems.
> I'll summarize the use cases since it may apply in later discussions...
>
> 1. Is it possible to import parts of a module to avoid potentially large
> network payloads?
> 2. Is there syntax that would allow the server to group or concatenate
> delivery of multiple modules within one request?
>
>
> thanks
> Kam
>
>
>
>
> *From:* David Herman <dherman at mozilla.com>
> *To:* Mike Shaver <mike.shaver at gmail.com>
> *Cc:* Kam Kasravi <kamkasravi at yahoo.com>; Brendan Eich <
> brendan at mozilla.com>; P T Withington <ptw at pobox.com>; es-discuss Steen <
> es-discuss at mozilla.org>
> *Sent:* Mon, May 17, 2010 8:22:52 AM
> *Subject:* Re: modules proposal
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
> ----------
> From: *Brendan Eich* <brendan at mozilla.com>
> Date: Mon, May 17, 2010 at 11:07 AM
> To: Kam Kasravi <kamkasravi at yahoo.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>, P T Withington <
> ptw at pobox.com>
>
>
> It's modules all the way down. You only import what you specify from the
> module, but that doesn't affect downloading or indeed express the module
> dependency -- the dependency comes from module declarations creating
> bindings first, before any import from the module via its bound name.
>
> Network payloads are induced by URL requests that miss the HTTP-rules-based
> cache. MRLs are not URLs, however, so there's an opportunity here to
> coalesce load requests. See below.
>
>
> This is a good question. The grouping of modules for download should be
> decoupled from how one declares modules, to avoid mixing concerns and
> requiring refactoring or rewriting just on account of repackaging. Module
> declarations allow ahead of runtime loading, but they don't help coalesce
> requests.
>
> Coalescing requests (for some value of request) could be pushed down a
> layer, not specified as part of the ECMA-262 language. This serves the
> decoupling requirement. Is it enough? A while ago Allen wrote about
> separating "configuration management":
>
> https://mail.mozilla.org/pipermail/es-discuss/2010-January/010686.html
>
> Part of this was about version selection, but part of it was about
> "assembly" structuring. It seems worth working through this, both with a
> real implementation of simple modules, and with some thought experiments.
>
> /be
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Mon, May 17, 2010 at 12:07 PM
> To: Kam Kasravi <kamkasravi at yahoo.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>, Brendan Eich <
> brendan at mozilla.com>, P T Withington <ptw at pobox.com>
>
>
> Not parts of a module, no. (The semantics of this would be incredibly hairy
> and hard to define.) But you can dynamically load modules, so you can write
> code that decides dynamically when to load modules.
> Since modules can be nested, you can certainly put multiple modules in a
> file; grouping them in a single module is nothing more than namespace
> management. So you can write:
>
>     // file1.js
>     module A { ... }
>     module B { ... }
>     ...
>     module Z { ... }
>
>     // client.html
>     <script type="harmony">
>         module MyLib = load "file1.js";
>     </script>
>
> or with HTML support, something like:
>
>     // client.html
>     <script type="harmony" module="MyLib" src="file1.js"></script>
>
> Dave
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Mon, May 17, 2010 at 12:12 PM
> To: Brendan Eich <brendan at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>, P T Withington <
> ptw at pobox.com>
>
>
> Yes, certainly. To some extent the module declaration syntax provides you
> enough to do this already:
>
>     <!-- my configuration table -->
>     <script type="harmony">
>         module M1 = "m1.js";
>         module M2 = "m2.js";
>         ...
>     </script>
>
> But it might be nice to crystallize this in a restricted special form so
> browsers can reliably prefetch:
>
>     <script type="harmony">
>         module table {
>             M1: "m1.js",
>             M2: "m2.js",
>             // ...
>         }
>     </script>
>
> Dave
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
> ----------
> From: *Brendan Eich* <brendan at mozilla.com>
> Date: Mon, May 17, 2010 at 2:47 PM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>, P T Withington <
> ptw at pobox.com>
>
>
> Either way allows prefetching once the type="harmony" script content has
> been parsed. But the browser still would have to stall rendering while that
> "module table" script tag was being processed, as far as I can tell. Any
> later scripts would block too, to avoid using a not-yet-loaded module
> binding.
>
> Oh, but you probably meant that the module table form, besides being sugar,
> is written in a restricted language that cannot have effects other than to
> create module bindings -- cannot do document.write or
> document.createElementNS("script") or whatever. In that case we'd want
> type="harmony-module-table" or some such, and then such a script indeed
> would allow layout to proceed immediately, and not block rendering.
>
> Thinking about it more, simple modules let authors bundle things in .js
> files, and src them with scripts. That's almost enough. Anything more, we do
> not want to standardize prematurely. Simple modules are really about lexical
> scope all the way up, and guaranteed errors (early errors, even), and static
> code partitioning with information hiding, and of course the lexical-only
> module-binding namespace management.
>
> Which is all good. Prefetching and packaging are separable issues, we
> should keep thinking about them but I'd hate to try to "solve" them before
> considering simple modules as a proposal.
>
> /be
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Mon, May 17, 2010 at 2:53 PM
> To: Brendan Eich <brendan at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>, P T Withington <
> ptw at pobox.com>
>
>
> Yes, sorry for the mixup. I should've written something like:
>
>    <script type="harmony-module-configuration-table">
> Agreed.
> Well put.
>
> ----------
> From: *Kevin Curtis* <kevinc1846 at gmail.com>
> Date: Wed, May 19, 2010 at 12:59 AM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> On Mon, May 17, 2010 at 4:07 PM, David Herman <dherman at mozilla.com> wrote:
>
> > [snip] For example, consider:
> That's surprising. Within a moduleloader I would have thought that
> same url meant the same static module. Across moduleloaders maybe not.
>
> For the following scenario:
> <script>
> module ModA = "http://acme.com/moda.js";
> module ModB = "http://acme.com/modb.js";
> ... source
> </script>
>
> Both ModA and ModB use a utility module - that is the moda.js and
> modb.js files both contain:
> module ModUtils = "http://widgets.com/modutils.js";
>
> I would have guessed that ModA and ModB are using the exact same
> static utility module. Firstly for efficiency - "hey this source has
> been fetched and compiled already".
>
> But also, simple modules seem like 'traditional' modules. That is, if
> a top level variable is declared in a C source file, that variable
> occurs once in the resulting compiled image/program. Thus the source
> files (modules) author can reason about the (shared state) of the
> variable.
>
> However, if an ES module source can be declared multiple times (within
> a moduleloader) - doesn't it become harder for the author of the
> module to reason about a top level variable. If multiple instance of a
> module variable are required - then maybe an object should be used.
>
> Also, it seems unlikely that a new module source would be generated by
> a server within the context of a moduleloader fetching/compiling
> source. Maybe the rule should be - first source fetched for a url is
> the source used for subsequent module references.
>
> ----------
> From: *Sam Tobin-Hochstadt* <samth at ccs.neu.edu>
> Date: Wed, May 19, 2010 at 6:47 AM
> To: Kevin Curtis <kevinc1846 at gmail.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> The problem with this is that the web is not stable enough.  First, is
> it based on the string in the URL?  If so, then is "Widgets.com" the
> same as "widgets.com"?  What about "www.widgets.com"?  What if the url
> resolves to a different IP each time?  Or if the source changes over
> time?
>
> We feel that it's a bad idea to try to use addresses on the web to
> determine identity of modules.  Instead, we based the naming system on
> lexical scope, and let the programmer manage resources on the web.  If
> you want to share a common library with your context, then you refer
> to it by name, and the context can provide it the module under that
> name.
> --
> sam th
> samth at ccs.neu.edu
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Wed, May 19, 2010 at 7:04 AM
> To: Kevin Curtis <kevinc1846 at gmail.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> The problem is defining "same url." One option is that "same" means
> "identical string" but then when http://example.com/foo.html says:
>
>    <script>
>    module A = "http://example.com/lib.js";
>    module B = "./lib.js";
>    </script>
>
> the programmer would be tempted to think those are the same URL. And yet a
> server has access to its request URL and can deliver entirely different bits
> depending on exactly what was requested.
>
> So you could propose some sort of canonicalization that happens on the
> client side, and say "same" means "same canonicalized string." But then the
> semantics depends on some non-trivial algorithm that happens away from view
> of the programmer.
> If they want to share a utility module, you pull it out into a place that's
> in scope for both ModA and ModB:
>
>    <script>
>    module ModUtils = load "http://acme.com/modutils.js";
>    module ModA = load "http://acme.com/moda.js";
>    module ModB = load "http://acme.com/modb.js";
>    ...
>    </script>
> I'm surprised to here you cite C as a precedent for modules, since C has no
> module system. All it has is #include, which is much harder to work with.
> The "load" semantics does still have the hazard of re-loading the same
> source (just as <script> does, BTW), but the scope is more tightly
> controlled; a loaded module is only sensitive to the modules in scope (no
> var-, let-, const- or function-bindings).
>
> Dave
>
> ----------
> From: *Kevin Curtis* <kevinc1846 at gmail.com>
> Date: Wed, May 19, 2010 at 11:34 AM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Ahh - thanks for this.
>
> So both the moda.js and modb.js source files can contain (for example):
> ModUtils.myfunc();
>
> And can import the exports of ModUtils:
> import ModUtils.myfunc;
> myfunc();
>
>
> Also, a script author can configure which modules they will use:
> For example use modules ModA and ModB - but not say - ModC and ModD.
> <script>
> module Acme {
>  // don't load the source files modc.js and modd.js - not used
> }
> Acme.ModA.myfunc();
> Acme.ModB.myfunc2();
> ...
> </script>
>
> Is it correct that a module declaration within a script tag only has
> scope within that script tag?
> That would be a surprise! No just the lexical concept.
>
> --
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Wed, May 19, 2010 at 3:35 PM
> To: Kevin Curtis <kevinc1846 at gmail.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> Yes.
> No, each script is in scope for subsequent scripts. (The section "Top
> Level" in the strawman is the relevant part.) One of the enhancements to the
> current proposal, which we've considered but not worked out in detail, would
> be the ability to create private modules.
>
> Dave
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Thu, May 20, 2010 at 9:56 AM
> To: Mike Wilson <mikewse at hotmail.com>
> Cc: es-discuss at mozilla.org
>
>
> Hi Mike, sorry I overlooked this message.
> It's an automatic consequence of lexical scope. It's no different from
> functions. If you write:
>
>    function f() {
>        function even(n) { ... odd(n-1) ... }
>        function g() {
>            function odd(n) { ... even(n-1) ... }
>        }
>    }
>
> you get a scope error, because |even| refers to |odd| which is not in
> scope. But if you put them both at the same level of scope, they can refer
> to each other. Same deal with modules.
>
> Since MRL's and module names are distinct, there's no problem letting
> remote modules refer to one another, they just have to do so through
> agreed-upon names. For example:
>
>    module Even = "http://zombo.com/even.js";
>    module Odd = "http://realultimatepower.net/odd.js";
>
> By binding them both at the same level of scope, both even.js and odd.js
> can refer to Even and Odd.
> The offline-JS examples are mostly just suggestive; this question is left
> to the (host-dependent) module loader to determine. Some offline-JS engines
> might prefer to have a module loader that can register top-level names
> implicitly. It might also want to load these modules on demand (which is
> somewhat orthogonal), but this would likely only be desirable behavior for
> built-in libraries that have no observable side effects. (Laziness with
> side-effects is pain.)
>
> But all of this would require some host-dependent, built-in support;
> there's nothing in the spec per se that provides this functionality.
> The short answer is no: the contents are the body of the module.
>
> The long answer is that it depends on the module loader. Module loaders
> have hooks that can arbitrarily transform the contents of a module. So a
> module loader can decide on whatever format it wants.
>
> Note that when you say "an exception is thrown," this is a
> compile/load-time exception. IOW, in the code being loaded, there's no
> observable exception. But of course, with dynamic loading, one program's
> compile-time error is another program's run-time error. :)
> No. We avoided lazy loading in the semantics, because it'd be a hornets'
> nest on the web. Modules are eagerly evaluated in deterministic,
> top-to-bottom order. As I say above, offline-JS has different needs than
> web-JS, so in that context a JS engine may wish to provide a built-in custom
> module loader that can deal with the filesystem in more clever ways.
>
> As I replied to Kam Kasravi earlier in this thread, on-demand loading is
> achievable via explicit dynamic loading. We tried to be non-clever about
> doing this stuff behind programmers' backs.
> No. There'd be no implicit loading on the web.
> I'm not sure I see what you're getting at, but IIUC, both of those examples
> are fine. You can always declare a new module binding that points to/aliases
> an existing module binding.
> It's a module body, which may contain nested module declarations, variable
> declarations, function declarations, statements, etc.
> Yes, but you wouldn't wanna do that. ;)
> The creator of the JSON library doesn't name it; the client names it. The
> JSON module just contains the *body* of the module. This is crucial for the
> web: you can have millions of libraries without worrying about library name
> collisions.
> You can get partway there via:
>    import JSON.*;
>
> But yeah, it might be nice to have a shorthand that avoids the extra module
> binding. (I'd probably want the syntax to start with "import" or "module").
> Me neither... I'll have to think about it.
> No, I was just positing some syntax for built-in MRL's. Maybe I should've
> written something like
>
>    module JSON = load ('browser://JSON' || '
> http://json.org/modules/json2.js');
>
> but I didn't want anyone to think I was making some specific proposal for a
> new URL scheme or anything. This is one of those things that stands outside
> the jurisdiction of TC39 but would still want standardization. I think we're
> going to need some amount of (hopefully light) collaboration with a W3C
> committee.
> Heh-- excuse my bogus BNF! That's just a made-up extension that allows 1 or
> more instances of MRL, separated by the ',' token. Spelled out:
>
>    MRL+(',') ::= MRL
>               |  MRL+(',') ',' MRL
>
> Thanks for your feedback,
> Dave
>
> ----------
> From: *David Herman* <dherman at mozilla.com>
> Date: Thu, May 20, 2010 at 11:25 AM
> To: Mike Wilson <mikewse at hotmail.com>
> Cc: es-discuss Steen <es-discuss at mozilla.org>
>
>
> PS If this is still unclear, just replace MRL+(',') with MRLList, and add
> the production:
>
>    MRLList ::= MRL
>             |  MRLList ',' MRL
>
> I'll do that in the spec to avoid this confusion in the future.
>
> ----------
> From: *Mike Wilson* <mikewse at hotmail.com>
> Date: Thu, May 20, 2010 at 1:47 PM
> To: David Herman <dherman at mozilla.com>
> Cc: es-discuss at mozilla.org
>
>
> Thanks for the detailed explanations, David. Here's a few follow-
> up questions (with "done" questions snipped out):
> <snip>
> Agreed, but I was rather wondering about cases like:
>
>  even.js
>    module Odd = "odd.js";
>    ...
>  odd.js
>    module Even = "even.js";
>    ...
>
> From other discussion I'm guessing this kind of circular
> referencing will not be supported?
> Right, the modules importable through this syntax would
> thus be considered "pre-registered" in some sense.
> <snip>
>
> I'm still a little confused by the rules here, but assuming a
> naive loader implementation, what would the following result
> in? (bonus points for describing how you envision a made-up
> setup process):
>  module Tokenizer { ... }
>  ...
>  // Main.js
>  import compiler.Tokenizer.*;
> I don't find a definition for "module body" in your strawman.
> Are you meaning that http://json.org/modules/json2.js above
> is organized as:
>
>  function stringify...
>  function parse...
>
> or as
>
>  export function stringify...
>  export function parse...
>  (although this is invalid according to the grammar)
>
> or as something else?
> <snip>
> It would be nice with a unified syntax for module "sub-addressing"
> that looks the same both when loading a new module or when
> aliasing an existing module.
> Two random thoughts on this:
>
> - I think it would be suitable with some special marker when
>  addressing built-ins, as
>    module JSON = load "JSON";
>  might as well be used for relative addressing to the
>    ./JSON
>  application URL, which should issue an external request.
>
> - For the web it is probably not interesting to do this resolution
>  for anything else than built-ins and *one* external URL.
>  Providing a search path with multiple external URLs would mean
>  depending on hitting 404s as part of the load phase, which is
>  usually frowned upon.
>
> Best regards
> Mike
>
> ----------
> From: *Sam Tobin-Hochstadt* <samth at ccs.neu.edu>
> Date: Thu, May 20, 2010 at 2:12 PM
> To: Mike Wilson <mikewse at hotmail.com>
> Cc: es-discuss <es-discuss at mozilla.org>
>
>
> Thanks for all your detailed feedback!
> Right.  If this was allowed, then we'd have the infinite chain of
> modules Even.Odd.Even.Odd.Even and so on.
> First, I want to emphasize again that our ideas about offline JS are
> preliminary, and not intended for standardization.  Different host
> environments can make different choices here.  But on this example,
> we're envisioning that Main.js would import compiler.Lexer.Tokenizer.
> Or perhaps there would only be one module per file when implicitly
> loading modules from the file system, but that would probably be
> needlessly restrictive.
> The latter.  We should think of the contents of json2.js as an
> anonymous module, which the client names using 'load'.
> I agree, it's probably confusing for "JSON" and "./JSON" to mean
> radically different things.  But staking out URL space for this seems
> heavyweight and ugly.  Is there a good middle ground?
> I think this is right in terms of how people should program on the
> web, but I'm not sure that it should be standardized.  Only allowing
> one external URL requires making a determination of what's external
> and what's built-in, and any one decision might not necessarily be
> right for every host environment.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20100520/e8889205/attachment-0001.html>


More information about the es-discuss mailing list