Skip to content

unsafe compress option produces invalid output when using ternary if - case not really hinted by readme #988

Closed

Description

@danieltroger

Bug report

Version (complete output of terser -V or specific git commit): https://try.terser.org/ / terser 5.7.0

Complete CLI command or minify() options used

{
  module: true,
  compress: {unsafe: true},
  mangle: {},
  output: {},
  parse: {},
  rename: {},
}

terser input

function breaks_terser() {
  const t = [];
  (Math.random() < 0.5 ? t : []).push("lengthisnownolongerzero")
  return 1 <= t.length
}
const possible_outputs = [];
for (let i = 0; i < 100; i++) {
  possible_outputs.push(breaks_terser());
}
console.log([...new Set(possible_outputs)]);

terser output or error

function n(){const n=[];return(Math.random()<.5?n:[]).push("lengthisnownolongerzero"),!1}const o=[];for(let e=0;e<100;e++)o.push(n());console.log([...new Set(o)]);

Output when ran: [false]

Expected result

Expected code output: function n(){const n=[];return(Math.random()<.5?n:[]).push("lengthisnownolongerzero"),1<=n.length}const o=[];for(let e=0;e<100;e++)o.push(n());console.log([...new Set(o)]); (same as without unsafe compress option)

Expected output when ran: [true, false] or [false, true]

Context

I wondered today why my slider is not loading the images behind the viewport after the images in the viewport has loaded in production but does so in development. The example code here is really dumbed down to demonstrate the issue. But basically terser assumes the length of the array is going to be zero because it doesn't understand that the ternary statement can change its length.

If the ternary statement is converted to a normal if statement like this the terser output is as expected:

function breaks_terser() {
  const t = [];
  if (Math.random() < 0.5) {
    t.push("lengthisnownolongerzero")
  } else {
    [].push("lengthisnownolongerzero");
  }
  return 1 <= t.length
}
const possible_outputs = [];
for (let i = 0; i < 100; i++) {
  possible_outputs.push(breaks_terser());
}
console.log([...new Set(possible_outputs)]);

According to my interpretation of this: https://github.com/terser/terser#the-unsafe-compress-option using the ternary statement should not break the output when using the unsafe option.

Activity

  1. fabiosantoscode commented on May 30, 2023

    @fabiosantoscode
    Collaborator

    Looks like this has been since fixed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions