Skip to content

Commit 57ab969

Browse files
Nick Santoshns
authored andcommitted
Update the rhino parser to handle ES5 object literal definitions:
1) Allow the use of keywords in key names 2) Allow quoted strings and number for getter and setter definitions. Committed by John Lenz ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=26337123 Conflicts: src/org/mozilla/javascript/CompilerEnvirons.java src/org/mozilla/javascript/Parser.java
1 parent 10bd92a commit 57ab969

File tree

5 files changed

+266
-78
lines changed

5 files changed

+266
-78
lines changed

src/org/mozilla/javascript/CompilerEnvirons.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public CompilerEnvirons()
5252
languageVersion = Context.VERSION_DEFAULT;
5353
generateDebugInfo = true;
5454
reservedKeywordAsIdentifier = true;
55+
allowKeywordAsObjectPropertyName = false;
5556
allowMemberExprAsFunctionName = false;
5657
xmlAvailable = true;
5758
optimizationLevel = 0;
@@ -65,11 +66,13 @@ public CompilerEnvirons()
6566
public void initFromContext(Context cx)
6667
{
6768
setErrorReporter(cx.getErrorReporter());
68-
this.languageVersion = cx.getLanguageVersion();
69+
languageVersion = cx.getLanguageVersion();
6970
generateDebugInfo = (!cx.isGeneratingDebugChanged()
7071
|| cx.isGeneratingDebug());
7172
reservedKeywordAsIdentifier
7273
= cx.hasFeature(Context.FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER);
74+
allowKeywordAsObjectPropertyName
75+
= (languageVersion >= Context.VERSION_1_8);
7376
allowMemberExprAsFunctionName
7477
= cx.hasFeature(Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME);
7578
strictMode
@@ -129,6 +132,14 @@ public void setReservedKeywordAsIdentifier(boolean flag)
129132
reservedKeywordAsIdentifier = flag;
130133
}
131134

135+
public boolean isAllowKeywordAsObjectPropertyName() {
136+
return allowKeywordAsObjectPropertyName;
137+
}
138+
139+
public void setAllowKeywordAsObjectPropertyName(boolean flag) {
140+
this.allowKeywordAsObjectPropertyName = flag;
141+
}
142+
132143
/**
133144
* Extension to ECMA: if 'function <name>' is not followed
134145
* by '(', assume <name> starts a {@code memberExpr}
@@ -295,23 +306,25 @@ public boolean getAllowSharpComments() {
295306
* The {@link ErrorReporter} is set to an {@link ErrorCollector}.
296307
*/
297308
public static CompilerEnvirons ideEnvirons() {
298-
CompilerEnvirons env = new CompilerEnvirons();
299-
env.setRecoverFromErrors(true);
300-
env.setRecordingComments(true);
301-
env.setStrictMode(true);
302-
env.setWarnTrailingComma(true);
303-
env.setLanguageVersion(170);
304-
env.setReservedKeywordAsIdentifier(true);
305-
env.setIdeMode(true);
306-
env.setErrorReporter(new ErrorCollector());
307-
return env;
309+
CompilerEnvirons env = new CompilerEnvirons();
310+
env.setRecoverFromErrors(true);
311+
env.setRecordingComments(true);
312+
env.setStrictMode(true);
313+
env.setWarnTrailingComma(true);
314+
env.setLanguageVersion(170);
315+
env.setReservedKeywordAsIdentifier(true);
316+
env.setAllowKeywordAsObjectPropertyName(true);
317+
env.setIdeMode(true);
318+
env.setErrorReporter(new ErrorCollector());
319+
return env;
308320
}
309321

310322
private ErrorReporter errorReporter;
311323

312324
private int languageVersion;
313325
private boolean generateDebugInfo;
314326
private boolean reservedKeywordAsIdentifier;
327+
private boolean allowKeywordAsObjectPropertyName;
315328
private boolean allowMemberExprAsFunctionName;
316329
private boolean xmlAvailable;
317330
private int optimizationLevel;

src/org/mozilla/javascript/Parser.java

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,7 +2597,13 @@ private AstNode propertyAccess(int tt, AstNode pn)
25972597
}
25982598

