babel / babel/minify

dead-code-elimination: doesn't remove the value of unused const (let/var too?)

Open
#973 2 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**

I'm just experimenting with set of plugins and presets, plus terser to see what is happening.

In one of the `if` branches that I have, I have unused const variable, what dead-code-elimination is doing is that it's removing the `const val =` an the value remains.

**To Reproduce**

Minimal code to reproduce the bug

```js
const foo = (str: string) => {
const pro = /(?\d{4})-(?\d{2})-(?\d{2})/

if (process.env.NODE === '123') {
return 1234
}
if (process.env.WAS === str) {
const someRe = new RegExp(`

# A regular expression for date.

(?\\d{4})- # year part of a date
(?\\d{2})- # month part of a date
(?\\d{2}) # day part of a date

`, 'x');

return pro
}

return process.env.BAR || process.env.QUX === 'sas'
}

console.log(foo('was was'))

```

with config shown below.

And run it with

```
WAS='was was' babel index.ts -d dist -x .ts
```

**Actual Output**

Which outputs

```js
const foo = str => {
const pro = /(\d{4})-(\d{2})-(\d{2})/;

if ("was was" === str) {
/(\d{4})-(\d{2})-(\d{2})/;
return pro;
}

return void 0 || void 0 === 'sas';
};

console.log(foo('was was'));
```

Now, you can see it's clearly not correct - the regex remains and changes the meaning completely. Only the `const someRe =` is removed. It's not some collision of the `modern-regexp` transform. When we remove that transform it still just removes the `const someRe=` instead of the whole regex thing block.

That is a problem, because the above output later can be minified with terser to a thing that means totally different thing:

```js
const foo=o=>{return"was was"===o&&/(\d{4})-(\d{2})-(\d{2})/}
```

Where you can clearly see that it is not correct.

**Expected Output**

If this dead-code-elimination plugin was working right it would remove the const and the whole regex so the terser's output will be something like

```js
const foo=o=>{return /(\d{4})-(\d{2})-(\d{2})/}
```

and the following when not minified

```js
const foo = str => {
const pro = /(\d{4})-(\d{2})-(\d{2})/;

if ("was was" === str) {
return /(\d{4})-(\d{2})-(\d{2});
}

return void 0 || void 0 === 'sas';
};

console.log(foo('was was'));
```

**Stack Trace**

none

**Configuration**

Using pieces of `babel-minify`.

babel.config.js

```js
const modernRegex = false

module.exports = {
presets: [
'@babel/preset-typescript',
'@babel/preset-modules'
],
plugins: [
'babel-plugin-annotate-pure-calls',
'babel-plugin-dev-expression',
'babel-plugin-minify-builtins',
'babel-plugin-transform-inline-environment-variables',
'babel-plugin-transform-modern-regexp',
'babel-plugin-transform-node-env-inline',
'babel-plugin-transform-undefined-to-void',
'babel-plugin-minify-dead-code-elimination',
'babel-plugin-unassert',
].filter(Boolean)
}

```

How are you using babel-minify?

Babel CLI

```json
"dependencies": {
"@babel/cli": "^7.8.0",
"@babel/core": "^7.8.0",
"@babel/preset-modules": "^0.1.2",
"@babel/preset-typescript": "^7.8.0",
"@types/node": "^13.1.6",
"babel-plugin-annotate-pure-calls": "^0.4.0",
"babel-plugin-dev-expression": "^0.2.2",
"babel-plugin-minify-builtins": "^0.5.0",
"babel-plugin-minify-dead-code-elimination": "^0.5.1",
"babel-plugin-transform-inline-environment-variables": "^0.4.3",
"babel-plugin-transform-modern-regexp": "^0.0.6",
"babel-plugin-transform-node-env-inline": "^0.4.3",
"babel-plugin-transform-undefined-to-void": "^6.9.4",
"babel-plugin-unassert": "^3.0.1",
"terser": "^4.6.2"
}
```

**Possible solution**

Don't know.

Contributor guide

Open the contributing guide

Research direction

Start with the minimal TypeScript reproduction and babel.config.js, then run it through the Babel CLI with babel-plugin-minify-dead-code-elimination enabled. Compare the transformed output with the expected output, including the unused RegExp initializer, and verify that the plugin no longer leaves a standalone expression that changes behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
babel, javascript, typescript
Domain
build-system, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.