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>
This commit is contained in:
Jacek Caban 2018-04-04 21:43:19 +02:00 committed by Alexandre Julliard
parent da943f2c08
commit 3263d51a1f
4 changed files with 112 additions and 9 deletions

View file

@ -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;
}

View file

@ -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); }

View file

@ -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();
}

View file

@ -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
];