lautis / uglifier

Ruby wrapper for UglifyJS JavaScript compressor.
http://www.rubydoc.info/gems/uglifier
MIT License
615 stars 81 forks source link

Uglifier 3.1.0 produces "invalid assignment left-hand side" #110

Closed bodrovis closed 7 years ago

bodrovis commented 7 years ago

Good day. After updating to Uglifier 3.1.0 I am starting to get a JS error in production saying "invalid assignment left-hand side". It happens on Heroku with Rails 5, Ruby 2.3. I am not really sure whether this should be reported here or at UglifyJS repo. After some inspection it appeared that the following line is problematic:

do 1 = 1, u /= 1, dt.style(t, e, u + a); while (1 = o() / s, !1)

This is a deobfuscated line of code that relates to jQuery 1 (it happens with jQuery 2 as well). Switching back to Uglifier 3.0.4 solves the problem. I can send minified and deobfuscated js files.

jasonroelofs commented 7 years ago

I have also run into this. The generated code is such:

for(var o="function"==typeof require&&require;0<r.length;0++)i(r[0]);return i}

That's a number zero getting an increment operator. Previously that was a proper variable s. I'm not really sure what underlying code is hitting this but it seems to be some shim code to loading compiled ES6 modules.

lautis commented 7 years ago

Does this happen if you disable reduce_vars and collapse_vars options? Those were enabled by default in 3.1 (and also UglifyJS2 2.8.0).

vanitu commented 7 years ago

+1 same issue. solved by downgrading to 3.0.4

bodrovis commented 7 years ago

@lautis sorry for a stupid question, but where should I provide these options for Rails?

lautis commented 7 years ago

@bodrovis, in config/application.rb: config.assets.js_compressor = Uglifier.new(compress: { reduce_vars: false, collapse_vars: false })

brodjustice commented 7 years ago

Not sure if this is the same issue but 3.1 breaks rails 3 by somehow messing up jquery. Fixed by going back to 3.0.4. I can dig in to provide more detail if required.

jasonroelofs commented 7 years ago

@lautis Thanks for the pointer. The problem occurs when reduce_vars: true. From my testing, collapse_vars does not trigger the problem.

bodrovis commented 7 years ago

Yeah, setting reduce_vars to false fixes it.

ahorek commented 7 years ago

minification of

function isAllChecked() { var boxes = $('body').find('input[type=checkbox]'); var all_checked = true; boxes.each(function(i) { if (!$(this).is(":checked")) { all_checked = false; } }); return all_checked; }

produces

function isAllChecked() { var c = $("body").find("input[type=checkbox]"); return c.each(function() { $(this).is(":checked") || (!0 = !1); }), !0; }

!0 = !1 => invalid assignment left-hand side

reduce_vars disabled

function isAllChecked() { var c = $("body").find("input[type=checkbox]"), e = !0; return c.each(function() { $(this).is(":checked") || (e = !1); }), e; }

lautis commented 7 years ago

Switched the default value to false for reduce_vars in 3.1.1.

bodrovis commented 7 years ago

@lautis Kiitos!

ncuesta commented 7 years ago

@lautis Thanks for your dedication! This bug just hit us and you shipped the fix before we could even determine the root cause.

Just stopped by to say you're awesome and, once again, thank you for your hard work.

vanitu commented 7 years ago

Thanks a lot for quick fix and support. Great!

lautis commented 7 years ago

There's a spec now that catches at least some errors like this in the future. I changed the minification test to use ExecJS.compile instead of UglifyJS to parse the output of minifying UglifyJS itself. I changed this to make the test suite a bit faster, but it also would've caught the error in 3.1.0.

https://github.com/lautis/uglifier/commit/c800c33daebadaf9ecd3562abc2b27e8279849d2