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

Incorrect handling of function default params when shadowed #1478

Open
jjhuff opened this issue Dec 5, 2023 · 3 comments
Open

Incorrect handling of function default params when shadowed #1478

jjhuff opened this issue Dec 5, 2023 · 3 comments
Labels

Comments

@jjhuff
Copy link

jjhuff commented Dec 5, 2023

Bug report

While we encountered this in our codebase, I can also repro with https://try.terser.org/

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

$ yarn run terser -V
terser 5.25.0

Complete CLI command or minify() options used

// edit terser options
{
  module: true,
  compress: {},
  mangle: {},
  output: {},
  parse: {},
  rename: {},
}

terser input

export const exp = (t) => 1 ;

export function smoothDamp(easing = exp) {
  const exp = easing(10); 
}

terser output or error

export const exp=o=>1;export function smoothDamp(o=t){const t=o(10)}

Expected result

export const exp=o=>1;export function smoothDamp(o=exp){o(10)}

t in the output is undefined in global scope. In our case, it appears that it was getting assigned to another function -- leading to some really weird stuff. However, in the original case, it just doesn't work. By changing const exp to const e, the param default is handled correctly as exp.

Now, if you change const exp = easing(10); to be const e = easing(10); , you get correct output:

A coworker happened to try with esbuild:
https://esbuild.github.io/try/#dAAwLjE5LjgALS1taW5pZnkAZXhwb3J0IGNvbnN0IGV4cCA9ICh0KSA9PiAxIDsKCmV4cG9ydCBmdW5jdGlvbiBzbW9vdGhEYW1wKGVhc2luZyA9IGV4cCkgewogIGNvbnN0IGV4cCA9IGVhc2luZygxMCk7IAp9

@fabiosantoscode
Copy link
Collaborator

This is indeed a bug. And an incredibly hard one to fix. I think this is because there's a scope for the function's default parameters, and another for the function's variables. Thanks for reporting!

@jjhuff
Copy link
Author

jjhuff commented Dec 6, 2023

Cool, thanks! Yeah, function scopes are a pain.

@fabiosantoscode
Copy link
Collaborator

fabiosantoscode commented Feb 11, 2024

I think the advanced bits of this problem are impossible to fix such as the scope of var x here (from mishoo/UglifyJS#2662):

function(x, f = (() => x)) {
    var x;
    var y = x; // reading the argument `x`
    x = 2; // creating `var x`
    return [ x, y, f() ];
}(1);

This returns [2, 1, 1] because the inner x binding is only created by x = 2. Until then, accessing x goes to the outer scope, with the function args.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants