Skip to content

babel-plugin-minify-dead-code-elimination is too eager on jquery.js #691

@lydell

Description

@lydell

Input

function test(props) {
  var isBox = "width" in props;

  for (prop in props) {
    delete props[prop];
  }
  // This also triggers the bug:
  // delete props.width;

  if (isBox) {
    console.log("hello");
  }
}

Output

function test(props) {

  for (prop in props) {
    delete props[prop];
  }
  // This also triggers the bug:
  // delete props.width;

  if ("width" in props) {
    console.log("hello");
  }
}

Problem

The minifier inlines the isBox variable, which moves the "width" in props expression. However, at that point the "width" property has been removed from props, effectively making "width" in props always be false, so that console.log("hello") never runs.

Here's how I tested: https://github.com/lydell/babel-plugin-minify-dead-code-elimination-bug/blob/master/minimal.js

jQuery!

This bugs affects jQuery!

A minimal repo with test cases can be found here: https://github.com/lydell/babel-plugin-minify-dead-code-elimination-bug

What happens is that after I’ve run babel-plugin-minify-dead-code-elimination on jquery.js (node_modules/jquery/dist/jquery.js), the .slideToggle() method no longer behaves correctly: It does animate the height of elements, but fails to apply overflow: hidden; while animating, making text inside elements overflow.

Info

Here’s exactly how I run babel-plugin-minify-dead-code-elimination: https://github.com/lydell/babel-plugin-minify-dead-code-elimination-bug/blob/master/minify.js

Here’s the diff between input and output of jquery.js, so you can see what babel-plugin-minify-dead-code-elimination has done: https://github.com/lydell/babel-plugin-minify-dead-code-elimination-bug/blob/master/jquery.diff

I've also manually reverted changes made by the minifier until only the breaking change was left. Here's the diff for that: https://github.com/lydell/babel-plugin-minify-dead-code-elimination-bug/blob/master/jquery-edit.diff

In the production app where I discovered this, I use babel-minify-webpack-plugin and new MinifyPlugin({deadcode: false}) is a workaround.

Expected behavior (before minify)

Click to show gif

Actual behavior (after minify)

Click to show gif

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions