Index: src/json-parser.cc |
diff --git a/src/json-parser.h b/src/json-parser.cc |
similarity index 73% |
copy from src/json-parser.h |
copy to src/json-parser.cc |
index 1b9829fa40ba39774656836ad1c8941b36ab3be3..fc8b17943b8aa03f458b5ee82dc335552c8a96fb 100644 |
--- a/src/json-parser.h |
+++ b/src/json-parser.cc |
@@ -1,16 +1,16 @@ |
-// Copyright 2011 the V8 project authors. All rights reserved. |
+// Copyright 2016 the V8 project authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#ifndef V8_JSON_PARSER_H_ |
-#define V8_JSON_PARSER_H_ |
+#include "src/json-parser.h" |
-#include "src/char-predicates.h" |
+#include "src/char-predicates-inl.h" |
#include "src/conversions.h" |
#include "src/debug/debug.h" |
#include "src/factory.h" |
#include "src/field-type.h" |
#include "src/messages.h" |
+#include "src/objects-inl.h" |
#include "src/parsing/scanner.h" |
#include "src/parsing/token.h" |
#include "src/transitions.h" |
@@ -18,195 +18,24 @@ |
namespace v8 { |
namespace internal { |
-enum ParseElementResult { kElementFound, kElementNotFound, kNullHandle }; |
- |
- |
-// A simple json parser. |
template <bool seq_one_byte> |
-class JsonParser BASE_EMBEDDED { |
- public: |
- MUST_USE_RESULT static MaybeHandle<Object> Parse(Handle<String> source) { |
- return JsonParser(source).ParseJson(); |
- } |
- |
- static const int kEndOfString = -1; |
- |
- private: |
- explicit JsonParser(Handle<String> source) |
- : source_(source), |
- source_length_(source->length()), |
- isolate_(source->map()->GetHeap()->isolate()), |
- factory_(isolate_->factory()), |
- zone_(isolate_->allocator()), |
- object_constructor_(isolate_->native_context()->object_function(), |
- isolate_), |
- position_(-1) { |
- source_ = String::Flatten(source_); |
- pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED; |
- |
- // Optimized fast case where we only have Latin1 characters. |
- if (seq_one_byte) { |
- seq_source_ = Handle<SeqOneByteString>::cast(source_); |
- } |
- } |
- |
- // Parse a string containing a single JSON value. |
- MaybeHandle<Object> ParseJson(); |
- |
- inline void Advance() { |
- position_++; |
- if (position_ >= source_length_) { |
- c0_ = kEndOfString; |
- } else if (seq_one_byte) { |
- c0_ = seq_source_->SeqOneByteStringGet(position_); |
- } else { |
- c0_ = source_->Get(position_); |
- } |
- } |
- |
- // The JSON lexical grammar is specified in the ECMAScript 5 standard, |
- // section 15.12.1.1. The only allowed whitespace characters between tokens |
- // are tab, carriage-return, newline and space. |
- |
- inline void AdvanceSkipWhitespace() { |
- do { |
- Advance(); |
- } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r'); |
- } |
- |
- inline void SkipWhitespace() { |
- while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') { |
- Advance(); |
- } |
- } |
- |
- inline uc32 AdvanceGetChar() { |
- Advance(); |
- return c0_; |
- } |
- |
- // Checks that current charater is c. |
- // If so, then consume c and skip whitespace. |
- inline bool MatchSkipWhiteSpace(uc32 c) { |
- if (c0_ == c) { |
- AdvanceSkipWhitespace(); |
- return true; |
- } |
- return false; |
- } |
- |
- // A JSON string (production JSONString) is subset of valid JavaScript string |
- // literals. The string must only be double-quoted (not single-quoted), and |
- // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and |
- // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid. |
- Handle<String> ParseJsonString() { |
- return ScanJsonString<false>(); |
- } |
- |
- bool ParseJsonString(Handle<String> expected) { |
- int length = expected->length(); |
- if (source_->length() - position_ - 1 > length) { |
- DisallowHeapAllocation no_gc; |
- String::FlatContent content = expected->GetFlatContent(); |
- if (content.IsOneByte()) { |
- DCHECK_EQ('"', c0_); |
- const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1; |
- const uint8_t* expected_chars = content.ToOneByteVector().start(); |
- for (int i = 0; i < length; i++) { |
- uint8_t c0 = input_chars[i]; |
- if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') { |
- return false; |
- } |
- } |
- if (input_chars[length] == '"') { |
- position_ = position_ + length + 1; |
- AdvanceSkipWhitespace(); |
- return true; |
- } |
- } |
- } |
- return false; |
- } |
- |
- Handle<String> ParseJsonInternalizedString() { |
- Handle<String> result = ScanJsonString<true>(); |
- if (result.is_null()) return result; |
- return factory()->InternalizeString(result); |
- } |
- |
- template <bool is_internalized> |
- Handle<String> ScanJsonString(); |
- // Creates a new string and copies prefix[start..end] into the beginning |
- // of it. Then scans the rest of the string, adding characters after the |
- // prefix. Called by ScanJsonString when reaching a '\' or non-Latin1 char. |
- template <typename StringType, typename SinkChar> |
- Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end); |
- |
- // A JSON number (production JSONNumber) is a subset of the valid JavaScript |
- // decimal number literals. |
- // It includes an optional minus sign, must have at least one |
- // digit before and after a decimal point, may not have prefixed zeros (unless |
- // the integer part is zero), and may include an exponent part (e.g., "e-10"). |
- // Hexadecimal and octal numbers are not allowed. |
- Handle<Object> ParseJsonNumber(); |
- |
- // Parse a single JSON value from input (grammar production JSONValue). |
- // A JSON value is either a (double-quoted) string literal, a number literal, |
- // one of "true", "false", or "null", or an object or array literal. |
- Handle<Object> ParseJsonValue(); |
- |
- // Parse a JSON object literal (grammar production JSONObject). |
- // An object literal is a squiggly-braced and comma separated sequence |
- // (possibly empty) of key/value pairs, where the key is a JSON string |
- // literal, the value is a JSON value, and the two are separated by a colon. |
- // A JSON array doesn't allow numbers and identifiers as keys, like a |
- // JavaScript array. |
- Handle<Object> ParseJsonObject(); |
- |
- // Helper for ParseJsonObject. Parses the form "123": obj, which is recorded |
- // as an element, not a property. |
- ParseElementResult ParseElement(Handle<JSObject> json_object); |
- |
- // Parses a JSON array literal (grammar production JSONArray). An array |
- // literal is a square-bracketed and comma separated sequence (possibly empty) |
- // of JSON values. |
- // A JSON array doesn't allow leaving out values from the sequence, nor does |
- // it allow a terminal comma, like a JavaScript array does. |
- Handle<Object> ParseJsonArray(); |
- |
- |
- // Mark that a parsing error has happened at the current token, and |
- // return a null handle. Primarily for readability. |
- inline Handle<Object> ReportUnexpectedCharacter() { |
- return Handle<Object>::null(); |
+JsonParser<seq_one_byte>::JsonParser(Handle<String> source) |
+ : source_(source), |
+ source_length_(source->length()), |
+ isolate_(source->map()->GetHeap()->isolate()), |
+ factory_(isolate_->factory()), |
+ zone_(isolate_->allocator()), |
+ object_constructor_(isolate_->native_context()->object_function(), |
+ isolate_), |
+ position_(-1) { |
+ source_ = String::Flatten(source_); |
+ pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED; |
+ |
+ // Optimized fast case where we only have Latin1 characters. |
+ if (seq_one_byte) { |
+ seq_source_ = Handle<SeqOneByteString>::cast(source_); |
} |
- |
- inline Isolate* isolate() { return isolate_; } |
- inline Factory* factory() { return factory_; } |
- inline Handle<JSFunction> object_constructor() { return object_constructor_; } |
- |
- static const int kInitialSpecialStringLength = 32; |
- static const int kPretenureTreshold = 100 * 1024; |
- |
- |
- private: |
- Zone* zone() { return &zone_; } |
- |
- void CommitStateToJsonObject(Handle<JSObject> json_object, Handle<Map> map, |
- ZoneList<Handle<Object> >* properties); |
- |
- Handle<String> source_; |
- int source_length_; |
- Handle<SeqOneByteString> seq_source_; |
- |
- PretenureFlag pretenure_; |
- Isolate* isolate_; |
- Factory* factory_; |
- Zone zone_; |
- Handle<JSFunction> object_constructor_; |
- uc32 c0_; |
- int position_; |
-}; |
+} |
template <bool seq_one_byte> |
MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() { |
@@ -261,6 +90,72 @@ MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() { |
return result; |
} |
+template <bool seq_one_byte> |
+void JsonParser<seq_one_byte>::Advance() { |
+ position_++; |
+ if (position_ >= source_length_) { |
+ c0_ = kEndOfString; |
+ } else if (seq_one_byte) { |
+ c0_ = seq_source_->SeqOneByteStringGet(position_); |
+ } else { |
+ c0_ = source_->Get(position_); |
+ } |
+} |
+ |
+template <bool seq_one_byte> |
+void JsonParser<seq_one_byte>::AdvanceSkipWhitespace() { |
+ do { |
+ Advance(); |
+ } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r'); |
+} |
+ |
+template <bool seq_one_byte> |
+void JsonParser<seq_one_byte>::SkipWhitespace() { |
+ while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') { |
+ Advance(); |
+ } |
+} |
+ |
+template <bool seq_one_byte> |
+uc32 JsonParser<seq_one_byte>::AdvanceGetChar() { |
+ Advance(); |
+ return c0_; |
+} |
+ |
+template <bool seq_one_byte> |
+bool JsonParser<seq_one_byte>::MatchSkipWhiteSpace(uc32 c) { |
+ if (c0_ == c) { |
+ AdvanceSkipWhitespace(); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+template <bool seq_one_byte> |
+bool JsonParser<seq_one_byte>::ParseJsonString(Handle<String> expected) { |
+ int length = expected->length(); |
+ if (source_->length() - position_ - 1 > length) { |
+ DisallowHeapAllocation no_gc; |
+ String::FlatContent content = expected->GetFlatContent(); |
+ if (content.IsOneByte()) { |
+ DCHECK_EQ('"', c0_); |
+ const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1; |
+ const uint8_t* expected_chars = content.ToOneByteVector().start(); |
+ for (int i = 0; i < length; i++) { |
+ uint8_t c0 = input_chars[i]; |
+ if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') { |
+ return false; |
+ } |
+ } |
+ if (input_chars[length] == '"') { |
+ position_ = position_ + length + 1; |
+ AdvanceSkipWhitespace(); |
+ return true; |
+ } |
+ } |
+ } |
+ return false; |
+} |
// Parse any JSON value. |
template <bool seq_one_byte> |
@@ -308,7 +203,6 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() { |
return ReportUnexpectedCharacter(); |
} |
- |
template <bool seq_one_byte> |
ParseElementResult JsonParser<seq_one_byte>::ParseElement( |
Handle<JSObject> json_object) { |
@@ -481,7 +375,8 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() { |
if (value.is_null()) return ReportUnexpectedCharacter(); |
JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, |
- value).Check(); |
+ value) |
+ .Check(); |
} |
} |
@@ -493,7 +388,6 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() { |
return scope.CloseAndEscape(json_object); |
} |
- |
template <bool seq_one_byte> |
void JsonParser<seq_one_byte>::CommitStateToJsonObject( |
Handle<JSObject> json_object, Handle<Map> map, |
@@ -510,7 +404,6 @@ void JsonParser<seq_one_byte>::CommitStateToJsonObject( |
} |
} |
- |
// Parse a JSON array. Position must be right at '['. |
template <bool seq_one_byte> |
Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() { |
@@ -541,7 +434,6 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() { |
return scope.CloseAndEscape(json_array); |
} |
- |
template <bool seq_one_byte> |
Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() { |
bool negative = false; |
@@ -587,7 +479,7 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() { |
int length = position_ - beg_pos; |
double number; |
if (seq_one_byte) { |
- Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length); |
+ Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length); |
number = StringToDouble(isolate()->unicode_cache(), chars, |
NO_FLAGS, // Hex, octal or trailing junk. |
std::numeric_limits<double>::quiet_NaN()); |
@@ -596,8 +488,7 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() { |
String::WriteToFlat(*source_, buffer.start(), beg_pos, position_); |
Vector<const uint8_t> result = |
Vector<const uint8_t>(buffer.start(), length); |
- number = StringToDouble(isolate()->unicode_cache(), |
- result, |
+ number = StringToDouble(isolate()->unicode_cache(), result, |
NO_FLAGS, // Hex, octal or trailing junk. |
0.0); |
buffer.Dispose(); |
@@ -606,7 +497,6 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() { |
return factory()->NewNumber(number, pretenure_); |
} |
- |
template <typename StringType> |
inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c); |
@@ -621,25 +511,21 @@ inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) { |
} |
template <typename StringType> |
-inline Handle<StringType> NewRawString(Factory* factory, |
- int length, |
+inline Handle<StringType> NewRawString(Factory* factory, int length, |
PretenureFlag pretenure); |
template <> |
-inline Handle<SeqTwoByteString> NewRawString(Factory* factory, |
- int length, |
+inline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length, |
PretenureFlag pretenure) { |
return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked(); |
} |
template <> |
-inline Handle<SeqOneByteString> NewRawString(Factory* factory, |
- int length, |
- PretenureFlag pretenure) { |
+inline Handle<SeqOneByteString> NewRawString(Factory* factory, int length, |
+ PretenureFlag pretenure) { |
return factory->NewRawOneByteString(length, pretenure).ToHandleChecked(); |
} |
- |
// Scans the rest of a JSON string starting from position_ and writes |
// prefix[start..end] along with the scanned characters into a |
// sequential string of type StringType. |
@@ -718,8 +604,7 @@ Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString( |
// char. |
position_ -= 6; // Rewind position_ to \ in \uxxxx. |
Advance(); |
- return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, |
- 0, |
+ return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, |
count); |
} |
} |
@@ -738,7 +623,6 @@ Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString( |
return SeqString::Truncate(seq_string, count); |
} |
- |
template <bool seq_one_byte> |
template <bool is_internalized> |
Handle<String> JsonParser<seq_one_byte>::ScanJsonString() { |
@@ -761,8 +645,7 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() { |
c0_ = c0; |
int beg_pos = position_; |
position_ = position; |
- return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, |
- beg_pos, |
+ return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos, |
position_); |
} |
if (c0 < 0x20) return Handle<String>::null(); |
@@ -776,8 +659,8 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() { |
uint32_t hash = (length <= String::kMaxHashCalcLength) |
? StringHasher::GetHashCore(running_hash) |
: static_cast<uint32_t>(length); |
- Vector<const uint8_t> string_vector( |
- seq_source_->GetChars() + position_, length); |
+ Vector<const uint8_t> string_vector(seq_source_->GetChars() + position_, |
+ length); |
StringTable* string_table = isolate()->heap()->string_table(); |
uint32_t capacity = string_table->Capacity(); |
uint32_t entry = StringTable::FirstProbe(hash, capacity); |
@@ -787,8 +670,8 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() { |
Object* element = string_table->KeyAt(entry); |
if (element == isolate()->heap()->undefined_value()) { |
// Lookup failure. |
- result = factory()->InternalizeOneByteString( |
- seq_source_, position_, length); |
+ result = |
+ factory()->InternalizeOneByteString(seq_source_, position_, length); |
break; |
} |
if (element != isolate()->heap()->the_hole_value() && |
@@ -819,13 +702,11 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() { |
if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) { |
Advance(); |
} else { |
- return SlowScanJsonString<SeqTwoByteString, uc16>(source_, |
- beg_pos, |
+ return SlowScanJsonString<SeqTwoByteString, uc16>(source_, beg_pos, |
position_); |
} |
} else { |
- return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, |
- beg_pos, |
+ return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos, |
position_); |
} |
} while (c0_ != '"'); |
@@ -841,7 +722,9 @@ Handle<String> JsonParser<seq_one_byte>::ScanJsonString() { |
return result; |
} |
+// Explicit instantiation. |
+template class JsonParser<true>; |
+template class JsonParser<false>; |
+ |
} // namespace internal |
} // namespace v8 |
- |
-#endif // V8_JSON_PARSER_H_ |