babel / babel/minify

babel-plugin-minify-dead-code-elimination: Function name gets removed when keepFnNames is enabled in some scenarios

Open
#1,001 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
4.4k
Forks
217
PR merge metrics
No merged PRs in 30d

Description

**Describe the bug**

The name of functions that infer their names from a variable name is being removed when `babel-plugin-minify-dead-code-elimination` is used with the `keepFnNames` option enabled.

All of these function definitions hav the name "func":

```js
function func() {}
console.log(func.name) // "func"
```

```js
const other = function func() {}
console.log(other.name) // "func"
```

```js
const func = function() {}
console.log(func.name) // "func"
```

```js
const func = () => {}
console.log(func.name) // "func"
```

If we return these definitions from a wrapping function before logging the name, the first two will retain the name from their definitions:

```js
function createFunc() {
return function func() {}
}

const func = createFunc()
console.log(func.name) // "func"
```

```js
function createFunc() {
const other = function func() {}
return other
}

const func = createFunc()
console.log(func.name) // "func"
```

However, the second two have lost their names:

```js
function createFunc() {
const func = function() {}
return func
}

const func = createFunc()
console.log(func.name) // ""
```

```js
function createFunc() {
const func = () => {}
return func;
}

const func = createFunc()
console.log(func.name) // ""
```

**To Reproduce**

Minimal code to reproduce the bug

```js
function createFunc1() {
return function func() {}
}

function createFunc2() {
const other = function func() {}
return other;
}

function createFunc3() {
const func = function() {}
return func;
}

function createFunc4() {
const func = () => {}
return func;
}
```

**Actual Output**

If there is no Error thrown,

```js
function createFunc1() {
return function func() {};
}

function createFunc2() {
return function func() {};
}

function createFunc3() {
return function () {};
}

function createFunc4() {
return () => {};
}
```

**Expected Output**

```js
function createFunc1() {
return function func() {}
}

function createFunc2() {
const other = function func() {}
return other;
}

function createFunc3() {
const func = function() {}
return func;
}

function createFunc4() {
const func = () => {}
return func;
}
```

**Configuration**

How are you using babel-minify?

babelrc.js:

```json5
module.exports = {
plugins: [
[require.resolve('babel-plugin-minify-dead-code-elimination'), { keepFnName: true }]
]
}
```

**Possible solution**

The issue seems to be coming from inlining the variable into the return of the function, losing the variable name to infer the function name from.

**Additional context**

I discovered this when function names were being stripped out of stack traces in error logs.

It also seems particularly problematic for React HOCs where the `displayName` for the wrapping component is derived from the function name for a function component, e.g.

```jsx
const withValue = (value) => (Component) => {
const WithValue = (props) => (

)
return WithValue
}

const WrappedComponent = withValue(SomeComponent)
```

Contributor guide

Open the contributing guide

Research direction

Start at the babel-plugin-minify-dead-code-elimination entry point and reproduce the issue with the supplied createFunc1–createFunc4 examples while the keepFnNames option is enabled. Trace the variable inlining that occurs before the returned function is emitted; done means inferred names are preserved for all four cases and the regression is covered by a test.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.