Skip to content

Incorrect scope with @babel/preset-env due to plugin ordering #7557

@xandris

Description

@xandris

Choose one: is this a bug report or feature request? A bug report.

I couldn't tell if this was the same bug as other similar issues. Sorry for any duplication.

Input Code

for(let [a] of c) {
  a=1;
  ()=>a;
}

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

{
    presets: [
        [ '@babel/env', { debug: true } ]
    ]
}
BROWSERSLIST='IE 11' npx babel --config-file ./.babelrc test.js

Adding in the destructuring plugin doesn't change anything.

Expected Behavior

Something like @babel/preset-es2015 produces (boilerplate omitted):

  var _loop = function _loop() {
    var _step$value = _slicedToArray(_step.value, 1),
        a = _step$value[0];

    a = 1;

    (function () {
      return a;
    });
  };

  for (var _iterator = c[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
    _loop();
  }

Current Behavior

var _loop = function _loop(_a) {
  _a = 1;

  (function () {
    return _a;
  });

  a = _a;
};

var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;

try {
  for (var _iterator = c[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
    var _ref3 = _step.value;

    var _ref2 = _slicedToArray(_ref3, 1);

    var _a2 = _ref2[0];

    _loop(_a2);
  }

The line a = _a assigns to a when no variable a is in scope.

It seems @babel/preset-env orders the relevant transforms like this:

  transform-block-scoping { "ie":"11" }
  transform-for-of { "ie":"11" }

when they really should be ordered like this:

  transform-for-of { "ie":"11" }
  transform-block-scoping { "ie":"11" }

or the relevant transformations should be insensitive to ordering.

You can run them by themselves to confirm:

npx babel --no-babelrc --plugins @babel/transform-for-of,@babel/transform-block-scoping test.js # works correctly
npx babel --no-babelrc --plugins @babel/transform-block-scoping,@babel/transform-for-of test.js # breaks

Context

Our code had a more convoluted example, but basically captured a mutated loop variable within a lambda, and threw an exception at runtime because of the bogus assignment.

Your Environment

software version(s)
Babel 7.0.0-beta.40
node 9.8.0
npm 5.6.0
Operating System macOS 10.13.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    Has PRoutdatedA closed issue/PR that is archived due to age. Recommended to make a new issuepkg: preset-env

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions