#include "config.h"
#include "LiteralParser.h"
+#include "ButterflyInlines.h"
+#include "CopiedSpaceInlines.h"
#include "JSArray.h"
#include "JSString.h"
#include "Lexer.h"
+#include "ObjectConstructor.h"
+#include "Operations.h"
#include "StrongInlines.h"
-#include "UStringBuilder.h"
#include <wtf/ASCIICType.h>
#include <wtf/dtoa.h>
+#include <wtf/text/StringBuilder.h>
namespace JSC {
do {
Vector<JSONPPathEntry> path;
// Unguarded next to start off the lexer
- Identifier name = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+ Identifier name = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
JSONPPathEntry entry;
- if (name == m_exec->globalData().propertyNames->varKeyword) {
+ if (name == m_exec->vm().propertyNames->varKeyword) {
if (m_lexer.next() != TokIdentifier)
return false;
entry.m_type = JSONPPathEntryTypeDeclare;
- entry.m_pathEntryName = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+ entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
path.append(entry);
} else {
entry.m_type = JSONPPathEntryTypeDot;
- entry.m_pathEntryName = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+ entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
path.append(entry);
}
- if (m_exec->globalData().keywords->isKeyword(entry.m_pathEntryName))
+ if (m_exec->vm().keywords->isKeyword(entry.m_pathEntryName))
return false;
TokenType tokenType = m_lexer.next();
+ if (entry.m_type == JSONPPathEntryTypeDeclare && tokenType != TokAssign)
+ return false;
while (tokenType != TokAssign) {
switch (tokenType) {
case TokLBracket: {
entry.m_type = JSONPPathEntryTypeDot;
if (m_lexer.next() != TokIdentifier)
return false;
- entry.m_pathEntryName = Identifier(&m_exec->globalData(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+ entry.m_pathEntryName = Identifier(&m_exec->vm(), m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
break;
}
case TokLParen: {
startJSON:
m_lexer.next();
results.append(JSONPData());
- results.last().m_value.set(m_exec->globalData(), parse(StartParseExpression));
+ results.last().m_value.set(m_exec->vm(), parse(StartParseExpression));
if (!results.last().m_value)
return false;
results.last().m_path.swap(path);
ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const LChar* characters, size_t length)
{
if (!length)
- return m_exec->globalData().propertyNames->emptyIdentifier;
+ return m_exec->vm().propertyNames->emptyIdentifier;
if (characters[0] >= MaximumCachableCharacter)
- return Identifier(&m_exec->globalData(), characters, length);
+ return Identifier(&m_exec->vm(), characters, length);
if (length == 1) {
if (!m_shortIdentifiers[characters[0]].isNull())
return m_shortIdentifiers[characters[0]];
- m_shortIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+ m_shortIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
return m_shortIdentifiers[characters[0]];
}
if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length))
return m_recentIdentifiers[characters[0]];
- m_recentIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+ m_recentIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
return m_recentIdentifiers[characters[0]];
}
ALWAYS_INLINE const Identifier LiteralParser<CharType>::makeIdentifier(const UChar* characters, size_t length)
{
if (!length)
- return m_exec->globalData().propertyNames->emptyIdentifier;
+ return m_exec->vm().propertyNames->emptyIdentifier;
if (characters[0] >= MaximumCachableCharacter)
- return Identifier(&m_exec->globalData(), characters, length);
+ return Identifier(&m_exec->vm(), characters, length);
if (length == 1) {
if (!m_shortIdentifiers[characters[0]].isNull())
return m_shortIdentifiers[characters[0]];
- m_shortIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+ m_shortIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
return m_shortIdentifiers[characters[0]];
}
if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length))
return m_recentIdentifiers[characters[0]];
- m_recentIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+ m_recentIdentifiers[characters[0]] = Identifier(&m_exec->vm(), characters, length);
return m_recentIdentifiers[characters[0]];
}
return lexIdentifier(token);
if (*m_ptr == '\'') {
if (mode == StrictJSON) {
- m_lexErrorMessage = "Single quotes (\') are not allowed in JSON";
+ m_lexErrorMessage = ASCIILiteral("Single quotes (\') are not allowed in JSON");
return TokError;
}
return lexString<mode, '\''>(token);
{
++m_ptr;
const CharType* runStart = m_ptr;
- UStringBuilder builder;
+ StringBuilder builder;
do {
runStart = m_ptr;
while (m_ptr < m_end && isSafeStringCharacter<mode, CharType, terminator>(*m_ptr))
builder.append(runStart, m_ptr - runStart);
++m_ptr;
if (m_ptr >= m_end) {
- m_lexErrorMessage = "Unterminated string";
+ m_lexErrorMessage = ASCIILiteral("Unterminated string");
return TokError;
}
switch (*m_ptr) {
case 'u':
if ((m_end - m_ptr) < 5) {
- m_lexErrorMessage = "\\u must be followed by 4 hex digits";
+ m_lexErrorMessage = ASCIILiteral("\\u must be followed by 4 hex digits");
return TokError;
} // uNNNN == 5 characters
for (int i = 1; i < 5; i++) {
if (!isASCIIHexDigit(m_ptr[i])) {
- m_lexErrorMessage = String::format("\"\\%s\" is not a valid unicode escape", UString(m_ptr, 5).ascii().data()).impl();
+ m_lexErrorMessage = String::format("\"\\%s\" is not a valid unicode escape", String(m_ptr, 5).ascii().data()).impl();
return TokError;
}
}
} while ((mode != NonStrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != terminator);
if (m_ptr >= m_end || *m_ptr != terminator) {
- m_lexErrorMessage = "Unterminated string";
+ m_lexErrorMessage = ASCIILiteral("Unterminated string");
return TokError;
}
if (builder.isEmpty()) {
- token.stringBuffer = UString();
+ token.stringBuffer = String();
setParserTokenString<CharType>(token, runStart);
token.stringLength = m_ptr - runStart;
} else {
- token.stringBuffer = builder.toUString();
+ token.stringBuffer = builder.toString();
if (token.stringBuffer.is8Bit()) {
token.stringIs8Bit = 1;
token.stringToken8 = token.stringBuffer.characters8();
while (m_ptr < m_end && isASCIIDigit(*m_ptr))
++m_ptr;
} else {
- m_lexErrorMessage = "Invalid number";
+ m_lexErrorMessage = ASCIILiteral("Invalid number");
return TokError;
}
++m_ptr;
// [0-9]+
if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
- m_lexErrorMessage = "Invalid digits after decimal point";
+ m_lexErrorMessage = ASCIILiteral("Invalid digits after decimal point");
return TokError;
}
// [0-9]+
if (m_ptr >= m_end || !isASCIIDigit(*m_ptr)) {
- m_lexErrorMessage = "Exponent symbols should be followed by an optional '+' or '-' and then by at least one number";
+ m_lexErrorMessage = ASCIILiteral("Exponent symbols should be followed by an optional '+' or '-' and then by at least one number");
return TokError;
}
ParserState state = initialState;
MarkedArgumentBuffer objectStack;
JSValue lastValue;
- Vector<ParserState, 16> stateStack;
- Vector<Identifier, 16> identifierStack;
+ Vector<ParserState, 16, UnsafeVectorOverflow> stateStack;
+ Vector<Identifier, 16, UnsafeVectorOverflow> identifierStack;
while (1) {
switch(state) {
startParseArray:
case StartParseArray: {
- JSArray* array = constructEmptyArray(m_exec);
+ JSArray* array = constructEmptyArray(m_exec, 0);
objectStack.append(array);
// fallthrough
}
TokenType lastToken = m_lexer.currentToken().type;
if (m_lexer.next() == TokRBracket) {
if (lastToken == TokComma) {
- m_parseErrorMessage = "Unexpected comma at the end of array expression";
+ m_parseErrorMessage = ASCIILiteral("Unexpected comma at the end of array expression");
return JSValue();
}
m_lexer.next();
goto startParseExpression;
}
case DoParseArrayEndExpression: {
- asArray(objectStack.last())->push(m_exec, lastValue);
+ JSArray* array = asArray(objectStack.last());
+ array->putDirectIndex(m_exec, array->length(), lastValue);
if (m_lexer.currentToken().type == TokComma)
goto doParseArrayStartExpression;
if (m_lexer.currentToken().type != TokRBracket) {
- m_parseErrorMessage = "Expected ']'";
+ m_parseErrorMessage = ASCIILiteral("Expected ']'");
return JSValue();
}
// Check for colon
if (m_lexer.next() != TokColon) {
- m_parseErrorMessage = "Expected ':' before value in object property definition";
+ m_parseErrorMessage = ASCIILiteral("Expected ':' before value in object property definition");
return JSValue();
}
goto startParseExpression;
}
if (type != TokRBrace) {
- m_parseErrorMessage = "Expected '}'";
+ m_parseErrorMessage = ASCIILiteral("Expected '}'");
return JSValue();
}
m_lexer.next();
case DoParseObjectStartExpression: {
TokenType type = m_lexer.next();
if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier)) {
- m_parseErrorMessage = "Property name must be a string literal";
+ m_parseErrorMessage = ASCIILiteral("Property name must be a string literal");
return JSValue();
}
LiteralParserToken<CharType> identifierToken = m_lexer.currentToken();
// Check for colon
if (m_lexer.next() != TokColon) {
- m_parseErrorMessage = "Expected ':'";
+ m_parseErrorMessage = ASCIILiteral("Expected ':'");
return JSValue();
}
}
case DoParseObjectEndExpression:
{
- asObject(objectStack.last())->putDirect(m_exec->globalData(), identifierStack.last(), lastValue);
+ JSObject* object = asObject(objectStack.last());
+ PropertyName ident = identifierStack.last();
+ unsigned i = ident.asIndex();
+ if (i != PropertyName::NotAnIndex)
+ object->putDirectIndex(m_exec, i, lastValue);
+ else
+ object->putDirect(m_exec->vm(), ident, lastValue);
identifierStack.removeLast();
if (m_lexer.currentToken().type == TokComma)
goto doParseObjectStartExpression;
if (m_lexer.currentToken().type != TokRBrace) {
- m_parseErrorMessage = "Expected '}'";
+ m_parseErrorMessage = ASCIILiteral("Expected '}'");
return JSValue();
}
m_lexer.next();
LiteralParserToken<CharType> stringToken = m_lexer.currentToken();
m_lexer.next();
if (stringToken.stringIs8Bit)
- lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken8, stringToken.stringLength).ustring());
+ lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken8, stringToken.stringLength).string());
else
- lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken16, stringToken.stringLength).ustring());
+ lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken16, stringToken.stringLength).string());
break;
}
case TokNumber: {
lastValue = jsBoolean(false);
break;
case TokRBracket:
- m_parseErrorMessage = "Unexpected token ']'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token ']'");
return JSValue();
case TokRBrace:
- m_parseErrorMessage = "Unexpected token '}'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token '}'");
return JSValue();
case TokIdentifier: {
const LiteralParserToken<CharType>& token = m_lexer.currentToken();
if (token.stringIs8Bit)
- m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken8, m_lexer.currentToken().stringLength).ascii().data()).impl();
+ m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", String(m_lexer.currentToken().stringToken8, m_lexer.currentToken().stringLength).ascii().data()).impl();
else
- m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", UString(m_lexer.currentToken().stringToken16, m_lexer.currentToken().stringLength).ascii().data()).impl();
+ m_parseErrorMessage = String::format("Unexpected identifier \"%s\"", String(m_lexer.currentToken().stringToken16, m_lexer.currentToken().stringLength).ascii().data()).impl();
return JSValue();
}
case TokColon:
- m_parseErrorMessage = "Unexpected token ':'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token ':'");
return JSValue();
case TokLParen:
- m_parseErrorMessage = "Unexpected token '('";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token '('");
return JSValue();
case TokRParen:
- m_parseErrorMessage = "Unexpected token ')'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token ')'");
return JSValue();
case TokComma:
- m_parseErrorMessage = "Unexpected token ','";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token ','");
return JSValue();
case TokDot:
- m_parseErrorMessage = "Unexpected token '.'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token '.'");
return JSValue();
case TokAssign:
- m_parseErrorMessage = "Unexpected token '='";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token '='");
return JSValue();
case TokSemi:
- m_parseErrorMessage = "Unexpected token ';'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token ';'");
return JSValue();
case TokEnd:
- m_parseErrorMessage = "Unexpected EOF";
+ m_parseErrorMessage = ASCIILiteral("Unexpected EOF");
return JSValue();
case TokError:
default:
// Error
- m_parseErrorMessage = "Could not parse value expression";
+ m_parseErrorMessage = ASCIILiteral("Could not parse value expression");
return JSValue();
}
break;
goto startParseExpression;
}
case TokRBracket:
- m_parseErrorMessage = "Unexpected token ']'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token ']'");
return JSValue();
case TokLBrace:
- m_parseErrorMessage = "Unexpected token '{'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token '{'");
return JSValue();
case TokRBrace:
- m_parseErrorMessage = "Unexpected token '}'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token '}'");
return JSValue();
case TokIdentifier:
- m_parseErrorMessage = "Unexpected identifier";
+ m_parseErrorMessage = ASCIILiteral("Unexpected identifier");
return JSValue();
case TokColon:
- m_parseErrorMessage = "Unexpected token ':'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token ':'");
return JSValue();
case TokRParen:
- m_parseErrorMessage = "Unexpected token ')'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token ')'");
return JSValue();
case TokComma:
- m_parseErrorMessage = "Unexpected token ','";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token ','");
return JSValue();
case TokTrue:
- m_parseErrorMessage = "Unexpected token 'true'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token 'true'");
return JSValue();
case TokFalse:
- m_parseErrorMessage = "Unexpected token 'false'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token 'false'");
return JSValue();
case TokNull:
- m_parseErrorMessage = "Unexpected token 'null'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token 'null'");
return JSValue();
case TokEnd:
- m_parseErrorMessage = "Unexpected EOF";
+ m_parseErrorMessage = ASCIILiteral("Unexpected EOF");
return JSValue();
case TokDot:
- m_parseErrorMessage = "Unexpected token '.'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token '.'");
return JSValue();
case TokAssign:
- m_parseErrorMessage = "Unexpected token '='";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token '='");
return JSValue();
case TokSemi:
- m_parseErrorMessage = "Unexpected token ';'";
+ m_parseErrorMessage = ASCIILiteral("Unexpected token ';'");
return JSValue();
case TokError:
default:
- m_parseErrorMessage = "Could not parse statement";
+ m_parseErrorMessage = ASCIILiteral("Could not parse statement");
return JSValue();
}
}
return JSValue();
if (m_lexer.next() == TokEnd)
return lastValue;
- m_parseErrorMessage = "Unexpected content at end of JSON literal";
+ m_parseErrorMessage = ASCIILiteral("Unexpected content at end of JSON literal");
return JSValue();
}
default:
- ASSERT_NOT_REACHED();
+ RELEASE_ASSERT_NOT_REACHED();
}
if (stateStack.isEmpty())
return lastValue;