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

babel-plugin-transform-es2015-modules-umd does not produce ES3 compatible modules #4799

Closed
kitsonk opened this issue Oct 31, 2016 · 8 comments
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue

Comments

@kitsonk
Copy link

kitsonk commented Oct 31, 2016

Input Code

a.js:

export default function foo() {
	return 'foo';
}

b.js:

import a from './a';

export default a();

Babel Configuration (.babelrc, package.json, cli command)

{
  "plugins": ["transform-es2015-modules-umd"],
  "presets": ["es2015", "es3"]
}

Expected Behavior

The keyword default is not valid in ES3 and must always be quoted. For both a default export of a function and the import of a default it seems the plugin produces unquoted default in some code positions.

a.js

(function (global, factory) {
	if (typeof define === "function" && define.amd) {
		define(['exports'], factory);
	} else if (typeof exports !== "undefined") {
		factory(exports);
	} else {
		var mod = {
			exports: {}
		};
		factory(mod.exports);
		global.es3 = mod.exports;
	}
})(this, function (exports) {
	'use strict';

	Object.defineProperty(exports, "__esModule", {
		value: true
	});
	exports['default'] = foo;
	function foo() {
		return 'foo';
	}
});

b.js

(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(['exports', './a'], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports, require('./a'));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.a);
    global.b = mod.exports;
  }
})(this, function (exports, _a) {
  'use strict';

  Object.defineProperty(exports, "__esModule", {
    value: true
  });

  var _a2 = _interopRequireDefault(_a);

  function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
      'default': obj
    };
  }

  exports['default'] = (0, _a2['default'])();
});

Current Behavior

When exporting a function as default, it gets emitted as exports.default = instead of export["default"] =.

a.js

(function (global, factory) {
	if (typeof define === "function" && define.amd) {
		define(['exports'], factory);
	} else if (typeof exports !== "undefined") {
		factory(exports);
	} else {
		var mod = {
			exports: {}
		};
		factory(mod.exports);
		global.a = mod.exports;
	}
})(this, function (exports) {
	'use strict';

	Object.defineProperty(exports, "__esModule", {
		value: true
	});
	exports.default = foo;
	function foo() {
		return 'foo';
	}
});

When importing a default from another module, the interop require default includes an object literal with a default key instead of "default":

b.js

(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(['exports', './a'], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports, require('./a'));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.a);
    global.b = mod.exports;
  }
})(this, function (exports, _a) {
  'use strict';

  Object.defineProperty(exports, "__esModule", {
    value: true
  });

  var _a2 = _interopRequireDefault(_a);

  function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
      default: obj
    };
  }

  exports['default'] = (0, _a2['default'])();
});

Possible Solution

Always quote default.

Context

It is causing Babel to produce invalid ES3 code, which is not ideal when trying to generate ES3 compatible modules.

Your Environment

software version
Babel 6.18.0
node 6.5.0
npm 3.10.3
Operating System macOS Sierra
@benlesh
Copy link

benlesh commented Dec 9, 2016

I tried chaining transform-es3-property-literals with this, and it had no effect.

@DrewML
Copy link
Member

DrewML commented Dec 9, 2016

I tried chaining transform-es3-property-literals with this, and it had no effect.

Most likely didn't work because plugins run before presets.

Not a long-term fix, but have y'all tried switching the order of the presets in .babelrc?

Presets run last to first (yes, super confusing), so babel-preset-es3 may be running before babel-preset-es2015, which it looks like is the culprit for the unquoted default.

Edit: Tested that theory locally - unfortunately doesn't resolve the issue.

@Jessidhia
Copy link
Member

The commonjs transform actually has hacks specifically to deal with this issue: https://github.com/babel/babel/blob/de46827/packages/babel-plugin-transform-es2015-modules-commonjs/src/index.js#L265-L270

@DrewML
Copy link
Member

DrewML commented Dec 9, 2016

@Kovensky Good catch. It looks like disabling the UMD transform addresses the issue, so we may (unfortunately) need similar hacks in there until the bigger issue is resolved

@DrewML
Copy link
Member

DrewML commented Dec 9, 2016

@Blesh For the time being, you can use the passPerPreset option in your Babel config, which will address the issue (but will slow the build down).

{
  "plugins": ["transform-es2015-modules-umd"],
  "presets": ["es3", "es2015"],
  "passPerPreset": true
}

@benlesh
Copy link

benlesh commented Dec 9, 2016

that seems to have done the trick, thanks @DrewML

@gkatsev
Copy link

gkatsev commented Jan 19, 2017

I'm having a similar issue with sometimes not getting default quoted correctly. I made a reduced test case here: https://gist.github.com/gkatsev/d60b19120db3ada5d21a00ba5996f109. If you run babel on bar.js and have typeof "foo"; uncommented, in _interopRequireDefault, the return object will have an unquoted default, if typeof is commented out, `default will be quoted correctly.

gkatsev added a commit to videojs/video.js that referenced this issue Jan 19, 2017
* Switch to es3 preset for babel so that it runs last. Plugins run before presets and presets run in reverse order. Also, we ran into a weird bug in babel that causes `default` not to be quoted in some cases (babel/babel#4799) which we've worked around here.
* Restore the es-shims for tests and the ie8 fallback script.
* Do a null-check around `Player.players`.
* use more round fractions (like 0.5 and 1) to avoid rounding issues.
@loganfsmyth
Copy link
Member

Your example appear to be working now.

@lock lock bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label May 4, 2018
@lock lock bot locked as resolved and limited conversation to collaborators May 4, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue
Projects
None yet
Development

No branches or pull requests

6 participants