in rhino/src/main/java/org/mozilla/javascript/Parser.java [3761:3915]
private ObjectLiteral objectLiteral() throws IOException {
int pos = ts.tokenBeg, lineno = lineNumber(), column = columnNumber();
int afterComma = -1;
List<ObjectProperty> elems = new ArrayList<>();
Set<String> getterNames = null;
Set<String> setterNames = null;
if (this.inUseStrictDirective) {
getterNames = new HashSet<>();
setterNames = new HashSet<>();
}
Comment objJsdocNode = getAndResetJsDoc();
boolean objectLiteralDestructuringDefault = false;
commaLoop:
for (; ; ) {
String propertyName = null;
int entryKind = PROP_ENTRY;
int tt = peekToken();
Comment jsdocNode = getAndResetJsDoc();
if (tt == Token.COMMENT) {
consumeToken();
tt = peekUntilNonComment(tt);
}
if (tt == Token.RC) {
if (afterComma != -1) warnTrailingComma(pos, elems, afterComma);
break commaLoop;
}
AstNode pname = objliteralProperty();
if (pname == null) {
reportError("msg.bad.prop");
} else {
propertyName = ts.getString();
int ppos = ts.tokenBeg;
consumeToken();
if (pname instanceof Name || pname instanceof StringLiteral) {
// For complicated reasons, parsing a name does not advance the token
pname.setLineColumnNumber(lineNumber(), columnNumber());
} else if (pname instanceof GeneratorMethodDefinition) {
// Same as above
((GeneratorMethodDefinition) pname)
.getMethodName()
.setLineColumnNumber(lineNumber(), columnNumber());
}
// This code path needs to handle both destructuring object
// literals like:
// var {get, b} = {get: 1, b: 2};
// and getters like:
// var x = {get 1() { return 2; };
// So we check a whitelist of tokens to check if we're at the
// first case. (Because of keywords, the second case may be
// many tokens.)
int peeked = peekToken();
if (peeked != Token.COMMA && peeked != Token.COLON && peeked != Token.RC) {
if (peeked == Token.ASSIGN) { // we have an object literal with
// destructuring assignment and a default value
objectLiteralDestructuringDefault = true;
if (compilerEnv.getLanguageVersion() >= Context.VERSION_ES6) {
elems.add(plainProperty(pname, tt));
if (matchToken(Token.COMMA, true)) {
continue;
} else {
break commaLoop;
}
} else {
reportError("msg.default.args");
}
} else if (peeked == Token.LP) {
entryKind = METHOD_ENTRY;
} else if (pname.getType() == Token.NAME) {
if ("get".equals(propertyName)) {
entryKind = GET_ENTRY;
} else if ("set".equals(propertyName)) {
entryKind = SET_ENTRY;
}
}
if (entryKind == GET_ENTRY || entryKind == SET_ENTRY) {
pname = objliteralProperty();
if (pname == null) {
reportError("msg.bad.prop");
}
consumeToken();
}
if (pname == null) {
propertyName = null;
} else {
propertyName = ts.getString();
// short-hand method definition
ObjectProperty objectProp =
methodDefinition(
ppos,
pname,
entryKind,
pname instanceof GeneratorMethodDefinition);
pname.setJsDocNode(jsdocNode);
elems.add(objectProp);
}
} else {
pname.setJsDocNode(jsdocNode);
elems.add(plainProperty(pname, tt));
}
if (pname instanceof GeneratorMethodDefinition && entryKind != METHOD_ENTRY) {
reportError("msg.bad.prop");
}
}
if (this.inUseStrictDirective
&& propertyName != null
&& !(pname instanceof ComputedPropertyKey)) {
switch (entryKind) {
case PROP_ENTRY:
case METHOD_ENTRY:
if (getterNames.contains(propertyName)
|| setterNames.contains(propertyName)) {
addError("msg.dup.obj.lit.prop.strict", propertyName);
}
getterNames.add(propertyName);
setterNames.add(propertyName);
break;
case GET_ENTRY:
if (getterNames.contains(propertyName)) {
addError("msg.dup.obj.lit.prop.strict", propertyName);
}
getterNames.add(propertyName);
break;
case SET_ENTRY:
if (setterNames.contains(propertyName)) {
addError("msg.dup.obj.lit.prop.strict", propertyName);
}
setterNames.add(propertyName);
break;
}
}
// Eat any dangling jsdoc in the property.
getAndResetJsDoc();
if (matchToken(Token.COMMA, true)) {
afterComma = ts.tokenEnd;
} else {
break commaLoop;
}
}
mustMatchToken(Token.RC, "msg.no.brace.prop", true);
ObjectLiteral pn = new ObjectLiteral(pos, ts.tokenEnd - pos);
if (objectLiteralDestructuringDefault) {
pn.putIntProp(Node.OBJECT_LITERAL_DESTRUCTURING, 1);
}
if (objJsdocNode != null) {
pn.setJsDocNode(objJsdocNode);
}
pn.setElements(elems);
pn.setLineColumnNumber(lineno, column);
return pn;
}