NUglify icon indicating copy to clipboard operation
NUglify copied to clipboard

Refactoring JS breaks variable scope

Open ianleeder opened this issue 2 years ago • 5 comments

Tested using 1.20.6

Describe the bug NUglify refactors JS code, and moves variables inside block scope, breaking functions that reference that variable.

To Reproduce This example uses C#11 raw string literals

using NUglify;

string testJs =
$$"""
document.addEventListener("DOMContentLoaded", () => {
    const body = document.querySelector("body");
    if (!body) {
      return;
    }
    const foo = 'bar'
    doIt();
    function doIt() {
        console.log(foo);
    }
  });
""";

UglifyResult uglified = Uglify.Js(testJs);
Console.WriteLine(uglified.Code);

Minified output or stack trace The minified code:

document.addEventListener("DOMContentLoaded",()=>{function i(){console.log(t)}const n=document.querySelector("body");if(n){const t="bar";i()}})

You can clearly see (once formatted), that the variable t is no longer accessible by the function i:

document.addEventListener("DOMContentLoaded", ()=>{
    function i() {
        console.log(t)
    }
    const n = document.querySelector("body");
    if (n) {
        const t = "bar";
        i()
    }
}
)

Uncaught ReferenceError: t is not defined at i

Excepted output code Variable declaration should not be moved inside the if block.

ianleeder avatar Apr 17 '23 07:04 ianleeder

If you change Const to Var does it still happen? What about Let?

trullock avatar Apr 17 '23 07:04 trullock

Changing the variable to var/let/const doesn't make a difference.

Running the same test without all this code inside an event handler works correctly, eg:

const body = document.querySelector("body");
if (!body) {
  return;
}
var foo = 'bar'
doIt();
function doIt() {
  console.log(foo);
}

Generates

function doIt(){console.log(foo)}const body=document.querySelector("body");if(!body)return;var foo="bar";doIt()

The guard-clause hasn't been inverted: if(!body)return;.

Also it no longer renames variables/functions.

ianleeder avatar Apr 17 '23 23:04 ianleeder

The non-renaming is expected as they are in global scope (and be theoretically be used elsewhere)

Otherwise it does seem like a bug then

trullock avatar Apr 19 '23 10:04 trullock