Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES2015 preset not compatible with modules exposing mutable fields when using namespace import syntax (T7097) #4081

Open
babel-bot opened this issue Feb 12, 2016 · 5 comments

Comments

@babel-bot
Copy link
Collaborator

babel-bot commented Feb 12, 2016

Issue originally made by @abergenw

Bug information

  • Babel version: 6

Description

The ES2015 preset (presumably transform-es2015-modules-commonjs) runs the imported module through _interopRequireWildcard() when importing using the namespace syntax (import * from X). This results in a copied object as Babel probably tries to imitate ES6 module immutable bindings.

If the imported module exposes a mutable field (like D3.js for example, d3.event) this clearly won't work.

Any suggestions on how this can be overcome?

@babel-bot
Copy link
Collaborator Author

Comment originally made by @loganfsmyth

Hmm, tough one. In the short-term you'd have to do import {event} from 'd3';

Seems to me like the most correct approach here would be for _interopRequireWildcard to return an object with getter properties instead, but that'd potentially be a performance hit. Another alternative would be

var newObj = Object.create(obj);
newObj.default = obj;

but that'd be non-spec since the properties wouldn't be own properties.

@babel-bot
Copy link
Collaborator Author

Comment originally made by @abergenw

In d3 event is not exported separately so I cannot do import {event} from 'd3'. However I solved this by forking d3 and providing a getter.

I can't say what the most correct solution would be, but since it's not very common to expose mutable fields like this, perhaps a solution would be to simply turn off interop for certain modules by configuring transform-es2015-modules-commonjs with the necessary parameters.

@babel-bot
Copy link
Collaborator Author

Comment originally made by @loganfsmyth

@abergenw import {event} from 'd3'; console.log(event) is essentially the same as import * as d3 from 'd3'; console.log(d3.event); Since d3 is CommonJS, you should also be able to do import d3 from 'd3'; console.log(d3.event);.

Only import * as d3 from 'd3' will incorrectly handle the live behavior of event, so you have several options.

@babel-bot
Copy link
Collaborator Author

Comment originally made by @abergenw

Yes correct, thank you. I can get around the problem by using any other means of importing than the namespace/wildcard syntax (my typescript definitions fooled me I couldn't). I still think however that the way _interopRequireWildcard works may cause more harm than good. Cheers!

@nicolo-ribaudo
Copy link
Member

Would reimplementing the _interopRequireWildcard helper like this work? It doesn't clone the imported namespace, but it creates a new object and sets __proto__ to the module.exports of the imported module.

function _interopRequireWildcard(obj) {
  if (obj && obj.__esModule) {
    return obj;
  } else {
    function C() { this.default = obj; }
    C.prototype = obj;
    return new C;
  }
}

Current implementation:

function _interopRequireWildcard(obj) {
  if (obj && obj.__esModule) {
    return obj;
  } else {
    var newObj = {};
    if (obj != null) {
      for (var key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
          var desc =
            Object.defineProperty && Object.getOwnPropertyDescriptor
              ? Object.getOwnPropertyDescriptor(obj, key)
              : {};
          if (desc.get || desc.set) {
            Object.defineProperty(newObj, key, desc);
          } else {
            newObj[key] = obj[key];
          }
        }
      }
    }
    newObj.default = obj;
    return newObj;
  }
}

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

No branches or pull requests

3 participants