question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[transform-parameter] Incorrect IIFE when shadowed variable initialized from parameters

See original GitHub issue
  • First, check a function like this:
const dateSample = (date, defValue = 0) => {
  var date = new Date(date, defValue);
  return date;
}
  • And then transfer it with Babel 7:
var dateSample = function dateSample(date) {
  var defValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  return function () {
    var date = new Date(date, defValue);
    return date;
  }();
};

The input param date is discarded for function scope chain.

  • But if you transfer the original code with Babel 6, the output code is:
var dateSample = function dateSample(date) {
    var defValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

    var date = new Date(date, defValue);
    return date;
};

Yeah! You can run it perfectly.

I am not sure if it is a bug! But I think the original code is not a good coding habit, which should be processed as an error to warn the developers.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
JLHwungcommented, Mar 21, 2020

The Babel 7 behaviour is expected. I would not consider it a bug yet it is indeed sub-optimal.

The input param date is discarded for function scope chain.

When there is a variable declaration shadowing the function parameter binding, (i.e. var date inside date-param function), we will wrap the function body inside an IIFE so that the scope of the var-binding is always up to its function body. That means it should not interfere with the desugared parameter initializer. For example (taken from packages/babel-plugin-transform-parameters/test/fixtures/parameters/var-same-as-param-closure/exec.js)

var x = 1
function foo(x, y = function () { x = 2 }) {
  var x = 3
  y()
  expect(x).toBe(3);
}
foo()
expect(x).toBe(1);

If we do not wrap var x = 3; y() into an IIFE, x will be changed to 2 by default y implementation.

I think the original code is not a good coding habit, which should be processed as an error to warn the developers.

True. But babel placed correctness over legibility. The babel processed code is not supposed to be of good readability.

Note that in your case, the IIFE is redundant, and we could definitely improve it a bit using the following heuristics:

Do not wrap function body as IIFE if

  1. the parameters contain either Assignment Pattern or Identifier
  2. at least one of parameters is Assignment Pattern
  3. The initializer of the assignment pattern is a literal (does not refer to any other params)

PR is welcome.

P.S. I assume you intend to use the term “transform” instead of “transfer”.

0reactions
huanzhiyazicommented, Mar 23, 2020

@JLHwung Wow! A clearer example:

((a = 41) => {
  var a = a + 1;
  return a;
})()
// should return 42
Read more comments on GitHub >

github_iconTop Results From Across the Web

no-shadowed-variable - Rule
When set to false parameters, classes, enums and variables declared with let or const are not considered shadowed if the shadowing occurs within...
Read more >
Making Sense of 'No Shadowed Variable' tslint Warning
The linter complains because you are redefining the same variable multiple times. Thus replacing the ones in the closure containing it.
Read more >
no-shadow - ESLint - Pluggable JavaScript Linter
The shadowing variable must be on the right side and declared in a callback function or in an IIFE. Examples of incorrect code...
Read more >
C++ static code analysis: Variables should not be shadowed
It is common in a constructor to have constructor arguments shadowing the fields that they will initialize. This pattern avoids the need to...
Read more >
Essential JavaScript: Mastering Immediately-invoked Function ...
Before we can understand what an IIFE is and why we need one, we need to review a few ... But the init...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found