-- v3: jscript: Allow ES5 keywords as identifiers in expressions. jscript: Allow ES5 keywords as identifiers in labelled statements. jscript: Allow ES5 keywords as identifiers in function parameter lists. jscript: Allow ES5 keywords as identifiers in function expressions. jscript: Allow ES5 keywords as identifiers in catch statements. jscript: Allow ES5 keywords as identifiers in variable declarations.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/parser.y | 23 +++++++++++++++-------- dlls/mshtml/tests/es5.js | 7 +++++-- 2 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 42d695e0846..d557588a5c5 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -221,7 +221,7 @@ static expression_t *new_prop_and_value_expression(parser_ctx_t*,property_list_t %type <expr> MemberExpression %type <expr> PrimaryExpression %type <expr> GetterSetterMethod -%type <identifier> Identifier_opt +%type <identifier> Identifier Identifier_opt %type <variable_list> VariableDeclarationList %type <variable_list> VariableDeclarationListNoIn %type <variable_declaration> VariableDeclaration @@ -241,7 +241,7 @@ static expression_t *new_prop_and_value_expression(parser_ctx_t*,property_list_t %type <literal> PropertyName %type <literal> BooleanLiteral %type <ival> AssignOper -%type <identifier> IdentifierName ReservedAsIdentifier +%type <identifier> IdentifierName ReservedAsIdentifier ES5Keyword
%nonassoc LOWER_THAN_ELSE %nonassoc kELSE @@ -381,12 +381,12 @@ VariableDeclarationListNoIn
/* ECMA-262 3rd Edition 12.2 */ VariableDeclaration - : tIdentifier Initialiser_opt + : Identifier Initialiser_opt { $$ = new_variable_declaration(ctx, $1, $2); }
/* ECMA-262 3rd Edition 12.2 */ VariableDeclarationNoIn - : tIdentifier InitialiserNoIn_opt + : Identifier InitialiserNoIn_opt { $$ = new_variable_declaration(ctx, $1, $2); }
/* ECMA-262 3rd Edition 12.2 */ @@ -860,7 +860,11 @@ PropertyName /* ECMA-262 3rd Edition 7.6 */ Identifier_opt : /* empty*/ { $$ = NULL; } - | tIdentifier { $$ = $1; } + | Identifier { $$ = $1; } + +Identifier + : tIdentifier { $$ = $1; } + | ES5Keyword { $$ = $1; }
/* ECMA-262 5.1 Edition 7.6 */ IdentifierName @@ -890,15 +894,12 @@ ReservedAsIdentifier | kFINALLY { $$ = $1; } | kFOR { $$ = $1; } | kFUNCTION { $$ = $1; } - | kGET { $$ = $1; } | kIF { $$ = $1; } | kIN { $$ = $1; } | kINSTANCEOF { $$ = $1; } - | kLET { $$ = $1; } | kNEW { $$ = $1; } | kNULL { $$ = $1; } | kRETURN { $$ = $1; } - | kSET { $$ = $1; } | kSWITCH { $$ = $1; } | kTHIS { $$ = $1; } | kTHROW { $$ = $1; } @@ -909,6 +910,12 @@ ReservedAsIdentifier | kVOID { $$ = $1; } | kWHILE { $$ = $1; } | kWITH { $$ = $1; } + | ES5Keyword { $$ = $1; } + +ES5Keyword + : kGET { $$ = $1; } + | kLET { $$ = $1; } + | kSET { $$ = $1; }
/* ECMA-262 3rd Edition 7.8 */ Literal diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 18b106e2a82..70003761133 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -473,6 +473,8 @@ sync_test("array_sort", function() { });
sync_test("identifier_keywords", function() { + { get /* asdf */: 10 } + var set = 1234; var o = { if: 1, default: 2, @@ -486,8 +488,8 @@ sync_test("identifier_keywords", function() { else: true, finally: true, for: true, - in: true, - instanceof: true, + set in(x) { }, + get instanceof() { return 3; }, new: true, return: true, switch: true, @@ -508,6 +510,7 @@ sync_test("identifier_keywords", function() { ok(o.if === 1, "o.if = " + o.if); ok(ro().default === 2, "ro().default = " + ro().default); ok(o.false === true, "o.false = " + o.false); + ok(o.instanceof === 3, "o.instanceof = " + o.instanceof); });
function test_own_data_prop_desc(obj, prop, expected_writable, expected_enumerable,
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/parser.y | 2 +- dlls/mshtml/tests/es5.js | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index d557588a5c5..4a4955f1b18 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -527,7 +527,7 @@ TryStatement
/* ECMA-262 3rd Edition 12.14 */ Catch - : kCATCH left_bracket tIdentifier right_bracket Block + : kCATCH left_bracket Identifier right_bracket Block { $$ = new_catch_block(ctx, $3, $5); }
/* ECMA-262 3rd Edition 12.14 */ diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 70003761133..4c1df40e226 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -511,6 +511,15 @@ sync_test("identifier_keywords", function() { ok(ro().default === 2, "ro().default = " + ro().default); ok(o.false === true, "o.false = " + o.false); ok(o.instanceof === 3, "o.instanceof = " + o.instanceof); + + var tmp = false; + try { + eval('function var() { }'); + } + catch(set) { + tmp = true; + } + ok(tmp === true, "Expected exception for 'function var() { }'"); });
function test_own_data_prop_desc(obj, prop, expected_writable, expected_enumerable,
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/parser.y | 4 ++-- dlls/mshtml/tests/es5.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 4a4955f1b18..8cf25b795a8 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -268,9 +268,9 @@ FunctionStatementList FunctionExpression : kFUNCTION left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' { $$ = new_function_expression(ctx, NULL, $3, $6, NULL, ctx->begin + @1, @7 - @1 + 1); } - | kFUNCTION tIdentifier left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' + | kFUNCTION Identifier left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' { $$ = new_function_expression(ctx, $2, $4, $7, NULL, ctx->begin + @1, @8 - @1 + 1); } - | kFUNCTION tIdentifier kDCOL tIdentifier left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' + | kFUNCTION Identifier kDCOL Identifier left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' { $$ = new_function_expression(ctx, $4, $6, $9, $2, ctx->begin + @1, @10 - @1 + 1); }
/* ECMA-262 10th Edition 14.1 */ diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 4c1df40e226..2e07e9b8595 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -473,6 +473,7 @@ sync_test("array_sort", function() { });
sync_test("identifier_keywords", function() { + function get() { } { get /* asdf */: 10 } var set = 1234; var o = {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/parser.y | 4 ++-- dlls/mshtml/tests/es5.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 8cf25b795a8..0288577ed29 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -279,8 +279,8 @@ FunctionBody
/* ECMA-262 3rd Edition 13 */ FormalParameterList - : tIdentifier { $$ = new_parameter_list(ctx, $1); } - | FormalParameterList ',' tIdentifier + : Identifier { $$ = new_parameter_list(ctx, $1); } + | FormalParameterList ',' Identifier { $$ = parameter_list_add(ctx, $1, $3); }
/* ECMA-262 3rd Edition 13 */ diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 2e07e9b8595..d2ab19e309e 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -473,7 +473,7 @@ sync_test("array_sort", function() { });
sync_test("identifier_keywords", function() { - function get() { } + function get(let, set) { } { get /* asdf */: 10 } var set = 1234; var o = {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Also required for primary expression tests in next patch. --- dlls/jscript/parser.y | 14 +++++++++++++- dlls/mshtml/tests/es5.js | 5 +++++ 2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 0288577ed29..5f00dbcd1a2 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -244,7 +244,8 @@ static expression_t *new_prop_and_value_expression(parser_ctx_t*,property_list_t %type <identifier> IdentifierName ReservedAsIdentifier ES5Keyword
%nonassoc LOWER_THAN_ELSE -%nonassoc kELSE +%nonassoc kELSE kIN kINSTANCEOF ':' +%nonassoc kGET kLET kSET
%%
@@ -480,6 +481,17 @@ LabelledStatement : tIdentifier ':' Statement { $$ = new_labelled_statement(ctx, @$, $1, $3); }
+ /* We have to lay out the keywords explicitly instead of using Identifier, as otherwise bison's parser + * wouldn't be able to figure out whether to reduce the Identifier or shift the colon (following the + * label and thus treating it as a label). This happens because the parser has only one lookahead token + * that can be used to decide a shift/reduce and would introduce a conflict in this case... */ + | kGET ':' Statement + { $$ = new_labelled_statement(ctx, @$, $1, $3); } + | kSET ':' Statement + { $$ = new_labelled_statement(ctx, @$, $1, $3); } + | kLET ':' Statement + { $$ = new_labelled_statement(ctx, @$, $1, $3); } + /* ECMA-262 3rd Edition 12.11 */ SwitchStatement : kSWITCH left_bracket Expression right_bracket CaseBlock diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index d2ab19e309e..110a1c583fd 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -475,6 +475,11 @@ sync_test("array_sort", function() { sync_test("identifier_keywords", function() { function get(let, set) { } { get /* asdf */: 10 } + let /* block label */ : { + break let; + ok(false, "did not break out of 'let' labelled block statement"); + } + set: var let; var set = 1234; var o = { if: 1,
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/parser.y | 4 ++++ dlls/mshtml/tests/es5.js | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 5f00dbcd1a2..6618dc9add5 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -798,7 +798,11 @@ ArgumentList /* ECMA-262 3rd Edition 11.1 */ PrimaryExpression : kTHIS { $$ = new_expression(ctx, EXPR_THIS, 0); } + /* We have to lay out the keywords explicitly instead of using Identifier, see LabelledStatement. */ | tIdentifier { $$ = new_identifier_expression(ctx, $1); } + | kGET { $$ = new_identifier_expression(ctx, $1); } + | kSET { $$ = new_identifier_expression(ctx, $1); } + | kLET { $$ = new_identifier_expression(ctx, $1); } | Literal { $$ = new_literal_expression(ctx, $1); } | ArrayLiteral { $$ = $1; } | ObjectLiteral { $$ = $1; } diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 110a1c583fd..3adb7cc1d61 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -473,15 +473,18 @@ sync_test("array_sort", function() { });
sync_test("identifier_keywords", function() { - function get(let, set) { } + function get(let, set) { { get instanceof (Object); } return let + set; } { get /* asdf */: 10 } let /* block label */ : { break let; ok(false, "did not break out of 'let' labelled block statement"); } - set: var let; + set: var let = get(1, 2); var set = 1234; var o = { + get: get, + set: set, + let /* comment */ : let, if: 1, default: 2, function: 3, @@ -516,7 +519,12 @@ sync_test("identifier_keywords", function() { ok(o.if === 1, "o.if = " + o.if); ok(ro().default === 2, "ro().default = " + ro().default); ok(o.false === true, "o.false = " + o.false); + ok(o.get === get, "o.get = " + o.get); + ok(o.set === set, "o.set = " + o.set); + ok(o.let === let, "o.let = " + o.let); ok(o.instanceof === 3, "o.instanceof = " + o.instanceof); + ok(let === 3, "let = " + let); + ok(set === 1234, "set = " + set);
var tmp = false; try {
While adding more tests (in particular the labelled block statement), I had to also duplicate the primary expression rules the same way to have it work properly (it's also from the same underlying "Statement" rule).