mishoo / UglifyJS

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

RangeError: Maximum call stack size exceeded #414

Closed azhang closed 10 years ago

azhang commented 10 years ago

I'm getting this error when I run

uglifyjs build/someproject.js -o build/someproject.min.js --compress

Any idea why?

jdalton commented 10 years ago

I seen this too on large js files:

...[uglify-js\lib\utils.js:166](https://github.com/mishoo/UglifyJS2/blob/83e0939088a26ad8c28bd2c1719f92bdcf17d045/lib/utils.js#L166) if (array.indexOf(el) < 0)              ^ RangeError: Maximum call stack size exceeded

mishoo commented 10 years ago

@jdalton try running with node --stack_size=100000 uglifyjs.

Everything is recursive in UglifyJS, so I don't see any other fix for this, it just needs a higher stack size.

jdalton commented 10 years ago

Good to know. Thanks!

jdalton commented 10 years ago

Increasing the stack size --max-stack-size=100000000000000000000 still errored on the 5mb js file.

mishoo commented 10 years ago

@jdalton maybe there's a bug then, can you send me the file?

neekey commented 9 years ago

Same problem with large files

ben-ng commented 9 years ago

i've encountered this same problem

rvanvelzen commented 9 years ago

@neekey @ben-ng Could any of you provide us with an example with which this is reproducable?

ben-ng commented 9 years ago

this happened when i was trying to minify a file that included moment-timezone's npm module.

avdg commented 9 years ago

I've just minified a hand build moment-timezone with default node settings. Nothing unusual...

https://gist.githubusercontent.com/avdg/4e8439f004c10d99139a/raw/c53c3c51d3eaa5103e6876d738dad7466251e6fe/moment-timezone-full.js

neekey commented 9 years ago

@rvanvelzen check out this http://g.tbcdn.cn/tb/m-map-shopping/0.1.0/common/draw.js, this is a large JS file containing canvas drawing code, I have already compressed it with YUICompressor( it's not appropriate to provide you the source code),and it will throw Maximum call stack size exceeded if you try to minify it with uglifyJS (the source code will throw the same error)

rvanvelzen commented 9 years ago

@neekey Thanks. Even with a huge stack size that doesn't compile. However, I'm interested in whether it does compile the uncompressed version.

glasser commented 9 years ago

Here's another example of a file that UglifyJS can't compress: https://raw.githubusercontent.com/PeppeL-G/meteor-big-js-problem/de260b58396788bc7edaa1efa7d84f453d894a2d/client/ol.js

uglifyjs ol.js -c crashes with

/Users/glasser/Projects/Meteor/UglifyJS2/lib/transform.js:0
/***********************************************************************
^
RangeError: Maximum call stack size exceeded

with current HEAD (ae07714).

mishoo commented 9 years ago

@glasser indeed, I can reproduce it. However, if you increase the stack size it'll work, for example the following does the trick here:

node --stack_size=100000 /path/to/uglifyjs-repo/bin/uglifyjs ol.js -cm

and the result is 1420343 bytes.

I routinely run UglifyJS on files bigger than yours, so I'm assuming there's some deep nesting into your file which causes a stack overflow. I'll try to investigate.

glasser commented 9 years ago

Sure, but increasing Node's global stack size is a pretty blunt tool, especially when running uglify is just one thing of many that our process is doing (and we use fibers, which definitely does odd things with the stack). We could run uglify in a subprocess I guess.

If it does turn out there's something simpler here, that would be great!

mishoo commented 9 years ago

We could run uglify in a subprocess I guess.

Since I was able to reproduce it by running the uglifyjs CLI tool from a terminal, I guess that won't help. (well, unless you increase the stack for the subprocess)

I'll try to figure out what causes it; can't promise anything though. Some files are just too deeply nested—doesn't seem to be the case with your example, though, so I'm hoping it's just a bug that can be fixed. But right now, I'm calling it a night. ;-)

glasser commented 9 years ago

Right, I was suggesting increasing the stack for the subprocess rather than for the host process.

Thanks for the release and good night! Managed to close two meteor bugs with that release :)

mishoo commented 9 years ago

@glasser sorry for the delay. I pushed a fix that should help.

The issue in your case is that there are about 10000 consecutive statements in a single function; most of them are SimpleStatement nodes, which UglifyJS will try to join into a Sequence (with the comma operator). In many cases this reduces the number of statements, leading to an eventual drop of some brackets — but it hardly helps with a sequence so big, so I limited sequences to 2000 expressions. Works here now without manually increasing the stack and the generated file is only a few bytes longer.

glasser commented 9 years ago

@mishoo Looks like it fixes our reported bug! Looking forward to seeing it released.

faitno commented 8 years ago

+1

mojoaxel commented 8 years ago

Sadly this problem still exists in v2.6.2. Using the compress option results in the error: RangeError: Maximum call stack size exceeded, without any helpful debug information.

I'm using this source file:

uglifyjs app.js -c
kzc commented 8 years ago

@mojoaxel I think app.js has a couple of different issues on master.

Here's one of them: #1041

kzc commented 8 years ago

@mojoaxel

Until #1041 is fixed you can remove the @const pragma in your JS:

        /**
         * Base namespace for the Closure library.  Checks to see goog is already
         * defined in the current scope before assigning to prevent clobbering if
         * base.js is loaded more than once.
         *
         * @const
         */
        var goog = goog || {};

The other issue is just stack size. Workaround:

node /path/to/uglifyjs --stack-size=1000 app.js -c
mojoaxel commented 8 years ago

@kzc Thanks for the quick response! This code-snippet is obviously part of google's closure lib. Therefore it is not that simple to just change the code ;-) No problem we wait for #1041.

We use UglifyJS2 as part of the [webpack uglifyjs-plugin].(https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin). I have not yet found a way of setting the node stack size in the context of a webpack plugin.

For now we are going back to UglifyJS2@2.5.0 to avoid this issue.

kzc commented 8 years ago

Therefore it is not that simple to just change the code

sed can do wonders.

I think @const functionality really ought to be behind its own compress flag as there's no way to disable it.

I have not yet found a way of setting the node stack size in the context of a webpack plugin.

Isn't webpack itself a node program? If so, run it with node --stack-size=10000

kzc commented 8 years ago

Workaround until uglify-js release with fix #1042:

 echo '/* @const */ var goog = goog || {};' | uglifyjs -c evaluate=false
andrewfaria commented 8 years ago

Yeah... with Google Closure, after webpack does it's thing, I run this:

#!/bin/sh

for i in $(ls public/js/client | grep -v map)
do
    TARGET="public/js/client/$i"
    echo "compressing $TARGET"
    sed -i 's/@const//g' $TARGET
    node --stack_size=1000000 node_modules/.bin/uglifyjs -c -m -o $TARGET $TARGET
done
ramsunvtech commented 5 years ago

I've faced this same problem recently and came across to this thread but my problem was with React App Build in Webpack and Uglify bundle error. Below changes in the node build command solved my issues.

Syntax

node --stack-size=<your-size> scripts/build.js

Example

node --stack-size=1000 scripts/build.js

Why size is 1000 in max-old-space-size?

Basically, it varies depends on the call stack of your current application scripts.

How to verify and give right size?

This is basically stay in our engine v8. below command helps you to understand the Call stack Size of your local node v8 engine.

node --v8-options | grep -B0 -A1 stack-size