babel: SyntaxError: unknown: Binding 'arguments' in strict mode (2:6)

Hi I follow the instructions in this doc to transform arrow functions.

I find an error SyntaxError: unknown: Binding 'arguments' in strict mode (2:5) is thrown every time when a variable is named “arguments”. For example,

var foo = () => {
 var arguments = 1;
};

The instruction I use is require('@babel/core').transform(code, {plugins: ['@babel/plugin-transform-arrow-functions']}) where code is the input program like the above example.

So how can I fix it? Is there any options I miss to set?

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 18 (14 by maintainers)

Most upvoted comments

@RichardHoOoOo If you are interested in fixing this issue you are welcome to help, otherwise it’s open for anyone who wants to work on it!


The problem is in the utility we have to convert arrow functions to ES5 function expressions. In the hoistFunctionEnvironment function, we “extract” this, arguments, super and new.target to the outer scope, to preserve the correct semantics in cases like this one:

function f() {
  var g = () => console.log(arguments);
  g();
}

f(1, 2, 3); // should log 1, 2, 3

However, when there is a var arguments; declaration, arguments shouldn’t refer to the outer function’s arguments anymore. When replacing arguments, we need to check if it was defined as a variable in the local scope using argumentsChild.scope.hasOwnBinding("arguments").

Note that we also need to check argumentsChild.scope.parent, argumentsChild.scope.parent.parent and so on: we should stop when we reach a non-arrow function scope, which defines the implicit arguments binding.

A few test cases:

var foo = () => {
  var arguments = 1;
  return arguments;
};
var foo = () => {
  var arguments = 1;
  return () => arguments;
};
function fn() {
  var arguments = 1;
  var foo = () => {
    return arguments;
  };
}
var arguments = 1;
function fn() {
  var foo = () => {
    return arguments;
  };
}

If it is the first time that you contribute to Babel, follow these steps: (you need to have make and yarn available on your machine)

  1. Write a comment there to let other possible contributors know that you are working on this bug.
  2. Fork the repo
  3. Run git clone https://github.com/<YOUR_USERNAME>/babel.git && cd babel
  4. Run yarn && make bootstrap
  5. Wait ⏳
  6. Run make watch (or make build whenever you change a file)
  7. Add a test (only input.js; output.js will be automatically generated)
  8. Update the code!
  9. yarn jest plugin-transform-arrow-functions to run the tests
    • If some test outputs don’t match but the new results are correct, you can delete the bad output.js files and run the tests again
    • If you prefer, you can run OVERWRITE=true yarn jest plugin-transform-arrow-functions and they will be automatically updated.
  10. If it is working, run make test to run all the tests
  11. Run git push and open a PR!

I have started working on the issue!

It’s expected that it doesn’t stop: it’s waiting for you to change some files. I suggest leaving it in the background and opening a new terminal.

That’s expected (I should have been clearer): make watch never ends. If you modify a file and save it, you’ll notice that the make watch command that is running will produce new output showing that it re-compiled the updated file.

@nicolo-ribaudo Very appreciate your help for finding the root cause! Let me take a look and see if I can fix it.

Thanks for your answer! It works!

However, it seems the semantic of the program got changed. For example, if the input is like this:

var foo = () => {
 var arguments = 1;
 console.log(arguments);
};

foo();

The output is

var _arguments = arguments;

var foo = function () {
  var arguments = 1;
  console.log(_arguments);
};

foo();

Then the output in console is different. Could you give me some more advise? Thanks!

You can pass sourceType: "script" as an option to Babel. The default value is "module", and that code is not valid inside modules.