Uglifyjs: Function call without context in compressed assignment and immediate call

Created on 16 Jun 2017  路  2Comments  路  Source: mishoo/UglifyJS

Bug report
ES5
Uglify version (uglifyjs -V)
uglify-js 3.0.17

JavaScript input
test.js:

function f() {
  f.g = g;
  return f.g();

  function f() {};
  function g(){ return this }
}

The uglifyjs CLI command executed.
uglifyjs test.js -c

JavaScript incorrect output produced.

function f(){function f(){}return(f.g=function(){return this})()}

Description of the problem.
The assignment of f.g and immediate call looses the context of f when calling g. Therefore when g returns this, the later does not refer to f but to the global context.

Expected correct output.

function f(){function f(){}return(f.g=function(){return this}).call(f)}

Also correct, is the output of uglify-js 3.0.15 which is the last version that did not produce an incorrect output:

function f(){function f(){}function g(){return this}return f.g=g,f.g()}

Workaround until a fix is provided.
Do not use this in g, use f instead, this also yields a smaller output:
test-workaround.js:

function f() {
  f.g = g;
  return f.g();

  function f() {};
  function g(){ return f } // use f instead of this
}

Output:

function f(){function f(){}return f.g=function(){return f},f.g()}

Although the compressed output is still incorrect, the execution yields the right result because there is no reference to this.

bug

All 2 comments

@uiteoi thanks for the report - cascade is the culprit in this case:

$ cat test.js
function f() {
  f.g = g;
  return f.g();
  function f() {};
  function g(){ return this }
}
console.log(f().toString());

$ node test.js
function f() {}

```js
$ uglifyjs test.js -b bracketize -c cascade=0
function f() {
function f() {}
return f.g = function() {
return this;
}, f.g();
}

console.log(f().toString());

$ uglifyjs test.js -b bracketize -c cascade=0 | node
function f() {}

```js
$ uglifyjs test.js -b bracketize -c
function f() {
    function f() {}
    return (f.g = function() {
        return this;
    })();
}

console.log(f().toString());

$ uglifyjs test.js -b bracketize -c | node
[object global]

@alexlamsl, I am very impressed with the speed at which you fixed this with proper test cases. Also thanks for your detailed comment, it will help me in the future produce better bug reports, if I ever find anather one, using option -b and console.log() an expected output to help build test cases.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexlamsl picture alexlamsl  路  4Comments

alexlamsl picture alexlamsl  路  4Comments

chrismanley picture chrismanley  路  5Comments

kzc picture kzc  路  5Comments

diegocr picture diegocr  路  3Comments