Attempt on supporting strict mode reserved words conditionally.

This commit is contained in:
Pablo Cubico 2016-02-25 09:04:27 -03:00
parent 294861ba96
commit 4621481f00
2 changed files with 14 additions and 5 deletions

View File

@ -46,14 +46,16 @@
var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
var KEYWORDS_ATOM = 'false null true'; var KEYWORDS_ATOM = 'false null true';
var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield' var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto import int long native short super synchronized this throws transient volatile yield'
+ " " + KEYWORDS_ATOM + " " + KEYWORDS; + " " + KEYWORDS_ATOM + " " + KEYWORDS; // 'yield' is reserved in Firefox even outside strict mode.
var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case'; var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
var RESERVED_WORDS_STRICT_ONLY = 'implements interface let package private protected public static';
KEYWORDS = makePredicate(KEYWORDS); KEYWORDS = makePredicate(KEYWORDS);
RESERVED_WORDS = makePredicate(RESERVED_WORDS); RESERVED_WORDS = makePredicate(RESERVED_WORDS);
KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION); KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM); KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
RESERVED_WORDS_STRICT_ONLY = makePredicate(RESERVED_WORDS_STRICT_ONLY);
var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^")); var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
@ -152,8 +154,10 @@ function is_unicode_connector_punctuation(ch) {
return UNICODE.connector_punctuation.test(ch); return UNICODE.connector_punctuation.test(ch);
}; };
function is_identifier(name) { function is_identifier(name, strict_mode) {
return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name); return !RESERVED_WORDS(name)
&& /^[a-z_$][a-z0-9_$]*$/i.test(name)
&& (!strict_mode || strict_mode && !RESERVED_WORDS_STRICT_ONLY(name));
}; };
function is_identifier_start(code) { function is_identifier_start(code) {

View File

@ -134,6 +134,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
s.uses_with = true; s.uses_with = true;
return; return;
} }
if (node instanceof AST_Directive) {
scope.directives.push(node.value);
return;
}
if (node instanceof AST_Symbol) { if (node instanceof AST_Symbol) {
node.scope = scope; node.scope = scope;
} }
@ -237,6 +241,7 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){
this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes
this.cname = -1; // the current index for mangling functions/variables this.cname = -1; // the current index for mangling functions/variables
this.nesting = nesting; // the nesting level of this scope (0 means toplevel) this.nesting = nesting; // the nesting level of this scope (0 means toplevel)
this.directives = []; // a list of directives like "use strict" present in this scope
}); });
AST_Lambda.DEFMETHOD("init_scope_vars", function(){ AST_Lambda.DEFMETHOD("init_scope_vars", function(){
@ -287,7 +292,7 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){
var ext = this.enclosed; var ext = this.enclosed;
out: while (true) { out: while (true) {
var m = base54(++this.cname); var m = base54(++this.cname);
if (!is_identifier(m)) continue; // skip over "do" if (!is_identifier(m, this.directives.indexOf('use strict') >= 0)) continue; // skip over "do"
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not // https://github.com/mishoo/UglifyJS2/issues/242 -- do not
// shadow a name excepted from mangling. // shadow a name excepted from mangling.