25992599
if (!compilerEnv.isXmlAvailable()) {
2600-
mustMatchToken(Token.NAME, "msg.no.name.after.dot");
2600+
int maybeName = nextToken();
2601+
if (maybeName != Token.NAME &&
2602+
!(compilerEnv.isAllowKeywordAsObjectPropertyName()
2603+
&& TokenStream.isKeyword(ts.getString()))) {
2604+
reportError("msg.no.name.after.dot");
2605+
}
2606+
26012607
Name name = createNameNode(true, Token.GETPROP);
26022608
PropertyGet pg = new PropertyGet(pn, name, dotPos);
26032609
pg.setLineno(lineno);
@@ -3178,59 +3184,49 @@ private ObjectLiteral objectLiteral()
31783184
Comment jsdocNode = getAndResetJsDoc();
31793185
switch(tt) {
31803186
case Token.NAME:
3181-
case Token.STRING:
3182-
saveNameTokenData(ts.tokenBeg, ts.getString(), ts.lineno);
3183-
consumeToken();
3184-
StringLiteral stringProp = null;
3185-
if (tt == Token.STRING) {
3186-
stringProp = createStringLiteral();
3187-
}
3187+
afterComma = -1;
31883188
Name name = createNameNode();
31893189
propertyName = ts.getString();
31903190
int ppos = ts.tokenBeg;
3191+
consumeToken();
31913192

3192-
if ((tt == Token.NAME
3193-
&& (peekToken() == Token.NAME || convertToName(peekToken()))
3194-
&& ("get".equals(propertyName) || "set".equals(propertyName))))
3193+
if ((peekToken() != Token.COLON
3194+
&& ("get".equals(propertyName)
3195+
|| "set".equals(propertyName))))
31953196
{
3196-
consumeToken();
3197-
name = createNameNode();
3198-
name.setJsDocNode(jsdocNode);
3199-
ObjectProperty objectProp = getterSetterProperty(ppos, name,
3200-
"get".equals(propertyName));
3201-
elems.add(objectProp);
3202-
propertyName = objectProp.getLeft().getString();
3197+
boolean isGet = "get".equals(propertyName);
3198+
AstNode pname = objliteralProperty();
3199+
if (pname == null) {
3200+
propertyName = null;
3201+
} else {
3202+
propertyName = ts.getString();
3203+
ObjectProperty objectProp = getterSetterProperty(
3204+
ppos, pname, isGet);
3205+
pname.setJsDocNode(jsdocNode);
3206+
elems.add(objectProp);
3207+
}
32033208
} else {
3204-
AstNode pname = stringProp != null ? stringProp : name;
3209+
AstNode pname = name;
32053210
pname.setJsDocNode(jsdocNode);
32063211
elems.add(plainProperty(pname, tt));
32073212
}
32083213
break;
32093214

3210-
case Token.NUMBER:
3211-
consumeToken();
3212-
AstNode nl = new NumberLiteral(ts.tokenBeg,
3213-
ts.getString(),
3214-
ts.getNumber());
3215-
nl.setJsDocNode(jsdocNode);
3216-
propertyName = ts.getString();
3217-
elems.add(plainProperty(nl, tt));
3218-
break;
3219-
32203215
case Token.RC:
32213216
if (afterComma != -1)
32223217
warnTrailingComma(pos, elems, afterComma);
32233218
break commaLoop;
32243219

32253220
default:
3226-
if (convertToName(tt)) {
3227-
consumeToken();
3228-
AstNode pname = createNameNode();
3229-
pname.setJsDocNode(jsdocNode);
3230-
elems.add(plainProperty(pname, tt));
3231-
break;
3221+
AstNode pname = objliteralProperty();
3222+
if (pname == null) {
3223+
propertyName = null;
3224+
} else {
3225+
afterComma = -1;
3226+
propertyName = ts.getString();
3227+
pname.setJsDocNode(jsdocNode);
3228+
elems.add(plainProperty(pname, tt));
32323229
}
3233-
reportError("msg.bad.prop");
32343230
break;
32353231
}
32363232

@@ -3262,6 +3258,38 @@ private ObjectLiteral objectLiteral()
32623258
return pn;
32633259
}
32643260

3261+
private AstNode objliteralProperty() throws IOException {
3262+
AstNode pname;
3263+
int tt = peekToken();
3264+
switch(tt) {
3265+
case Token.NAME:
3266+
pname = createNameNode();
3267+
break;
3268+
3269+
case Token.STRING:
3270+
pname = createStringLiteral();
3271+
break;
3272+
3273+
case Token.NUMBER:
3274+
pname = new NumberLiteral(
3275+
ts.tokenBeg, ts.getString(), ts.getNumber());
3276+
break;
3277+
3278+
default:
3279+
if (compilerEnv.isReservedKeywordAsIdentifier()
3280+
&& TokenStream.isKeyword(ts.getString())) {
3281+
// convert keyword to property name, e.g. ({if: 1})
3282+
pname = createNameNode();
3283+
break;
3284+
}
3285+
reportError("msg.bad.prop");
3286+
return null;
3287+
}
3288+
3289+
consumeToken();
3290+
return pname;
3291+
}
3292+
32653293
private ObjectProperty plainProperty(AstNode property, int ptt)
32663294
throws IOException
32673295
{

src/org/mozilla/javascript/TokenStream.java

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ private static int stringToKeyword(String name)
136136
Id_function = Token.FUNCTION,
137137
Id_if = Token.IF,
138138
Id_in = Token.IN,
139-
Id_let = Token.LET,
139+
Id_let = Token.LET, // reserved ES5 strict
140140
Id_new = Token.NEW,
141141
Id_null = Token.NULL,
142142
Id_return = Token.RETURN,
@@ -148,44 +148,44 @@ private static int stringToKeyword(String name)
148148
Id_void = Token.VOID,
149149
Id_while = Token.WHILE,
150150
Id_with = Token.WITH,
151-
Id_yield = Token.YIELD,
151+
Id_yield = Token.YIELD, // reserved ES5 strict
152152

153153
// the following are #ifdef RESERVE_JAVA_KEYWORDS in jsscan.c
154-
Id_abstract = Token.RESERVED,
155-
Id_boolean = Token.RESERVED,
156-
Id_byte = Token.RESERVED,
154+
Id_abstract = Token.RESERVED, // ES3 only
155+
Id_boolean = Token.RESERVED, // ES3 only
156+
Id_byte = Token.RESERVED, // ES3 only
157157
Id_catch = Token.CATCH,
158-
Id_char = Token.RESERVED,
159-
Id_class = Token.RESERVED,
160-
Id_const = Token.CONST,
158+
Id_char = Token.RESERVED, // ES3 only
159+
Id_class = Token.RESERVED,
160+
Id_const = Token.CONST, // reserved
161161
Id_debugger = Token.DEBUGGER,
162-
Id_double = Token.RESERVED,
162+
Id_double = Token.RESERVED, // ES3 only
163163
Id_enum = Token.RESERVED,
164164
Id_extends = Token.RESERVED,
165-
Id_final = Token.RESERVED,
165+
Id_final = Token.RESERVED, // ES3 only
166166
Id_finally = Token.FINALLY,
167-
Id_float = Token.RESERVED,
168-
Id_goto = Token.RESERVED,
169-
Id_implements = Token.RESERVED,
167+
Id_float = Token.RESERVED, // ES3 only
168+
Id_goto = Token.RESERVED, // ES3 only
169+
Id_implements = Token.RESERVED, // ES3, ES5 strict
170170
Id_import = Token.RESERVED,
171171
Id_instanceof = Token.INSTANCEOF,
172-
Id_int = Token.RESERVED,
173-
Id_interface = Token.RESERVED,
174-
Id_long = Token.RESERVED,
175-
Id_native = Token.RESERVED,
176-
Id_package = Token.RESERVED,
177-
Id_private = Token.RESERVED,
178-
Id_protected = Token.RESERVED,
179-
Id_public = Token.RESERVED,
180-
Id_short = Token.RESERVED,
181-
Id_static = Token.RESERVED,
172+
Id_int = Token.RESERVED, // ES3
173+
Id_interface = Token.RESERVED, // ES3, ES5 strict
174+
Id_long = Token.RESERVED, // ES3 only
175+
Id_native = Token.RESERVED, // ES3 only
176+
Id_package = Token.RESERVED, // ES3, ES5 strict
177+
Id_private = Token.RESERVED, // ES3, ES5 strict
178+
Id_protected = Token.RESERVED, // ES3, ES5 strict
179+
Id_public = Token.RESERVED, // ES3, ES5 strict
180+
Id_short = Token.RESERVED, // ES3 only
181+
Id_static = Token.RESERVED, // ES3, ES5 strict
182182
Id_super = Token.RESERVED,
183-
Id_synchronized = Token.RESERVED,
183+
Id_synchronized = Token.RESERVED, // ES3 only
184184
Id_throw = Token.THROW,
185-
Id_throws = Token.RESERVED,
186-
Id_transient = Token.RESERVED,
185+
Id_throws = Token.RESERVED, // ES3 only
186+
Id_transient = Token.RESERVED, // ES3 only
187187
Id_try = Token.TRY,
188-
Id_volatile = Token.RESERVED;
188+
Id_volatile = Token.RESERVED; // ES3 only
189189

190190
int id;
191191
String s = name;
@@ -426,6 +426,9 @@ final int getToken() throws IOException
426426
string = result == Token.LET ? "let" : "yield";
427427
result = Token.NAME;
428428
}
429+
// Save the string in case we need to use in
430+
// object literal definitions.
431+
this.string = (String)allStrings.intern(str);
429432
if (result != Token.RESERVED) {
430433
return result;
431434
} else if (!parser.compilerEnv.

testsrc/org/mozilla/javascript/testing/TestErrorReporter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
*
2020
* @author Pascal-Louis Perez
2121
*/
22-
public final class TestErrorReporter extends Assert implements ErrorReporter {
22+
public class TestErrorReporter extends Assert implements ErrorReporter {
2323
private final String[] errors;
2424
private final String[] warnings;
2525
private int errorsIndex = 0;

0 commit comments

Comments
 (0)