From 4621481f0061e1e15e2f511a0296a0cef7cb35f7 Mon Sep 17 00:00:00 2001 From: Pablo Cubico Date: Thu, 25 Feb 2016 09:04:27 -0300 Subject: [PATCH] Attempt on supporting strict mode reserved words conditionally. --- lib/parse.js | 12 ++++++++---- lib/scope.js | 7 ++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/parse.js b/lib/parse.js index f1495153..8c243b43 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -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_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' - + " " + KEYWORDS_ATOM + " " + KEYWORDS; +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; // 'yield' is reserved in Firefox even outside strict mode. 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); RESERVED_WORDS = makePredicate(RESERVED_WORDS); KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION); KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM); +RESERVED_WORDS_STRICT_ONLY = makePredicate(RESERVED_WORDS_STRICT_ONLY); var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^")); @@ -152,8 +154,10 @@ function is_unicode_connector_punctuation(ch) { return UNICODE.connector_punctuation.test(ch); }; -function is_identifier(name) { - return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name); +function is_identifier(name, strict_mode) { + 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) { diff --git a/lib/scope.js b/lib/scope.js index ace25894..13eed6ad 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -134,6 +134,10 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){ s.uses_with = true; return; } + if (node instanceof AST_Directive) { + scope.directives.push(node.value); + return; + } if (node instanceof AST_Symbol) { 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.cname = -1; // the current index for mangling functions/variables 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(){ @@ -287,7 +292,7 @@ AST_Scope.DEFMETHOD("next_mangled", function(options){ var ext = this.enclosed; out: while (true) { 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 // shadow a name excepted from mangling.