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

Some strange interaction with builtin-extend, transform-runtime, and preset-es2015 #15

Open
glasserc opened this issue Nov 17, 2017 · 1 comment

Comments

@glasserc
Copy link

At https://gist.github.com/glasserc/be6ffc197fc961bd7f0ea3e9fee3cfd5 I have posted a stripped-down example of what I'm facing in a project at work. I have a src file which has some subclasses of Error:

class Error1 extends Error {}
class Error2 extends Error {}

I'm using transform-builtin-extend as well as transform-runtime (because this is a library that uses async/await).

{
  "env": {
    "development": {
      "plugins": [
        ["transform-builtin-extend", {
          "globals": ["Error"]
        }],
        "transform-runtime",
        "transform-es2015-classes",
        "transform-es2015-modules-commonjs"
      ]
    }
  }
}

(Here I have removed the es2015 plugins that don't appear to be relevant to the problem.)

The compiled output for the two Error subclasses is strange in that builtins are transformed inconsistently, with the first one referring to _create, _from, _getPrototypeOf, etc.:

function _extendableBuiltin(cls) {
  function ExtendableBuiltin() {
    var instance = (0, _construct2.default)(cls, (0, _from2.default)(arguments));
    (0, _setPrototypeOf2.default)(instance, (0, _getPrototypeOf2.default)(this));
    return instance;
  }

  ExtendableBuiltin.prototype = (0, _create2.default)(cls.prototype, {
    constructor: {
      value: cls,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });

  if (_setPrototypeOf2.default) {
    (0, _setPrototypeOf2.default)(ExtendableBuiltin, cls);
  } else {
    ExtendableBuiltin.__proto__ = cls;
  }

  return ExtendableBuiltin;
}

However, the second error is transformed differently, referring to _Object$create, _Array$from, _Object$getPrototypeOf, etc:

function _extendableBuiltin3(cls) {
  function ExtendableBuiltin() {
    var instance = _Reflect$construct(cls, _Array$from(arguments));

    _Object$setPrototypeOf(instance, _Object$getPrototypeOf(this));

    return instance;
  }

  ExtendableBuiltin.prototype = _Object$create(cls.prototype, {
    constructor: {
      value: cls,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });

  if (_Object$setPrototypeOf) {
    _Object$setPrototypeOf(ExtendableBuiltin, cls);
  } else {
    ExtendableBuiltin.__proto__ = cls;
  }

  return ExtendableBuiltin;
}

This causes errors when I use this library in other projects, because _Object$create is not defined anywhere.

Changing the order of transform-builtin-extend and transform-runtime in .babelrc does not appear to change the compiled output. Indeed, moving transform-runtime to the end of the list also doesn't seem to change anything.

Removing transform-runtime from .babelrc (leaving transform-builtin-extend and the es2015 plugins) generates _extendableBuiltin3 and _extendableBuiltin which are identical, and use Object.create, Array.from, Object.getPrototypeOf, etc.

function _extendableBuiltin(cls) {
  function ExtendableBuiltin() {
    var instance = Reflect.construct(cls, Array.from(arguments));
    Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
    return instance;
  }

  ExtendableBuiltin.prototype = Object.create(cls.prototype, {
    constructor: {
      value: cls,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });

  if (Object.setPrototypeOf) {
    Object.setPrototypeOf(ExtendableBuiltin, cls);
  } else {
    ExtendableBuiltin.__proto__ = cls;
  }

  return ExtendableBuiltin;
}

Taking this compiled output and saving it in index.js and running it through babel without transform-builtin-extend (but leaving transform-runtime and the es2015 plugins) seems to generate sensible output (with _create2.default, _from2.default, _getPrototypeOf2.default used in call sites in both _extendableBuiltin and _extendableBuiltin3).

For completeness, rerunning the original index.js through Babel without transform-es2015-modules-commonjs (but leaving transform-runtime and transform-builtin-extend as well as transform-es2015-classes) also seems to generate sensible output (with _Object$create, _Array$from, and _Object$getPrototypeOf being used in both functions after importing them using e.g. import _Object$create from "babel-runtime/core-js/object/create";).

In this experiment, the _Object$create behavior only seems to happen to the second exception subclass (even if you add other subclasses afterwards), but in my real project, it happened to both the second and the fourth.

Based on all of this, I conclude that there's some bug that arises from an interaction between transform-builtin-extend, transform-runtime, and the es2015 plugins, but I'm not sure how to characterize that interaction and I'm not really sure how to debug further, though. Do you have any idea what's going on?

glasserc added a commit to Kinto/kinto-http.js that referenced this issue Nov 20, 2017
…260)

transform-runtime is meant to allow us to access the regenerator
polyfill "seamlessly, without global pollution". This means we don't
need to import it explicitly, and we don't need to make any efforts to
import it only once.

This replaces babel-polyfill, which is meant for applications, not
libraries.

Applications are responsible for providing the polyfill.

We use the "polyfill: false" option to disable conversion of "builtin"
JS methods such as Array.from and Object.create, which we could also
rewrite except for
loganfsmyth/babel-plugin-transform-builtin-extend#15.

This is meant to fix #259 and Kinto/kinto#1379.

Refs #159 (cc: @screendriver).

Refs Kinto/kinto-admin#456 and Kinto/kinto-admin#446.
@soryy708
Copy link

soryy708 commented Mar 5, 2020

Perhaps related? #8

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

No branches or pull requests

2 participants