Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

minify: top level const used only once, value is replaced but variable not deleted #7473

Open
EgoziE opened this issue May 30, 2023 · 3 comments
Labels

Comments

@EgoziE
Copy link

EgoziE commented May 30, 2023

Describe the bug

When minified, a constant which is used only once is not deleted even if it's only usage is being replaced with it's value.

My code:

import { minifySync } from "@swc/core";

const src = `
const text = 'Some text';
console.log(text);
`;

const result = minifySync(src, {
    mangle: true,
    compress: true
});

console.log(result.code);

The playground output is correct, but my code produce a different output.

Input code

const text = "Some text";
console.log(text);

Config

No response

Playground link

https://play.swc.rs/?version=1.3.60&code=H4sIAAAAAAAAA0vOzysuUShJrShRsFVQCs7PTQVzlKy5koEy+Tmpejn56RogIU1rABXGmJMsAAAA&config=H4sIAAAAAAAAA42VzW7bMAyA732KwOcetsOAYg/Q1xAUiXKUyaIg0m6Mou8+2nHSZKaNXRybH38k/uXz5XBozuSa34dPeZWPYitBvX+LhMbM9iKSBlxnydVYuHm90TNNKNhEMIu+rqRhW1vg2Yp+LepNQiS4qS+yLuYYxseAnc1tggfJ5A5LggHSs/GM/gAU45IlyrYD2tIIu7TUOFgG+cWiKUV4U6Rkg63x54+nDNxzIAoOu1KB6Pkykpq+g8xaIFsrfkyAa/8oPyImsHmHGEsmZoYWqubYYUq2EJjBVsXLdFK5C6EWYoI9g7+nZ8WzjxwxS8w19WC9cehBQbGC4ziAZiaxxCwTJlDuM2MPx75t5379xxoGm3qpqEIuc0nktIrXE0ZiE/qspfAKN3JwhUtyV+0TTAXua17bnTHmjZr8b2dLP21Z73d9zEGmj0eFy6hqt8zQTmMSY1AyO2UGKketmhV872DKrNOOs+CN9FH0YCAE6RXFNX1EdictKI8FMChA6muD1lVXYO5TuMGngdjB73JL1hts0egsn7Ypjd0R006ADviEfkdBSsG4jatsiUvZ5n32IK0BXlXpaQbrJSADwGjSvPdXvSHjIR5Nm/D4vSZuG/Pl9px35/efwqzz9Rc+NnjbpwYAAA==

Expected behavior

console.log("Some text");

Actual behavior

const text="Some text";console.log("Some text");

Version

1.3.61

Additional context

When the constant is used twice, it is minified correctly:

const text = 'Some text';
console.log(text);
console.log(text);

becomes:

const text="Some text";console.log(text),console.log(text);

Also let and var is minified as expected.
And if the constant is inside any scope it is minified as expected.

@EgoziE EgoziE added the C-bug label May 30, 2023
@kwonoj
Copy link
Member

kwonoj commented May 30, 2023

Playground runs transform interface and your example runs minify only. (that's the reason it shows different output)

(this is off topic, but for the reference)

@kdy1 kdy1 self-assigned this May 31, 2023
@kdy1 kdy1 added this to the Planned milestone May 31, 2023
@Austaras
Copy link
Member

No idea why but this behavior is strictly copied from terser.

@kdy1 kdy1 removed their assignment Jun 2, 2023
@kdy1 kdy1 removed this from the Planned milestone Jun 2, 2023
@thebanjomatic
Copy link

thebanjomatic commented Jul 6, 2023

@Austaras The behavior doesn't really appear to strictly match terser from what I can see. If you use a longer string the problem is even more clear.

swc.minify produces:

const text="Some really long text that you definitely don't want to include twice because it's really long";console.log("Some really long text that you definitely don't want to include twice because it's really long");

Terser with the same settings produces the more reasonable output of:

const text="Some really long text that you definitely don't want to include twice because it's really long";console.log(text);

It doesn't ever really make sense to inline in this particular case because the variable is declared in the global scope and thus can't be dropped. As a result, any inlining is going to result in duplication. If you add the module: true option to both terser and swc, then you get consistent and sensible output where the string is inlined and only appears once:

console.log("Some really long text that you definitely don't want to include twice because it's really long");

This is because the variable test is now in module scope instead of being declared as a global and isn't observable outside of the module and can be safely removed. But the behavior for module: false is less than ideal.

@kdy1 kdy1 assigned kdy1 and unassigned kdy1 Jul 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

5 participants