Should we kill the ModuleImport syntax?
module foo from "foo"; // drop this
import bar from "bar";Pros:
modulekeyword is very confusing (e.g.: is this a definition of a new module? what is thefrompart?, etc.)- Removing
ModuleImportwill simplify the import/export syntax.
Cons:
- without a way to access the module object, it is difficult to deal with modules with many exports (e.g.: underscore), but we could fix this by using a reflective API to access imported modules
Resolution:
- let's kill it.
- let's use an imperative syntax to access the module object (see 3rd bullet for more details)
- @ericf will open the tickets to update the specs
(https://people.mozilla.org/~jorendorff/es6-draft.html#sec-imports)
// this !== realm.global?
// this !== Reflect.global?
// this === <ModuleMeta>?
// this === Object.create(null) per module?
export function foo() {};
// potential confusing side effect: `this.exports.foo()`???Pros:
this.somethingwill not define global variablesthis.somethingwill not be shared between modules
Cons:
- how to access
realm.globalfrom within the module?
Resolution:
- let's change it.
Reflect.globalwill be the way to access the global scopethis === Object.create(null)can be created by loader, this object will providethis.moduleamoung other members. (see 3rd bullet for more details)- @ericf will open the tickets to update the specs
updated: this proposal was dropped in favor of 3.2
module keyword points to the module meta (a la nodejs)
index.html
<script>
System.import('app');
</script>app.js
export function init() {
// critical initialization steps
// ...
module.import('./lazy-mod').then(m => {
// then, do less important things...
});
};In this example, module.import() is sugar to normalize the module name based on the host module metadata.
Pros:
module.import()is similar toSystem.import()- it is ergonomic
- prevents loader leaks since loader instance is not accesible from the module code
module.nameandmodule.addressare available
Cons:
- metamodule api has to be defined (whitelist/getters for loader records)
importmethod have to be attached to the metamodule per module (since it wraps the normalization for relative modules).module.exports, a la nodejs, but immutable. Is this even an issue?modulehappens thru some magic under the hood (nodejs does this by executing a function and passing arguments to it)
Resolution:
- introducing a magical
modulevariable is not desirable, instead we will stick tothis, which is described in 3.2.
Similar to 3.1 but using this instead of module.
index.html
<script>
System.import('app');
</script>app.js
let moduleMeta = this; // or Reflect.Loader.getModuleMeta(this);
export function init() {
// critical initialization steps
moduleMeta.import('./lazy-mod').then(m => {
// then, do less important things...
};
};Pros:
- prevents loader leaks since no loader is accesible from the module code
this.nameandthis.addressavailable after normalization and location- seems to be easy to implement (no many changes in the specs are needed)
Cons:
this.import()might throw people off by thinking thatthis === System- metamodule api has to be defined (whitelist/getters for loader records)
importmethod have to be attached to the metamodule per module (since it wraps the normalization for relative modules).- potentially confusion with:
this.import()vsimport foo from "foo"; thismight be confusing. footgun, imagine people trying this.import() within a function.
Resolution:
thisis some sort of meta module (we need a better term) that provide access to some functionalities bound to the host module, likethis.import(),this.get(), etc.this.moduleprovides access to the exportsReflect.Loader.getModuleMeta(this)is unnecessary.- @ericf will open the tickets to update the specs
(https://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-scriptevaluation)
@dminkovsky import us a reserved word saved for using here, require is not, same reason node uses exports instead of export