Module: wine Branch: master Commit: 3263d51a1fd86abf195c5be224f6fdb4db284b53 URL: https://source.winehq.org/git/wine.git/?a=commit;h=3263d51a1fd86abf195c5be22...
Author: Jacek Caban jacek@codeweavers.com Date: Wed Apr 4 21:43:19 2018 +0200
jscript: Allow using reserved words as identifiers in ES5 mode.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/jscript/lex.c | 2 +- dlls/jscript/parser.y | 58 ++++++++++++++++++++++++++++++++++----- dlls/mshtml/tests/documentmode.js | 18 ++++++++++++ dlls/mshtml/tests/es5.js | 43 ++++++++++++++++++++++++++++- 4 files changed, 112 insertions(+), 9 deletions(-)
diff --git a/dlls/jscript/lex.c b/dlls/jscript/lex.c index 3523958..b4f6d95 100644 --- a/dlls/jscript/lex.c +++ b/dlls/jscript/lex.c @@ -135,7 +135,7 @@ static int check_keyword(parser_ctx_t *ctx, const WCHAR *word, const WCHAR **lva return 1;
if(lval) - *lval = ctx->ptr; + *lval = word; ctx->ptr = p1; return 0; } diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 59e6757..a40b813 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -164,11 +164,11 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state }
/* keywords */ -%token kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kIF kFINALLY kFOR kIN -%token kINSTANCEOF kNEW kNULL kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH +%token <identifier> kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kFUNCTION kIF kFINALLY kFOR kIN +%token <identifier> kINSTANCEOF kNEW kNULL kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH %token tANDAND tOROR tINC tDEC tHTMLCOMMENT kDIVEQ kDCOL
-%token <srcptr> kFUNCTION '}' +%token <srcptr> '}'
/* tokens */ %token <identifier> tIdentifier @@ -241,6 +241,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state %type <literal> BooleanLiteral %type <srcptr> KFunction %type <ival> AssignOper +%type <identifier> IdentifierName ReservedAsIdentifier
%nonassoc LOWER_THAN_ELSE %nonassoc kELSE @@ -272,7 +273,7 @@ FunctionExpression { $$ = new_function_expression(ctx, $4, $6, $9, $2, $1, $10-$1+1); }
KFunction - : kFUNCTION { $$ = $1; } + : kFUNCTION { $$ = ctx->ptr - 8; }
/* ECMA-262 3rd Edition 13 */ FunctionBody @@ -711,7 +712,7 @@ MemberExpression | FunctionExpression { $$ = $1; } | MemberExpression '[' Expression ']' { $$ = new_binary_expression(ctx, EXPR_ARRAY, $1, $3); } - | MemberExpression '.' tIdentifier + | MemberExpression '.' IdentifierName { $$ = new_member_expression(ctx, $1, $3); } | kNEW MemberExpression Arguments { $$ = new_new_expression(ctx, $2, $3); } @@ -724,7 +725,7 @@ CallExpression { $$ = new_call_expression(ctx, $1, $2); } | CallExpression '[' Expression ']' { $$ = new_binary_expression(ctx, EXPR_ARRAY, $1, $3); } - | CallExpression '.' tIdentifier + | CallExpression '.' IdentifierName { $$ = new_member_expression(ctx, $1, $3); }
/* ECMA-262 3rd Edition 11.2 */ @@ -787,7 +788,7 @@ PropertyNameAndValueList
/* ECMA-262 3rd Edition 11.1.5 */ PropertyName - : tIdentifier { $$ = new_string_literal(ctx, $1); } + : IdentifierName { $$ = new_string_literal(ctx, $1); } | tStringLiteral { $$ = new_string_literal(ctx, $1); } | tNumericLiteral { $$ = $1; }
@@ -796,6 +797,49 @@ Identifier_opt : /* empty*/ { $$ = NULL; } | tIdentifier { $$ = $1; }
+/* ECMA-262 5.1 Edition 7.6 */ +IdentifierName + : tIdentifier { $$ = $1; } + | ReservedAsIdentifier + { + if(ctx->script->version < SCRIPTLANGUAGEVERSION_ES5) { + WARN("%s keyword used as an identifier in legacy mode.\n", + debugstr_w($1)); + YYABORT; + } + $$ = $1; + } + +ReservedAsIdentifier + : kBREAK { $$ = $1; } + | kCASE { $$ = $1; } + | kCATCH { $$ = $1; } + | kCONTINUE { $$ = $1; } + | kDEFAULT { $$ = $1; } + | kDELETE { $$ = $1; } + | kDO { $$ = $1; } + | kELSE { $$ = $1; } + | kFALSE { $$ = $1; } + | kFINALLY { $$ = $1; } + | kFOR { $$ = $1; } + | kFUNCTION { $$ = $1; } + | kIF { $$ = $1; } + | kIN { $$ = $1; } + | kINSTANCEOF { $$ = $1; } + | kNEW { $$ = $1; } + | kNULL { $$ = $1; } + | kRETURN { $$ = $1; } + | kSWITCH { $$ = $1; } + | kTHIS { $$ = $1; } + | kTHROW { $$ = $1; } + | kTRUE { $$ = $1; } + | kTRY { $$ = $1; } + | kTYPEOF { $$ = $1; } + | kVAR { $$ = $1; } + | kVOID { $$ = $1; } + | kWHILE { $$ = $1; } + | kWITH { $$ = $1; } + /* ECMA-262 3rd Edition 7.8 */ Literal : kNULL { $$ = new_null_literal(ctx); } diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index b9ac40e..21a3582 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -116,6 +116,20 @@ function test_javascript() { ok(!(func in obj), func + " found in " + obj); }
+ function test_parses(code, expect) { + var success; + try { + eval(code); + success = true; + }catch(e) { + success = false; + } + if(expect) + ok(success === true, code + " did not parse"); + else + ok(success === false, code + " parsed"); + } + var v = document.documentMode;
test_exposed("ScriptEngineMajorVersion", g, true); @@ -125,6 +139,10 @@ function test_javascript() { test_exposed("isArray", Array, v >= 9); test_exposed("indexOf", Array.prototype, v >= 9);
+ test_parses("if(false) { o.default; }", v >= 9); + test_parses("if(false) { o.with; }", v >= 9); + test_parses("if(false) { o.if; }", v >= 9); + next_test(); }
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 9f87e99..9b0dc21 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -73,8 +73,49 @@ function test_isArray() { next_test(); }
+function test_identifier_keywords() { + var o = { + if: 1, + default: 2, + function: 3, + break: true, + case: true, + catch: true, + continue: true, + delete: true, + do: true, + else: true, + finally: true, + for: true, + in: true, + instanceof: true, + new: true, + return: true, + switch: true, + throw: true, + try: true, + typeof: true, + var: true, + void: true, + while: true, + with: true, + true: true, + false: true, + null: true, + this: true + }; + function ro() { return o; }; + + ok(o.if === 1, "o.if = " + o.if); + ok(ro().default === 2, "ro().default = " + ro().default); + ok(o.false === true, "o.false = " + o.false); + + next_test(); +} + var tests = [ test_date_now, test_indexOf, - test_isArray + test_isArray, + test_identifier_keywords ];