blob: ddc3b736e3624aa556c46798bb13e49842ff87be [file] [log] [blame]
danno@chromium.org40cb8782011-05-25 07:58:50 +00001// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_JSON_PARSER_H_
29#define V8_JSON_PARSER_H_
30
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000031#include "v8.h"
32
33#include "char-predicates-inl.h"
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +000034#include "v8conversions.h"
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000035#include "messages.h"
36#include "spaces-inl.h"
danno@chromium.org40cb8782011-05-25 07:58:50 +000037#include "token.h"
38
39namespace v8 {
40namespace internal {
41
42// A simple json parser.
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000043template <bool seq_ascii>
danno@chromium.org40cb8782011-05-25 07:58:50 +000044class JsonParser BASE_EMBEDDED {
45 public:
mmassi@chromium.org7028c052012-06-13 11:51:58 +000046 static Handle<Object> Parse(Handle<String> source, Zone* zone) {
47 return JsonParser().ParseJson(source, zone);
danno@chromium.org40cb8782011-05-25 07:58:50 +000048 }
49
50 static const int kEndOfString = -1;
51
52 private:
53 // Parse a string containing a single JSON value.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000054 Handle<Object> ParseJson(Handle<String> source, Zone* zone);
danno@chromium.org40cb8782011-05-25 07:58:50 +000055
56 inline void Advance() {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +000057 position_++;
vegorov@chromium.org3cf47312011-06-29 13:20:01 +000058 if (position_ >= source_length_) {
danno@chromium.org40cb8782011-05-25 07:58:50 +000059 c0_ = kEndOfString;
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000060 } else if (seq_ascii) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +000061 c0_ = seq_source_->SeqOneByteStringGet(position_);
danno@chromium.org40cb8782011-05-25 07:58:50 +000062 } else {
danno@chromium.org40cb8782011-05-25 07:58:50 +000063 c0_ = source_->Get(position_);
64 }
65 }
66
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +000067 // The JSON lexical grammar is specified in the ECMAScript 5 standard,
68 // section 15.12.1.1. The only allowed whitespace characters between tokens
69 // are tab, carriage-return, newline and space.
danno@chromium.org40cb8782011-05-25 07:58:50 +000070
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +000071 inline void AdvanceSkipWhitespace() {
72 do {
73 Advance();
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000074 } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +000075 }
danno@chromium.org40cb8782011-05-25 07:58:50 +000076
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +000077 inline void SkipWhitespace() {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000078 while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +000079 Advance();
80 }
81 }
82
83 inline uc32 AdvanceGetChar() {
84 Advance();
85 return c0_;
86 }
87
88 // Checks that current charater is c.
89 // If so, then consume c and skip whitespace.
90 inline bool MatchSkipWhiteSpace(uc32 c) {
91 if (c0_ == c) {
92 AdvanceSkipWhitespace();
93 return true;
94 }
95 return false;
96 }
danno@chromium.org40cb8782011-05-25 07:58:50 +000097
98 // A JSON string (production JSONString) is subset of valid JavaScript string
99 // literals. The string must only be double-quoted (not single-quoted), and
100 // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and
101 // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000102 Handle<String> ParseJsonString() {
103 return ScanJsonString<false>();
104 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000105
106 bool ParseJsonString(Handle<String> expected) {
107 int length = expected->length();
108 if (source_->length() - position_ - 1 > length) {
109 AssertNoAllocation no_gc;
110 String::FlatContent content = expected->GetFlatContent();
111 if (content.IsAscii()) {
112 ASSERT_EQ('"', c0_);
113 const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
114 const uint8_t* expected_chars = content.ToOneByteVector().start();
115 for (int i = 0; i < length; i++) {
116 uint8_t c0 = input_chars[i];
117 if (c0 != expected_chars[i] ||
118 c0 == '"' || c0 < 0x20 || c0 == '\\') {
119 return false;
120 }
121 }
122 if (input_chars[length] == '"') {
123 position_ = position_ + length + 1;
124 AdvanceSkipWhitespace();
125 return true;
126 }
127 }
128 }
129 return false;
130 }
131
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000132 Handle<String> ParseJsonInternalizedString() {
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000133 return ScanJsonString<true>();
134 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000135
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000136 template <bool is_internalized>
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000137 Handle<String> ScanJsonString();
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000138 // Creates a new string and copies prefix[start..end] into the beginning
139 // of it. Then scans the rest of the string, adding characters after the
140 // prefix. Called by ScanJsonString when reaching a '\' or non-ASCII char.
141 template <typename StringType, typename SinkChar>
142 Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end);
danno@chromium.org40cb8782011-05-25 07:58:50 +0000143
144 // A JSON number (production JSONNumber) is a subset of the valid JavaScript
145 // decimal number literals.
146 // It includes an optional minus sign, must have at least one
147 // digit before and after a decimal point, may not have prefixed zeros (unless
148 // the integer part is zero), and may include an exponent part (e.g., "e-10").
149 // Hexadecimal and octal numbers are not allowed.
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000150 Handle<Object> ParseJsonNumber();
danno@chromium.org40cb8782011-05-25 07:58:50 +0000151
152 // Parse a single JSON value from input (grammar production JSONValue).
153 // A JSON value is either a (double-quoted) string literal, a number literal,
154 // one of "true", "false", or "null", or an object or array literal.
155 Handle<Object> ParseJsonValue();
156
157 // Parse a JSON object literal (grammar production JSONObject).
158 // An object literal is a squiggly-braced and comma separated sequence
159 // (possibly empty) of key/value pairs, where the key is a JSON string
160 // literal, the value is a JSON value, and the two are separated by a colon.
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000161 // A JSON array doesn't allow numbers and identifiers as keys, like a
danno@chromium.org40cb8782011-05-25 07:58:50 +0000162 // JavaScript array.
163 Handle<Object> ParseJsonObject();
164
165 // Parses a JSON array literal (grammar production JSONArray). An array
166 // literal is a square-bracketed and comma separated sequence (possibly empty)
167 // of JSON values.
168 // A JSON array doesn't allow leaving out values from the sequence, nor does
169 // it allow a terminal comma, like a JavaScript array does.
170 Handle<Object> ParseJsonArray();
171
172
173 // Mark that a parsing error has happened at the current token, and
174 // return a null handle. Primarily for readability.
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000175 inline Handle<Object> ReportUnexpectedCharacter() {
176 return Handle<Object>::null();
177 }
danno@chromium.org40cb8782011-05-25 07:58:50 +0000178
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000179 inline Isolate* isolate() { return isolate_; }
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000180 inline Factory* factory() { return factory_; }
181 inline Handle<JSFunction> object_constructor() { return object_constructor_; }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000182 inline Zone* zone() const { return zone_; }
danno@chromium.org40cb8782011-05-25 07:58:50 +0000183
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000184 static const int kInitialSpecialStringLength = 1024;
danno@chromium.org72204d52012-10-31 10:02:10 +0000185 static const int kPretenureTreshold = 100 * 1024;
danno@chromium.org40cb8782011-05-25 07:58:50 +0000186
187
188 private:
189 Handle<String> source_;
190 int source_length_;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000191 Handle<SeqOneByteString> seq_source_;
danno@chromium.org40cb8782011-05-25 07:58:50 +0000192
danno@chromium.org72204d52012-10-31 10:02:10 +0000193 PretenureFlag pretenure_;
danno@chromium.org40cb8782011-05-25 07:58:50 +0000194 Isolate* isolate_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000195 Factory* factory_;
196 Handle<JSFunction> object_constructor_;
danno@chromium.org40cb8782011-05-25 07:58:50 +0000197 uc32 c0_;
198 int position_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000199 Zone* zone_;
danno@chromium.org40cb8782011-05-25 07:58:50 +0000200};
201
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000202template <bool seq_ascii>
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000203Handle<Object> JsonParser<seq_ascii>::ParseJson(Handle<String> source,
204 Zone* zone) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000205 isolate_ = source->map()->GetHeap()->isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000206 factory_ = isolate_->factory();
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000207 object_constructor_ = Handle<JSFunction>(
208 isolate()->native_context()->object_function(), isolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000209 zone_ = zone;
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000210 FlattenString(source);
211 source_ = source;
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000212 source_length_ = source_->length();
danno@chromium.org72204d52012-10-31 10:02:10 +0000213 pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000214
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000215 // Optimized fast case where we only have ASCII characters.
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000216 if (seq_ascii) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000217 seq_source_ = Handle<SeqOneByteString>::cast(source_);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000218 }
219
220 // Set initial position right before the string.
221 position_ = -1;
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000222 // Advance to the first character (possibly EOS)
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000223 AdvanceSkipWhitespace();
224 Handle<Object> result = ParseJsonValue();
225 if (result.is_null() || c0_ != kEndOfString) {
danno@chromium.org72204d52012-10-31 10:02:10 +0000226 // Some exception (for example stack overflow) is already pending.
227 if (isolate_->has_pending_exception()) return Handle<Object>::null();
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000228
danno@chromium.org72204d52012-10-31 10:02:10 +0000229 // Parse failed. Current character is the unexpected token.
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000230 const char* message;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000231 Factory* factory = this->factory();
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000232 Handle<JSArray> array;
233
234 switch (c0_) {
235 case kEndOfString:
236 message = "unexpected_eos";
237 array = factory->NewJSArray(0);
238 break;
239 case '-':
240 case '0':
241 case '1':
242 case '2':
243 case '3':
244 case '4':
245 case '5':
246 case '6':
247 case '7':
248 case '8':
249 case '9':
250 message = "unexpected_token_number";
251 array = factory->NewJSArray(0);
252 break;
253 case '"':
254 message = "unexpected_token_string";
255 array = factory->NewJSArray(0);
256 break;
257 default:
258 message = "unexpected_token";
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000259 Handle<Object> name =
260 LookupSingleCharacterStringFromCode(isolate_, c0_);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000261 Handle<FixedArray> element = factory->NewFixedArray(1);
262 element->set(0, *name);
263 array = factory->NewJSArrayWithElements(element);
264 break;
265 }
266
267 MessageLocation location(factory->NewScript(source),
268 position_,
269 position_ + 1);
270 Handle<Object> result = factory->NewSyntaxError(message, array);
271 isolate()->Throw(*result, &location);
272 return Handle<Object>::null();
273 }
274 return result;
275}
276
277
278// Parse any JSON value.
279template <bool seq_ascii>
280Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
danno@chromium.org72204d52012-10-31 10:02:10 +0000281 StackLimitCheck stack_check(isolate_);
282 if (stack_check.HasOverflowed()) {
283 isolate_->StackOverflow();
284 return Handle<Object>::null();
285 }
286
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000287 if (c0_ == '"') return ParseJsonString();
288 if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
289 if (c0_ == '{') return ParseJsonObject();
290 if (c0_ == '[') return ParseJsonArray();
291 if (c0_ == 'f') {
292 if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
293 AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
294 AdvanceSkipWhitespace();
295 return factory()->false_value();
296 }
297 return ReportUnexpectedCharacter();
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000298 }
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000299 if (c0_ == 't') {
300 if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
301 AdvanceGetChar() == 'e') {
302 AdvanceSkipWhitespace();
303 return factory()->true_value();
304 }
305 return ReportUnexpectedCharacter();
306 }
307 if (c0_ == 'n') {
308 if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
309 AdvanceGetChar() == 'l') {
310 AdvanceSkipWhitespace();
311 return factory()->null_value();
312 }
313 return ReportUnexpectedCharacter();
314 }
315 return ReportUnexpectedCharacter();
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000316}
317
318
319// Parse a JSON object. Position must be right at '{'.
320template <bool seq_ascii>
321Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000322 HandleScope scope(isolate());
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000323 Handle<JSObject> json_object =
danno@chromium.org72204d52012-10-31 10:02:10 +0000324 factory()->NewJSObject(object_constructor(), pretenure_);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000325 Handle<Map> map(json_object->map());
326 ZoneScope zone_scope(zone(), DELETE_ON_EXIT);
327 ZoneList<Handle<Object> > properties(8, zone());
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000328 ASSERT_EQ(c0_, '{');
329
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000330 bool transitioning = true;
331
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000332 AdvanceSkipWhitespace();
333 if (c0_ != '}') {
334 do {
335 if (c0_ != '"') return ReportUnexpectedCharacter();
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000336
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000337 int start_position = position_;
338 Advance();
339
340 uint32_t index = 0;
danno@chromium.org72204d52012-10-31 10:02:10 +0000341 if (c0_ >= '0' && c0_ <= '9') {
342 // Maybe an array index, try to parse it.
343 if (c0_ == '0') {
344 // With a leading zero, the string has to be "0" only to be an index.
345 Advance();
346 } else {
347 do {
348 int d = c0_ - '0';
349 if (index > 429496729U - ((d > 5) ? 1 : 0)) break;
350 index = (index * 10) + d;
351 Advance();
352 } while (c0_ >= '0' && c0_ <= '9');
353 }
354
355 if (c0_ == '"') {
356 // Successfully parsed index, parse and store element.
357 AdvanceSkipWhitespace();
358
359 if (c0_ != ':') return ReportUnexpectedCharacter();
360 AdvanceSkipWhitespace();
361 Handle<Object> value = ParseJsonValue();
362 if (value.is_null()) return ReportUnexpectedCharacter();
363
364 JSObject::SetOwnElement(json_object, index, value, kNonStrictMode);
365 continue;
366 }
367 // Not an index, fallback to the slow path.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000368 }
369
danno@chromium.org72204d52012-10-31 10:02:10 +0000370 position_ = start_position;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000371#ifdef DEBUG
danno@chromium.org72204d52012-10-31 10:02:10 +0000372 c0_ = '"';
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000373#endif
374
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000375 Handle<String> key;
376 Handle<Object> value;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000377
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000378 // Try to follow existing transitions as long as possible. Once we stop
379 // transitioning, no transition can be found anymore.
380 if (transitioning) {
381 // First check whether there is a single expected transition. If so, try
382 // to parse it first.
383 bool follow_expected = false;
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000384 Handle<Map> target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000385 if (seq_ascii) {
386 key = JSObject::ExpectedTransitionKey(map);
387 follow_expected = !key.is_null() && ParseJsonString(key);
388 }
389 // If the expected transition hits, follow it.
390 if (follow_expected) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000391 target = JSObject::ExpectedTransitionTarget(map);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000392 } else {
393 // If the expected transition failed, parse an internalized string and
394 // try to find a matching transition.
395 key = ParseJsonInternalizedString();
396 if (key.is_null()) return ReportUnexpectedCharacter();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000397
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000398 target = JSObject::FindTransitionToField(map, key);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000399 // If a transition was found, follow it and continue.
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000400 transitioning = !target.is_null();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000401 }
402 if (c0_ != ':') return ReportUnexpectedCharacter();
403
404 AdvanceSkipWhitespace();
405 value = ParseJsonValue();
406 if (value.is_null()) return ReportUnexpectedCharacter();
407
danno@chromium.orgf005df62013-04-30 16:36:45 +0000408 if (transitioning) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000409 int descriptor = map->NumberOfOwnDescriptors();
410 PropertyDetails details =
411 target->instance_descriptors()->GetDetails(descriptor);
412 Representation expected_representation = details.representation();
413
414 if (value->FitsRepresentation(expected_representation)) {
415 // If the target representation is double and the value is already
416 // double, use the existing box.
417 if (FLAG_track_double_fields &&
418 value->IsSmi() &&
419 expected_representation.IsDouble()) {
420 value = factory()->NewHeapNumber(
421 Handle<Smi>::cast(value)->value());
422 }
423 properties.Add(value, zone());
424 map = target;
425 continue;
426 } else {
427 transitioning = false;
danno@chromium.orgf005df62013-04-30 16:36:45 +0000428 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000429 }
430
431 // Commit the intermediate state to the object and stop transitioning.
432 JSObject::AllocateStorageForMap(json_object, map);
433 int length = properties.length();
434 for (int i = 0; i < length; i++) {
435 Handle<Object> value = properties[i];
436 json_object->FastPropertyAtPut(i, *value);
danno@chromium.orgf005df62013-04-30 16:36:45 +0000437 }
danno@chromium.org72204d52012-10-31 10:02:10 +0000438 } else {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000439 key = ParseJsonInternalizedString();
440 if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
441
442 AdvanceSkipWhitespace();
443 value = ParseJsonValue();
444 if (value.is_null()) return ReportUnexpectedCharacter();
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000445 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000446
447 JSObject::SetLocalPropertyIgnoreAttributes(
448 json_object, key, value, NONE);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000449 } while (MatchSkipWhiteSpace(','));
450 if (c0_ != '}') {
451 return ReportUnexpectedCharacter();
452 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000453
454 // If we transitioned until the very end, transition the map now.
455 if (transitioning) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000456 JSObject::AllocateStorageForMap(json_object, map);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000457 int length = properties.length();
458 for (int i = 0; i < length; i++) {
danno@chromium.orgf005df62013-04-30 16:36:45 +0000459 Handle<Object> value = properties[i];
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000460 // If the target representation is double and the value is already
461 // double, use the existing box.
462 if (FLAG_track_double_fields && value->IsSmi()) {
463 Representation representation =
464 map->instance_descriptors()->GetDetails(i).representation();
465 if (representation.IsDouble()) {
466 value = factory()->NewHeapNumber(
467 Handle<Smi>::cast(value)->value());
468 }
danno@chromium.orgf005df62013-04-30 16:36:45 +0000469 }
470 json_object->FastPropertyAtPut(i, *value);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000471 }
472 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000473 }
474 AdvanceSkipWhitespace();
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000475 return scope.CloseAndEscape(json_object);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000476}
477
478// Parse a JSON array. Position must be right at '['.
479template <bool seq_ascii>
480Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000481 HandleScope scope(isolate());
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000482 ZoneScope zone_scope(zone(), DELETE_ON_EXIT);
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000483 ZoneList<Handle<Object> > elements(4, zone());
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000484 ASSERT_EQ(c0_, '[');
485
486 AdvanceSkipWhitespace();
487 if (c0_ != ']') {
488 do {
489 Handle<Object> element = ParseJsonValue();
490 if (element.is_null()) return ReportUnexpectedCharacter();
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000491 elements.Add(element, zone());
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000492 } while (MatchSkipWhiteSpace(','));
493 if (c0_ != ']') {
494 return ReportUnexpectedCharacter();
495 }
496 }
497 AdvanceSkipWhitespace();
498 // Allocate a fixed array with all the elements.
499 Handle<FixedArray> fast_elements =
danno@chromium.org72204d52012-10-31 10:02:10 +0000500 factory()->NewFixedArray(elements.length(), pretenure_);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000501 for (int i = 0, n = elements.length(); i < n; i++) {
502 fast_elements->set(i, *elements[i]);
503 }
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000504 Handle<Object> json_array = factory()->NewJSArrayWithElements(
danno@chromium.org72204d52012-10-31 10:02:10 +0000505 fast_elements, FAST_ELEMENTS, pretenure_);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000506 return scope.CloseAndEscape(json_array);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000507}
508
509
510template <bool seq_ascii>
511Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() {
512 bool negative = false;
ager@chromium.org04921a82011-06-27 13:21:41 +0000513 int beg_pos = position_;
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000514 if (c0_ == '-') {
515 Advance();
516 negative = true;
517 }
518 if (c0_ == '0') {
519 Advance();
520 // Prefix zero is only allowed if it's the only digit before
521 // a decimal point or exponent.
522 if ('0' <= c0_ && c0_ <= '9') return ReportUnexpectedCharacter();
523 } else {
524 int i = 0;
525 int digits = 0;
526 if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
527 do {
528 i = i * 10 + c0_ - '0';
529 digits++;
530 Advance();
531 } while (c0_ >= '0' && c0_ <= '9');
532 if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000533 SkipWhitespace();
ager@chromium.org04921a82011-06-27 13:21:41 +0000534 return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000535 }
536 }
537 if (c0_ == '.') {
538 Advance();
539 if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
540 do {
541 Advance();
542 } while (c0_ >= '0' && c0_ <= '9');
543 }
544 if (AsciiAlphaToLower(c0_) == 'e') {
545 Advance();
546 if (c0_ == '-' || c0_ == '+') Advance();
547 if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
548 do {
549 Advance();
550 } while (c0_ >= '0' && c0_ <= '9');
551 }
ager@chromium.org04921a82011-06-27 13:21:41 +0000552 int length = position_ - beg_pos;
553 double number;
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000554 if (seq_ascii) {
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000555 Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
ager@chromium.org04921a82011-06-27 13:21:41 +0000556 number = StringToDouble(isolate()->unicode_cache(),
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000557 Vector<const char>::cast(chars),
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000558 NO_FLAGS, // Hex, octal or trailing junk.
559 OS::nan_value());
560 } else {
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000561 Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
ager@chromium.org04921a82011-06-27 13:21:41 +0000562 String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000563 Vector<const uint8_t> result =
564 Vector<const uint8_t>(buffer.start(), length);
ager@chromium.org04921a82011-06-27 13:21:41 +0000565 number = StringToDouble(isolate()->unicode_cache(),
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000566 // TODO(dcarney): Convert StringToDouble to uint_t.
567 Vector<const char>::cast(result),
568 NO_FLAGS, // Hex, octal or trailing junk.
569 0.0);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000570 buffer.Dispose();
571 }
572 SkipWhitespace();
danno@chromium.org72204d52012-10-31 10:02:10 +0000573 return factory()->NewNumber(number, pretenure_);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000574}
575
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000576
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000577template <typename StringType>
578inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
579
580template <>
581inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
582 seq_str->SeqTwoByteStringSet(i, c);
583}
584
585template <>
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000586inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
587 seq_str->SeqOneByteStringSet(i, c);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000588}
589
590template <typename StringType>
danno@chromium.org72204d52012-10-31 10:02:10 +0000591inline Handle<StringType> NewRawString(Factory* factory,
592 int length,
593 PretenureFlag pretenure);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000594
595template <>
danno@chromium.org72204d52012-10-31 10:02:10 +0000596inline Handle<SeqTwoByteString> NewRawString(Factory* factory,
597 int length,
598 PretenureFlag pretenure) {
599 return factory->NewRawTwoByteString(length, pretenure);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000600}
601
602template <>
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000603inline Handle<SeqOneByteString> NewRawString(Factory* factory,
danno@chromium.org72204d52012-10-31 10:02:10 +0000604 int length,
605 PretenureFlag pretenure) {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000606 return factory->NewRawOneByteString(length, pretenure);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000607}
608
609
610// Scans the rest of a JSON string starting from position_ and writes
611// prefix[start..end] along with the scanned characters into a
612// sequential string of type StringType.
613template <bool seq_ascii>
614template <typename StringType, typename SinkChar>
615Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
616 Handle<String> prefix, int start, int end) {
617 int count = end - start;
618 int max_length = count + source_length_ - position_;
619 int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000620 Handle<StringType> seq_string =
danno@chromium.org72204d52012-10-31 10:02:10 +0000621 NewRawString<StringType>(factory(), length, pretenure_);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000622 // Copy prefix into seq_str.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000623 SinkChar* dest = seq_string->GetChars();
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000624 String::WriteToFlat(*prefix, dest, start, end);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000625
626 while (c0_ != '"') {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000627 // Check for control character (0x00-0x1f) or unterminated string (<0).
628 if (c0_ < 0x20) return Handle<String>::null();
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000629 if (count >= length) {
630 // We need to create a longer sequential string for the result.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000631 return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000632 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000633 if (c0_ != '\\') {
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000634 // If the sink can contain UC16 characters, or source_ contains only
635 // ASCII characters, there's no need to test whether we can store the
636 // character. Otherwise check whether the UC16 source character can fit
637 // in the ASCII sink.
638 if (sizeof(SinkChar) == kUC16Size ||
639 seq_ascii ||
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000640 c0_ <= String::kMaxOneByteCharCode) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000641 SeqStringSet(seq_string, count++, c0_);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000642 Advance();
643 } else {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000644 // StringType is SeqOneByteString and we just read a non-ASCII char.
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000645 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000646 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000647 } else {
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000648 Advance(); // Advance past the \.
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000649 switch (c0_) {
650 case '"':
651 case '\\':
652 case '/':
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000653 SeqStringSet(seq_string, count++, c0_);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000654 break;
655 case 'b':
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000656 SeqStringSet(seq_string, count++, '\x08');
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000657 break;
658 case 'f':
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000659 SeqStringSet(seq_string, count++, '\x0c');
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000660 break;
661 case 'n':
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000662 SeqStringSet(seq_string, count++, '\x0a');
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000663 break;
664 case 'r':
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000665 SeqStringSet(seq_string, count++, '\x0d');
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000666 break;
667 case 't':
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000668 SeqStringSet(seq_string, count++, '\x09');
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000669 break;
670 case 'u': {
671 uc32 value = 0;
672 for (int i = 0; i < 4; i++) {
673 Advance();
674 int digit = HexValue(c0_);
675 if (digit < 0) {
676 return Handle<String>::null();
677 }
678 value = value * 16 + digit;
679 }
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000680 if (sizeof(SinkChar) == kUC16Size ||
681 value <= String::kMaxOneByteCharCode) {
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000682 SeqStringSet(seq_string, count++, value);
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000683 break;
684 } else {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000685 // StringType is SeqOneByteString and we just read a non-ASCII char.
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000686 position_ -= 6; // Rewind position_ to \ in \uxxxx.
687 Advance();
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000688 return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string,
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000689 0,
690 count);
691 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000692 }
693 default:
694 return Handle<String>::null();
695 }
696 Advance();
697 }
698 }
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000699
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000700 ASSERT_EQ('"', c0_);
701 // Advance past the last '"'.
702 AdvanceSkipWhitespace();
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000703
704 // Shrink seq_string length to count and return.
705 return SeqString::Truncate(seq_string, count);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000706}
707
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000708
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000709template <bool seq_ascii>
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000710template <bool is_internalized>
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000711Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
712 ASSERT_EQ('"', c0_);
713 Advance();
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000714 if (c0_ == '"') {
715 AdvanceSkipWhitespace();
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000716 return factory()->empty_string();
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000717 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000718
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000719 if (seq_ascii && is_internalized) {
720 // Fast path for existing internalized strings. If the the string being
721 // parsed is not a known internalized string, contains backslashes or
722 // unexpectedly reaches the end of string, return with an empty handle.
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000723 uint32_t running_hash = isolate()->heap()->HashSeed();
724 int position = position_;
725 uc32 c0 = c0_;
726 do {
727 if (c0 == '\\') {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000728 c0_ = c0;
729 int beg_pos = position_;
730 position_ = position;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000731 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000732 beg_pos,
733 position_);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000734 }
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000735 if (c0 < 0x20) return Handle<String>::null();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000736 if (static_cast<uint32_t>(c0) >
737 unibrow::Utf16::kMaxNonSurrogateCharCode) {
738 running_hash =
739 StringHasher::AddCharacterCore(running_hash,
740 unibrow::Utf16::LeadSurrogate(c0));
741 running_hash =
742 StringHasher::AddCharacterCore(running_hash,
743 unibrow::Utf16::TrailSurrogate(c0));
744 } else {
745 running_hash = StringHasher::AddCharacterCore(running_hash, c0);
746 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000747 position++;
748 if (position >= source_length_) return Handle<String>::null();
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000749 c0 = seq_source_->SeqOneByteStringGet(position);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000750 } while (c0 != '"');
751 int length = position - position_;
752 uint32_t hash = (length <= String::kMaxHashCalcLength)
753 ? StringHasher::GetHashCore(running_hash) : length;
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000754 Vector<const uint8_t> string_vector(
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000755 seq_source_->GetChars() + position_, length);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000756 StringTable* string_table = isolate()->heap()->string_table();
757 uint32_t capacity = string_table->Capacity();
758 uint32_t entry = StringTable::FirstProbe(hash, capacity);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000759 uint32_t count = 1;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000760 Handle<String> result;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000761 while (true) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000762 Object* element = string_table->KeyAt(entry);
danno@chromium.org72204d52012-10-31 10:02:10 +0000763 if (element == isolate()->heap()->undefined_value()) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000764 // Lookup failure.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000765 result = factory()->InternalizeOneByteString(
766 seq_source_, position_, length);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000767 break;
768 }
danno@chromium.org72204d52012-10-31 10:02:10 +0000769 if (element != isolate()->heap()->the_hole_value() &&
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000770 String::cast(element)->IsOneByteEqualTo(string_vector)) {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000771 result = Handle<String>(String::cast(element), isolate());
772#ifdef DEBUG
773 uint32_t hash_field =
774 (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
775 ASSERT_EQ(static_cast<int>(result->Hash()),
776 static_cast<int>(hash_field >> String::kHashShift));
777#endif
778 break;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000779 }
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000780 entry = StringTable::NextProbe(entry, count++, capacity);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000781 }
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000782 position_ = position;
783 // Advance past the last '"'.
784 AdvanceSkipWhitespace();
785 return result;
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000786 }
787
ager@chromium.org04921a82011-06-27 13:21:41 +0000788 int beg_pos = position_;
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000789 // Fast case for ASCII only without escape characters.
790 do {
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000791 // Check for control character (0x00-0x1f) or unterminated string (<0).
792 if (c0_ < 0x20) return Handle<String>::null();
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000793 if (c0_ != '\\') {
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000794 if (seq_ascii || c0_ <= String::kMaxOneByteCharCode) {
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000795 Advance();
796 } else {
797 return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
798 beg_pos,
799 position_);
800 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000801 } else {
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000802 return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
803 beg_pos,
804 position_);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000805 }
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000806 } while (c0_ != '"');
807 int length = position_ - beg_pos;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000808 Handle<String> result = factory()->NewRawOneByteString(length, pretenure_);
809 uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
810 String::WriteToFlat(*source_, dest, beg_pos, position_);
811
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000812 ASSERT_EQ('"', c0_);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000813 // Advance past the last '"'.
814 AdvanceSkipWhitespace();
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000815 return result;
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000816}
817
danno@chromium.org40cb8782011-05-25 07:58:50 +0000818} } // namespace v8::internal
819
820#endif // V8_JSON_PARSER_H_