terser icon indicating copy to clipboard operation
terser copied to clipboard

Incorrect code when compress is enabled.

Open NickBolles opened this issue 2 years ago • 3 comments

Bug report or Feature request?

Version (complete output of terser -V or specific git commit)

  1. https://try.terser.org/ (I can't find a version on there)

  2. [email protected]

  • yarn why terser tells me Terser 5.11.0

Complete CLI command or minify() options used

  1. in the REPL,
// edit terser options
{
  module: false,
  compress: {},
  mangle: {},
  output: {},
  parse: {},
  rename: {},
}
  1. Default webpack 5 settings with [email protected]

terser input

// write or paste code here

function set(propValues, options) {
  var key;
  var value;
  var isSimpleSet = typeof propValues === 'string';
  var allChangeMessages = [];

  // Handle when first argument is a key and second is a value
  if (isSimpleSet) {
    key = arguments[0];
    value = arguments[1];
    options = arguments[2];
    propValues = {};
    propValues[key] = value;
  }

  console.log("arguments", arguments)
  console.log("key", key)
  console.log("value", value)
  console.log("options", options) 
  console.log("propValues", propValues)
}

set("foo", "val", {force: true})

terser output or error

(from try.terser.org)

function set(o,e){var l,s,n="string"==typeof o;n&&(e=arguments[2],(o={})[l=arguments[0]]=s=arguments[1]),console.log("arguments",arguments),console.log("key",l),console.log("value",s),console.log("options",e),console.log("propValues",o)}set("foo","val",{force:!0});

Expected result

The same console logs from the un-compressed and compressed versions.

Here's a screenshot of the outputs, top is un-compressed, bottom is compressed

image

Setting compress: false does not have the same issue. So the issue is scoped to the compress functionality.

NickBolles avatar Mar 14 '22 18:03 NickBolles

Ick, this is behavior with arguments[0] changing values when the o (which is the first param) binding is changed in sloppy mode code:

function sloppy(o) {
  o = 1;
  return arguments[0];
}
function strict(o) {
  "use strict";
  o = 1;
  return arguments[0];
}

sloppy(0); // 1
strict(0); // 0

We need be careful about reordering assignments when in sloppy mode and anything in the function is getting arguments[INDEX].

jridgewell avatar Mar 14 '22 20:03 jridgewell

Wow quick response! I'm really glad I was able to scope this down to a simple repro to find the bug!

NickBolles avatar Mar 15 '22 03:03 NickBolles

Maybe using arguments at all in a function should disable more optimizations than it does.

fabiosantoscode avatar Mar 21 '22 18:03 fabiosantoscode