mishoo / UglifyJS

JavaScript parser / mangler / compressor / beautifier toolkit
http://lisperator.net/uglifyjs/
Other
13.17k stars 1.25k forks source link

ERROR: Maximum call stack size exceeded #5951

Open PavelFil opened 1 month ago

PavelFil commented 1 month ago

uglify-js 3.19.3

test-js.zip Run

uglifyjs test.js

Receive

ERROR: Maximum call stack size exceeded
    at [Symbol.hasInstance] (<anonymous>)
    at Object.prepend_comments (eval at <anonymous> (/usr/local/lib/node_modules/uglify-js/tools/node.js:18:1), <anonymous>:21553:18)
    at doit (eval at <anonymous> (/usr/local/lib/node_modules/uglify-js/tools/node.js:18:1), <anonymous>:21691:20)
    at AST_Binary.eval [as print] (eval at <anonymous> (/usr/local/lib/node_modules/uglify-js/tools/node.js:18:1), <anonymous>:21686:13)
    at AST_Binary.eval [as _codegen] (eval at <anonymous> (/usr/local/lib/node_modules/uglify-js/tools/node.js:18:1), <anonymous>:22633:19)
    at doit (eval at <anonymous> (/usr/local/lib/node_modules/uglify-js/tools/node.js:18:1), <anonymous>:21693:18)
    at AST_Binary.eval [as print] (eval at <anonymous> (/usr/local/lib/node_modules/uglify-js/tools/node.js:18:1), <anonymous>:21686:13)
    at AST_Binary.eval [as _codegen] (eval at <anonymous> (/usr/local/lib/node_modules/uglify-js/tools/node.js:18:1), <anonymous>:22633:19)
    at doit (eval at <anonymous> (/usr/local/lib/node_modules/uglify-js/tools/node.js:18:1), <anonymous>:21693:18)
    at AST_Binary.eval [as print] (eval at <anonymous> (/usr/local/lib/node_modules/uglify-js/tools/node.js:18:1), <anonymous>:21686:13)
liquancss commented 3 weeks ago

In this way, Uglify will call the AST_Binary.print methods recursively and can lead to stack overflow error. You can try to replace doit() function call with it's actual code to reduce call frame.

// ./lib/output.js
AST_Node.DEFMETHOD("print", function(stream, force_parens) {
        var self = this;
        stream.push_node(self);
        if (force_parens || self.needs_parens(stream)) {
            stream.with_parens(doit);
        } else {
            // doit()
            stream.prepend_comments(self);
            self.add_source_map(stream);
            self._codegen(stream);
            stream.append_comments(self);
        }
        stream.pop_node();

        function doit() {
            stream.prepend_comments(self);
            self.add_source_map(stream);
            self._codegen(stream);
            stream.append_comments(self);
        }
    });