Skip to content
This repository has been archived by the owner on Jul 31, 2018. It is now read-only.

WRT PR #3 - CJS <-> ES import/export conversion #10

Closed
bmeck opened this issue Mar 9, 2016 · 4 comments
Closed

WRT PR #3 - CJS <-> ES import/export conversion #10

bmeck opened this issue Mar 9, 2016 · 4 comments

Comments

@bmeck
Copy link
Member

bmeck commented Mar 9, 2016

This is the place to discuss specifics of how imports and exports are wrapped / converted between the CommonJS (CJS) and EcmaScript (ES) module systems. The proposal itself can be seen in PR #3.

Discussions here should regard:

  • how to generate ModuleNamespaces for ES modules to consume from CJS module exports
  • how to generate values for CJS to consume from ES module exports

It should not discuss module path resolution, evaluation ordering, or detecting file mode.

@caridy
Copy link

caridy commented Mar 10, 2016

Invariants of the interoperability

In order to facilitate the discussion, so folks will not have to dig into 262 and loader specs, here are the details and the current invariants:

CJS requiring ES Modules

A ModuleNamespace is an exotic namespace object, somewhat equivalent to this:

let ns = Object.create(null, {
   foo: {
      enumerable: true,
      get: () { /* return some internal value the module environment record */ }
   } 
});
Object.freeze(ns);

Obviously, this is a module with only one named export, you could add as many exports, including the default export to that object; and that's what we are going to get when a CJS module attempt to require a ES Module. Any transformation to facilitate the interoperability, will have to be made outside of the namespace object since it is immutable, and it is used for others ES-to-ES dependencies. It is very likely that a proxy is enough here.

ES importing CJS modules

In order to consume CJS from an ES module, a new representation of the CJS module as a ES Module Record has to be made, it can't be a source text module record, it can only be a reflective module record, as follow:

let exports = require('the-cjs-module');
let o = Object.create(null);
Object.keys(otherModule).forEach(key => {
   o[key] = Reflect.Module.Export.from(otherModule, key);
});
let moduleRecord = new Reflect.Module(o);

Obviously, that code does not cover the interoperability aspect of it (what if exports is a function, a promise, non-enumerables, etc.), that will have to be discussed here.

Additionally, to make that module available via System.loader, you will have to create a new Reflect.Module.ModuleStatus() and add that new entry into the loader registry.

@bmeck
Copy link
Member Author

bmeck commented Mar 10, 2016

@caridy

  • We need full prototype crawl not Object.keys just like it is implemented in the PR.
  • Unclear on what Reflect.Module.Export.from is from. Some unpublished spec?

Does this differ from the implementation we specified in the PR?

@bmeck
Copy link
Member Author

bmeck commented Mar 10, 2016

Obviously, that code does not cover the interoperability aspect of it (what if exports is a function, a promise, non-enumerables, etc.), that will have to be discussed here.

This is discussed in https://github.com/bmeck/node-eps/blob/es6-module/002-es6-modules.md#default-imports . We do not do direct copying, we merely set default and add getters for any properties. We do not make any alterations to [[Call]] etc.

Additionally, to make that module available via System.loader, you will have to create a new Reflect.Module.ModuleStatus() and add that new entry into the loader registry.

Punt on this issue to the PR itself. It doesn't really have anything to argue.

@caridy
Copy link

caridy commented Mar 10, 2016

Unclear on what Reflect.Module.Export.from is from. Some unpublished spec?

We should get that merged today or tomorrow in the loader spec, here are the details: whatwg/loader#129

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants