Do Anonymous Exports Solve the Backwards Compatibility Problem?

Kevin Smith khs4473 at
Tue Dec 18 12:56:32 PST 2012

At first glance, it seems like anonymous exports might provide a way for
pre-ES6 (read: Node) modules and ES6 modules to coexist.  After all:

    exports = function A() {};

just looks so much like:

    module.exports = function A() {};

But is that the case?  Does this oddball syntax actually help?

My conclusion is that it does not, *unless* the loading environment is
willing to statically analyze every single module it wishes to load.
 Moreover, the desired interop is not even possible without performing
static analysis.

There are two directions that an interop strategy will have to deal with.
 First, we might want an ES6 module to be loaded by a pre-ES6 module:

    // "es5-module.js"
    var ES6Module = require("es6-module.js");

We might want to use this when a dependency is upgraded to ES6 modules and
we want to leave the dependent alone.  Now, since ES6 modules are
asynchronous, and require is synchronous, we must load "es6-module.js"
*before* "es5-module.js" is executed.  The only way to do that is to
statically analyze "es5-module.js", searching for calls to require.

However, since require allows an arbitrary expression argument, there are
many cases in Node where this static analysis will fail.

What about the other direction?  Let's say that we want to load an ES5
module from an ES6 module:

    import ES5Module from "es5-module.js";

Let's say that the ES5 module looks like this:

    // "es5-module.js"
    module.exports = function A() {};

We could dynamically add the following text to the end of "es5-module.js":

    exports = module.exports;

And thereby export the necessary binding.  But if we use such a trick on an
*ES6* module, we could run into problems:

    exports = "foo";
    // dynamically generated line:
    exports = module.exports;

This would presumably result in an error!   The only way to avoid such
problems (without resorting to something like "package language version
flags") is to statically analyze "es5-module.js" and only apply the trick
if ES6 module declarations are *not* found.

So interop implies static analysis.  And since parsing and analyzing
javascript, in javascript, for every single loaded module would be quite a
performance hit, I think such a strategy is infeasible.

So where does that leave anonymous exports?  My personal opinion is

- Kevin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list