-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mangling named functions in strict mode can cause syntax errors in Safari #179
Comments
Looks like a bug in Safari, isn't it? |
@mishoo Seems like it. I haven't found anything in the ECMA-262 5.1 that justifies Safari's behavior, but I am a JavaScript noob so I thought maybe it was a matter of interpretation of the spec. Anyway, I wasn't sure and I thought it might be an issue that others would run into. I ran into this "minimizing" an AngularJS project. The code that's tripping up Safari is in AngularJS so I can't modify it. But it looks like I can work around this by using angular.min.js. In case you're interested, that file is generated using Google's closure compiler which apparently converts the nested function into an anonymous function since there are no references to the function's name. Something like:
Maybe that's a worthwhile enhancement? |
It does that if you pass |
Facepalm. Thanks. |
Enabling mangle and compression worked around the Safari bug for me.
On Apr 9, 2013, at 2:31 AM, Eugene Bogomolny notifications@github.com wrote:
|
Encountering this as well, This can break many minified scripts, shouldn't this be handled by uglify in some way (through an option maybe), even it the behavior is safari-only? How can I minify & avoid name collision breaking safari otherwise? |
@mgcrea: On a side note (sorry it's not contributing anything): Thanks for finding this! I found an issue with my own code whereby I was encountering a strict mode exception because I had the following:
The parameter name This bug report saved me a lot of searching time! |
@ashclarke Thanks! Found that this error was indeed triggered by this code:
|
Fixes mishoo#326 and mishoo#179 It isn't a really clean solution, but it works. The idea is to "virtually" reference the function name inside the scope. But to be able know it isn't *really* referenced, we add a `virtual` flag to `AST_SymbolRef.reference`.
I think I have the same issue using uglify-js 2.4.16 via grunt-contrib-uglify 0.7.0. In my case, the error is on something like c.prototype.key=function k(k){var a=this._baseState;return f(null===a.key),a.key=k,this} tested on safari 7 and 8 |
ok, I found the code that produce this result: Node.prototype.key = function key(key) {
var state = this._baseState;
assert(state.key === null);
state.key = key;
return this;
}; It's part of the library added by browserify to my node modules. |
I tried reserving the word 'key', but the result is the same, because key is also a reserved word in ES5. |
I know it's safari bug, but lets try to get the total perspective of ecmascript's keywords @SteeveB where did you get the claim of Looking up the ecmascript standard: (lets assume the input is always an identifier)
(see http://www.ecma-international.org/ecma-262/5.1/#sec-A.1) My current guess is that the safari implementation believes that key is a reserved keyword and by that does not agree with what the ecmascript 5 standard says. Though I will not rule out that previous versions of ecmascript may had it as keyword, but I don't have time yet to find it out. |
@steeeveb The problem is not the word "key" as such. As per my comment, #179 (comment), the problem is that your If you had something like |
Yes, I confirm. Now I'm online with the minified version modified by hand in that point(a little bit ugly :) ) thank you! |
Hi all, I just tried all of approaches to make my codebase to avoid from Safari's issue. But i got fail.. I'm currently using Althrough I passed Here's what i passed into gulp-uglify
And i still can find some named anonymous function with same parameter's name, like: And I'm thinking reasons may be:
Is there anybody suffering the same issue? |
Probably time for a |
This was my solution, removing use strict. function minifyjs(js) { |
Hmm... so the problem was caused because safari wanted to pass the whole es 5 spec stuff literally... The restriction of functions to be limited in global functions and thus disabling that restriction is the es 6 way of doing this... There are tests in the test262 es5 suite to test that so that's how I know about this issue. I can lookup for details if really needed (so please ask) but otherwise you have to stick with the information in this comment :-) In short:
|
A related issue (#1052) has just broken jQuery minification in current (!) Firefox, Safari as well as IE 10. |
I experienced a similar problem due to mistakenly having the following in an AngularJS project: .factory('CustomerStore', function $instanceStore($q, $log, $instanceStore) { Which should have simply been: .factory('CustomerStore', function($q, $log, $instanceStore) { Hope this helps someone with a similar issue. |
This Safari mangling issue was fixed recently: eb63fec Upgrade to latest |
I have upgraded to latest version of gulp-uglify i.e 2.0.1 but I'm still getting the same issue, !function e(t, o, n) {
function r(i, s) {
if (!o[i]) {
if (!t[i]) {
var c = "function" == typeof require && require;
if (!s && c)
return c(i, !0);
if (a)
return a(i, !0);
var l = new Error("Cannot find module '" + i + "'");
throw l.code = "MODULE_NOT_FOUND", l
}
var u = o[i] = {
exports: {}
};
t[i][0].call(u.exports, function(e) {
var o = t[i][1][e];
return r(o ? o : e)
}, u, u.exports, e, t, o, n)
}
return o[i].exports
}
for (var a = "function" == typeof require && require, i = 0; i < n.length; i++)
r(n[i]);
return r
} How can i fix this, or atleast bypass this ? |
@PezCoder you might want to open a separate issue for that as there is no guarantee you are talking about the same issue? |
@avdg I'm confused on what side this issue persist.. gulp-uglify repo or the uglify itself ? |
Seems to be uglify |
Normally any collision on these names won't be an issue but the Safari on iOS 7/8/9 will yield with a SyntaxError. The problem was discuessed and (partially) fixed in mishoo#179 but function definition mangling still breaks: ```js $ echo 'function aaa(){function foo(bar){};foo.name=2;return foo}' | ./node_modules/.bin/uglifyjs --compress --mangle function aaa(){function n(n){}return n.name=2,n} ``` Since symbol names are now [mangled from within](mishoo#2948 (comment)), the mangled argument names can now be appended to `names` cache to make sure the later mangled function name won't collide with them.
Normally any collision on these names won't be an issue but the Safari on iOS 7/8/9 will yield with a SyntaxError. The problem was discuessed and (partially) fixed in mishoo#179 but function definition mangling still breaks: ```js $ echo 'function aaa(){function foo(bar){};foo.name=2;return foo}' | ./node_modules/.bin/uglifyjs --compress --mangle function aaa(){function n(n){}return n.name=2,n} ``` Since symbol names are now [mangled from within](mishoo#2948 (comment)), the mangled argument names can now be appended to `names` cache to make sure the later mangled function name won't collide with them.
In strict mode, Safari 6.0.3 on OS X 10.8.3 raises an exception if a named function's name is the same as one of the function's argument names (at least in some scenarios). For example:
results in the following code:
Safari parses the original code without errors, but the generated code causes the following error:
Manually converting the inner function to be anonymous or renaming to something not matching an argument's name resolves the problem.
Also, the generated code runs fine in Chrome and Firefox and Safari does not raise a syntax error for functions declared globally.
The text was updated successfully, but these errors were encountered: