Index: src/json-parser.h |
diff --git a/src/json-parser.h b/src/json-parser.h |
index 40116fa59ab9594c578d5467ac5330cf3509dd37..03ed22d70e52d38f0ac62dbf138171b12a495ea3 100644 |
--- a/src/json-parser.h |
+++ b/src/json-parser.h |
@@ -192,8 +192,10 @@ Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source, |
AdvanceSkipWhitespace(); |
Handle<Object> result = ParseJsonValue(); |
if (result.is_null() || c0_ != kEndOfString) { |
- // Parse failed. Current character is the unexpected token. |
+ // Some exception (for example stack overflow) is already pending. |
+ if (isolate_->has_pending_exception()) return Handle<Object>::null(); |
+ // Parse failed. Current character is the unexpected token. |
const char* message; |
Factory* factory = this->factory(); |
Handle<JSArray> array; |
@@ -244,6 +246,12 @@ Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source, |
// Parse any JSON value. |
template <bool seq_ascii> |
Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() { |
+ StackLimitCheck stack_check(isolate_); |
+ if (stack_check.HasOverflowed()) { |
+ isolate_->StackOverflow(); |
+ return Handle<Object>::null(); |
+ } |
+ |
if (c0_ == '"') return ParseJsonString(); |
if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber(); |
if (c0_ == '{') return ParseJsonObject(); |
@@ -293,45 +301,56 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() { |
Advance(); |
uint32_t index = 0; |
- while (c0_ >= '0' && c0_ <= '9') { |
- int d = c0_ - '0'; |
- if (index > 429496729U - ((d > 5) ? 1 : 0)) break; |
- index = (index * 10) + d; |
- Advance(); |
- } |
+ if (c0_ >= '0' && c0_ <= '9') { |
+ // Maybe an array index, try to parse it. |
+ if (c0_ == '0') { |
+ // With a leading zero, the string has to be "0" only to be an index. |
+ Advance(); |
+ } else { |
+ do { |
+ int d = c0_ - '0'; |
+ if (index > 429496729U - ((d > 5) ? 1 : 0)) break; |
+ index = (index * 10) + d; |
+ Advance(); |
+ } while (c0_ >= '0' && c0_ <= '9'); |
+ } |
- if (position_ != start_position + 1 && c0_ == '"') { |
- AdvanceSkipWhitespace(); |
+ if (c0_ == '"') { |
+ // Successfully parsed index, parse and store element. |
+ AdvanceSkipWhitespace(); |
- if (c0_ != ':') return ReportUnexpectedCharacter(); |
- AdvanceSkipWhitespace(); |
- Handle<Object> value = ParseJsonValue(); |
- if (value.is_null()) return ReportUnexpectedCharacter(); |
+ if (c0_ != ':') return ReportUnexpectedCharacter(); |
+ AdvanceSkipWhitespace(); |
+ Handle<Object> value = ParseJsonValue(); |
+ if (value.is_null()) return ReportUnexpectedCharacter(); |
- JSObject::SetOwnElement(json_object, index, value, kNonStrictMode); |
- } else { |
- position_ = start_position; |
+ JSObject::SetOwnElement(json_object, index, value, kNonStrictMode); |
+ continue; |
+ } |
+ // Not an index, fallback to the slow path. |
+ } |
+ |
+ position_ = start_position; |
#ifdef DEBUG |
- c0_ = '"'; |
+ c0_ = '"'; |
#endif |
- Handle<String> key = ParseJsonSymbol(); |
- if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter(); |
+ Handle<String> key = ParseJsonSymbol(); |
+ if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter(); |
- AdvanceSkipWhitespace(); |
- Handle<Object> value = ParseJsonValue(); |
- if (value.is_null()) return ReportUnexpectedCharacter(); |
+ AdvanceSkipWhitespace(); |
+ Handle<Object> value = ParseJsonValue(); |
+ if (value.is_null()) return ReportUnexpectedCharacter(); |
- if (key->Equals(isolate()->heap()->Proto_symbol())) { |
- prototype = value; |
+ if (key->Equals(isolate()->heap()->Proto_symbol())) { |
+ prototype = value; |
+ } else { |
+ if (JSObject::TryTransitionToField(json_object, key)) { |
+ int index = json_object->LastAddedFieldIndex(); |
+ json_object->FastPropertyAtPut(index, *value); |
} else { |
- if (JSObject::TryTransitionToField(json_object, key)) { |
- int index = json_object->LastAddedFieldIndex(); |
- json_object->FastPropertyAtPut(index, *value); |
- } else { |
- JSObject::SetLocalPropertyIgnoreAttributes( |
- json_object, key, value, NONE); |
- } |
+ JSObject::SetLocalPropertyIgnoreAttributes( |
+ json_object, key, value, NONE); |
} |
} |
} while (MatchSkipWhiteSpace(',')); |