Home | History | Annotate | Download | only in src
      1 // 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 
     31 #include "v8.h"
     32 
     33 #include "char-predicates-inl.h"
     34 #include "v8conversions.h"
     35 #include "messages.h"
     36 #include "spaces-inl.h"
     37 #include "token.h"
     38 
     39 namespace v8 {
     40 namespace internal {
     41 
     42 // A simple json parser.
     43 template <bool seq_ascii>
     44 class JsonParser BASE_EMBEDDED {
     45  public:
     46   static Handle<Object> Parse(Handle<String> source) {
     47     return JsonParser(source).ParseJson();
     48   }
     49 
     50   static const int kEndOfString = -1;
     51 
     52  private:
     53   explicit JsonParser(Handle<String> source)
     54       : source_(source),
     55         source_length_(source->length()),
     56         isolate_(source->map()->GetHeap()->isolate()),
     57         factory_(isolate_->factory()),
     58         zone_(isolate_),
     59         object_constructor_(isolate_->native_context()->object_function(),
     60                             isolate_),
     61         position_(-1) {
     62     FlattenString(source_);
     63     pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
     64 
     65     // Optimized fast case where we only have ASCII characters.
     66     if (seq_ascii) {
     67       seq_source_ = Handle<SeqOneByteString>::cast(source_);
     68     }
     69   }
     70 
     71   // Parse a string containing a single JSON value.
     72   Handle<Object> ParseJson();
     73 
     74   inline void Advance() {
     75     position_++;
     76     if (position_ >= source_length_) {
     77       c0_ = kEndOfString;
     78     } else if (seq_ascii) {
     79       c0_ = seq_source_->SeqOneByteStringGet(position_);
     80     } else {
     81       c0_ = source_->Get(position_);
     82     }
     83   }
     84 
     85   // The JSON lexical grammar is specified in the ECMAScript 5 standard,
     86   // section 15.12.1.1. The only allowed whitespace characters between tokens
     87   // are tab, carriage-return, newline and space.
     88 
     89   inline void AdvanceSkipWhitespace() {
     90     do {
     91       Advance();
     92     } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
     93   }
     94 
     95   inline void SkipWhitespace() {
     96     while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
     97       Advance();
     98     }
     99   }
    100 
    101   inline uc32 AdvanceGetChar() {
    102     Advance();
    103     return c0_;
    104   }
    105 
    106   // Checks that current charater is c.
    107   // If so, then consume c and skip whitespace.
    108   inline bool MatchSkipWhiteSpace(uc32 c) {
    109     if (c0_ == c) {
    110       AdvanceSkipWhitespace();
    111       return true;
    112     }
    113     return false;
    114   }
    115 
    116   // A JSON string (production JSONString) is subset of valid JavaScript string
    117   // literals. The string must only be double-quoted (not single-quoted), and
    118   // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and
    119   // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
    120   Handle<String> ParseJsonString() {
    121     return ScanJsonString<false>();
    122   }
    123 
    124   bool ParseJsonString(Handle<String> expected) {
    125     int length = expected->length();
    126     if (source_->length() - position_ - 1 > length) {
    127       DisallowHeapAllocation no_gc;
    128       String::FlatContent content = expected->GetFlatContent();
    129       if (content.IsAscii()) {
    130         ASSERT_EQ('"', c0_);
    131         const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
    132         const uint8_t* expected_chars = content.ToOneByteVector().start();
    133         for (int i = 0; i < length; i++) {
    134           uint8_t c0 = input_chars[i];
    135           if (c0 != expected_chars[i] ||
    136               c0 == '"' || c0 < 0x20 || c0 == '\\') {
    137             return false;
    138           }
    139         }
    140         if (input_chars[length] == '"') {
    141           position_ = position_ + length + 1;
    142           AdvanceSkipWhitespace();
    143           return true;
    144         }
    145       }
    146     }
    147     return false;
    148   }
    149 
    150   Handle<String> ParseJsonInternalizedString() {
    151     return ScanJsonString<true>();
    152   }
    153 
    154   template <bool is_internalized>
    155   Handle<String> ScanJsonString();
    156   // Creates a new string and copies prefix[start..end] into the beginning
    157   // of it. Then scans the rest of the string, adding characters after the
    158   // prefix. Called by ScanJsonString when reaching a '\' or non-ASCII char.
    159   template <typename StringType, typename SinkChar>
    160   Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end);
    161 
    162   // A JSON number (production JSONNumber) is a subset of the valid JavaScript
    163   // decimal number literals.
    164   // It includes an optional minus sign, must have at least one
    165   // digit before and after a decimal point, may not have prefixed zeros (unless
    166   // the integer part is zero), and may include an exponent part (e.g., "e-10").
    167   // Hexadecimal and octal numbers are not allowed.
    168   Handle<Object> ParseJsonNumber();
    169 
    170   // Parse a single JSON value from input (grammar production JSONValue).
    171   // A JSON value is either a (double-quoted) string literal, a number literal,
    172   // one of "true", "false", or "null", or an object or array literal.
    173   Handle<Object> ParseJsonValue();
    174 
    175   // Parse a JSON object literal (grammar production JSONObject).
    176   // An object literal is a squiggly-braced and comma separated sequence
    177   // (possibly empty) of key/value pairs, where the key is a JSON string
    178   // literal, the value is a JSON value, and the two are separated by a colon.
    179   // A JSON array doesn't allow numbers and identifiers as keys, like a
    180   // JavaScript array.
    181   Handle<Object> ParseJsonObject();
    182 
    183   // Parses a JSON array literal (grammar production JSONArray). An array
    184   // literal is a square-bracketed and comma separated sequence (possibly empty)
    185   // of JSON values.
    186   // A JSON array doesn't allow leaving out values from the sequence, nor does
    187   // it allow a terminal comma, like a JavaScript array does.
    188   Handle<Object> ParseJsonArray();
    189 
    190 
    191   // Mark that a parsing error has happened at the current token, and
    192   // return a null handle. Primarily for readability.
    193   inline Handle<Object> ReportUnexpectedCharacter() {
    194     return Handle<Object>::null();
    195   }
    196 
    197   inline Isolate* isolate() { return isolate_; }
    198   inline Factory* factory() { return factory_; }
    199   inline Handle<JSFunction> object_constructor() { return object_constructor_; }
    200 
    201   static const int kInitialSpecialStringLength = 1024;
    202   static const int kPretenureTreshold = 100 * 1024;
    203 
    204 
    205  private:
    206   Zone* zone() { return &zone_; }
    207 
    208   Handle<String> source_;
    209   int source_length_;
    210   Handle<SeqOneByteString> seq_source_;
    211 
    212   PretenureFlag pretenure_;
    213   Isolate* isolate_;
    214   Factory* factory_;
    215   Zone zone_;
    216   Handle<JSFunction> object_constructor_;
    217   uc32 c0_;
    218   int position_;
    219 };
    220 
    221 template <bool seq_ascii>
    222 Handle<Object> JsonParser<seq_ascii>::ParseJson() {
    223   // Advance to the first character (possibly EOS)
    224   AdvanceSkipWhitespace();
    225   Handle<Object> result = ParseJsonValue();
    226   if (result.is_null() || c0_ != kEndOfString) {
    227     // Some exception (for example stack overflow) is already pending.
    228     if (isolate_->has_pending_exception()) return Handle<Object>::null();
    229 
    230     // Parse failed. Current character is the unexpected token.
    231     const char* message;
    232     Factory* factory = this->factory();
    233     Handle<JSArray> array;
    234 
    235     switch (c0_) {
    236       case kEndOfString:
    237         message = "unexpected_eos";
    238         array = factory->NewJSArray(0);
    239         break;
    240       case '-':
    241       case '0':
    242       case '1':
    243       case '2':
    244       case '3':
    245       case '4':
    246       case '5':
    247       case '6':
    248       case '7':
    249       case '8':
    250       case '9':
    251         message = "unexpected_token_number";
    252         array = factory->NewJSArray(0);
    253         break;
    254       case '"':
    255         message = "unexpected_token_string";
    256         array = factory->NewJSArray(0);
    257         break;
    258       default:
    259         message = "unexpected_token";
    260         Handle<Object> name =
    261             LookupSingleCharacterStringFromCode(isolate_, c0_);
    262         Handle<FixedArray> element = factory->NewFixedArray(1);
    263         element->set(0, *name);
    264         array = factory->NewJSArrayWithElements(element);
    265         break;
    266     }
    267 
    268     MessageLocation location(factory->NewScript(source_),
    269                              position_,
    270                              position_ + 1);
    271     Handle<Object> result = factory->NewSyntaxError(message, array);
    272     isolate()->Throw(*result, &location);
    273     return Handle<Object>::null();
    274   }
    275   return result;
    276 }
    277 
    278 
    279 // Parse any JSON value.
    280 template <bool seq_ascii>
    281 Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
    282   StackLimitCheck stack_check(isolate_);
    283   if (stack_check.HasOverflowed()) {
    284     isolate_->StackOverflow();
    285     return Handle<Object>::null();
    286   }
    287 
    288   if (c0_ == '"') return ParseJsonString();
    289   if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
    290   if (c0_ == '{') return ParseJsonObject();
    291   if (c0_ == '[') return ParseJsonArray();
    292   if (c0_ == 'f') {
    293     if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
    294         AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
    295       AdvanceSkipWhitespace();
    296       return factory()->false_value();
    297     }
    298     return ReportUnexpectedCharacter();
    299   }
    300   if (c0_ == 't') {
    301     if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
    302         AdvanceGetChar() == 'e') {
    303       AdvanceSkipWhitespace();
    304       return factory()->true_value();
    305     }
    306     return ReportUnexpectedCharacter();
    307   }
    308   if (c0_ == 'n') {
    309     if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
    310         AdvanceGetChar() == 'l') {
    311       AdvanceSkipWhitespace();
    312       return factory()->null_value();
    313     }
    314     return ReportUnexpectedCharacter();
    315   }
    316   return ReportUnexpectedCharacter();
    317 }
    318 
    319 
    320 // Parse a JSON object. Position must be right at '{'.
    321 template <bool seq_ascii>
    322 Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
    323   HandleScope scope(isolate());
    324   Handle<JSObject> json_object =
    325       factory()->NewJSObject(object_constructor(), pretenure_);
    326   Handle<Map> map(json_object->map());
    327   ZoneList<Handle<Object> > properties(8, zone());
    328   ASSERT_EQ(c0_, '{');
    329 
    330   bool transitioning = true;
    331 
    332   AdvanceSkipWhitespace();
    333   if (c0_ != '}') {
    334     do {
    335       if (c0_ != '"') return ReportUnexpectedCharacter();
    336 
    337       int start_position = position_;
    338       Advance();
    339 
    340       uint32_t index = 0;
    341       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.
    368       }
    369 
    370       position_ = start_position;
    371 #ifdef DEBUG
    372       c0_ = '"';
    373 #endif
    374 
    375       Handle<String> key;
    376       Handle<Object> value;
    377 
    378       // 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;
    384         Handle<Map> target;
    385         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) {
    391           target = JSObject::ExpectedTransitionTarget(map);
    392         } 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();
    397 
    398           target = JSObject::FindTransitionToField(map, key);
    399           // If a transition was found, follow it and continue.
    400           transitioning = !target.is_null();
    401         }
    402         if (c0_ != ':') return ReportUnexpectedCharacter();
    403 
    404         AdvanceSkipWhitespace();
    405         value = ParseJsonValue();
    406         if (value.is_null()) return ReportUnexpectedCharacter();
    407 
    408         if (transitioning) {
    409           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;
    428           }
    429         }
    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);
    437         }
    438       } else {
    439         key = ParseJsonInternalizedString();
    440         if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
    441 
    442         AdvanceSkipWhitespace();
    443         value = ParseJsonValue();
    444         if (value.is_null()) return ReportUnexpectedCharacter();
    445       }
    446 
    447       JSObject::SetLocalPropertyIgnoreAttributes(
    448           json_object, key, value, NONE);
    449     } while (MatchSkipWhiteSpace(','));
    450     if (c0_ != '}') {
    451       return ReportUnexpectedCharacter();
    452     }
    453 
    454     // If we transitioned until the very end, transition the map now.
    455     if (transitioning) {
    456       JSObject::AllocateStorageForMap(json_object, map);
    457       int length = properties.length();
    458       for (int i = 0; i < length; i++) {
    459         Handle<Object> value = properties[i];
    460         json_object->FastPropertyAtPut(i, *value);
    461       }
    462     }
    463   }
    464   AdvanceSkipWhitespace();
    465   return scope.CloseAndEscape(json_object);
    466 }
    467 
    468 // Parse a JSON array. Position must be right at '['.
    469 template <bool seq_ascii>
    470 Handle<Object> JsonParser<seq_ascii>::ParseJsonArray() {
    471   HandleScope scope(isolate());
    472   ZoneList<Handle<Object> > elements(4, zone());
    473   ASSERT_EQ(c0_, '[');
    474 
    475   AdvanceSkipWhitespace();
    476   if (c0_ != ']') {
    477     do {
    478       Handle<Object> element = ParseJsonValue();
    479       if (element.is_null()) return ReportUnexpectedCharacter();
    480       elements.Add(element, zone());
    481     } while (MatchSkipWhiteSpace(','));
    482     if (c0_ != ']') {
    483       return ReportUnexpectedCharacter();
    484     }
    485   }
    486   AdvanceSkipWhitespace();
    487   // Allocate a fixed array with all the elements.
    488   Handle<FixedArray> fast_elements =
    489       factory()->NewFixedArray(elements.length(), pretenure_);
    490   for (int i = 0, n = elements.length(); i < n; i++) {
    491     fast_elements->set(i, *elements[i]);
    492   }
    493   Handle<Object> json_array = factory()->NewJSArrayWithElements(
    494       fast_elements, FAST_ELEMENTS, pretenure_);
    495   return scope.CloseAndEscape(json_array);
    496 }
    497 
    498 
    499 template <bool seq_ascii>
    500 Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() {
    501   bool negative = false;
    502   int beg_pos = position_;
    503   if (c0_ == '-') {
    504     Advance();
    505     negative = true;
    506   }
    507   if (c0_ == '0') {
    508     Advance();
    509     // Prefix zero is only allowed if it's the only digit before
    510     // a decimal point or exponent.
    511     if ('0' <= c0_ && c0_ <= '9') return ReportUnexpectedCharacter();
    512   } else {
    513     int i = 0;
    514     int digits = 0;
    515     if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
    516     do {
    517       i = i * 10 + c0_ - '0';
    518       digits++;
    519       Advance();
    520     } while (c0_ >= '0' && c0_ <= '9');
    521     if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
    522       SkipWhitespace();
    523       return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
    524     }
    525   }
    526   if (c0_ == '.') {
    527     Advance();
    528     if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
    529     do {
    530       Advance();
    531     } while (c0_ >= '0' && c0_ <= '9');
    532   }
    533   if (AsciiAlphaToLower(c0_) == 'e') {
    534     Advance();
    535     if (c0_ == '-' || c0_ == '+') Advance();
    536     if (c0_ < '0' || c0_ > '9') return ReportUnexpectedCharacter();
    537     do {
    538       Advance();
    539     } while (c0_ >= '0' && c0_ <= '9');
    540   }
    541   int length = position_ - beg_pos;
    542   double number;
    543   if (seq_ascii) {
    544     Vector<const uint8_t> chars(seq_source_->GetChars() +  beg_pos, length);
    545     number = StringToDouble(isolate()->unicode_cache(),
    546                              Vector<const char>::cast(chars),
    547                              NO_FLAGS,  // Hex, octal or trailing junk.
    548                              OS::nan_value());
    549   } else {
    550     Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
    551     String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
    552     Vector<const uint8_t> result =
    553         Vector<const uint8_t>(buffer.start(), length);
    554     number = StringToDouble(isolate()->unicode_cache(),
    555                             // TODO(dcarney): Convert StringToDouble to uint_t.
    556                             Vector<const char>::cast(result),
    557                             NO_FLAGS,  // Hex, octal or trailing junk.
    558                             0.0);
    559     buffer.Dispose();
    560   }
    561   SkipWhitespace();
    562   return factory()->NewNumber(number, pretenure_);
    563 }
    564 
    565 
    566 template <typename StringType>
    567 inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
    568 
    569 template <>
    570 inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
    571   seq_str->SeqTwoByteStringSet(i, c);
    572 }
    573 
    574 template <>
    575 inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
    576   seq_str->SeqOneByteStringSet(i, c);
    577 }
    578 
    579 template <typename StringType>
    580 inline Handle<StringType> NewRawString(Factory* factory,
    581                                        int length,
    582                                        PretenureFlag pretenure);
    583 
    584 template <>
    585 inline Handle<SeqTwoByteString> NewRawString(Factory* factory,
    586                                              int length,
    587                                              PretenureFlag pretenure) {
    588   return factory->NewRawTwoByteString(length, pretenure);
    589 }
    590 
    591 template <>
    592 inline Handle<SeqOneByteString> NewRawString(Factory* factory,
    593                                            int length,
    594                                            PretenureFlag pretenure) {
    595   return factory->NewRawOneByteString(length, pretenure);
    596 }
    597 
    598 
    599 // Scans the rest of a JSON string starting from position_ and writes
    600 // prefix[start..end] along with the scanned characters into a
    601 // sequential string of type StringType.
    602 template <bool seq_ascii>
    603 template <typename StringType, typename SinkChar>
    604 Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
    605     Handle<String> prefix, int start, int end) {
    606   int count = end - start;
    607   int max_length = count + source_length_ - position_;
    608   int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
    609   Handle<StringType> seq_string =
    610       NewRawString<StringType>(factory(), length, pretenure_);
    611   // Copy prefix into seq_str.
    612   SinkChar* dest = seq_string->GetChars();
    613   String::WriteToFlat(*prefix, dest, start, end);
    614 
    615   while (c0_ != '"') {
    616     // Check for control character (0x00-0x1f) or unterminated string (<0).
    617     if (c0_ < 0x20) return Handle<String>::null();
    618     if (count >= length) {
    619       // We need to create a longer sequential string for the result.
    620       return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
    621     }
    622     if (c0_ != '\\') {
    623       // If the sink can contain UC16 characters, or source_ contains only
    624       // ASCII characters, there's no need to test whether we can store the
    625       // character. Otherwise check whether the UC16 source character can fit
    626       // in the ASCII sink.
    627       if (sizeof(SinkChar) == kUC16Size ||
    628           seq_ascii ||
    629           c0_ <= String::kMaxOneByteCharCode) {
    630         SeqStringSet(seq_string, count++, c0_);
    631         Advance();
    632       } else {
    633         // StringType is SeqOneByteString and we just read a non-ASCII char.
    634         return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
    635       }
    636     } else {
    637       Advance();  // Advance past the \.
    638       switch (c0_) {
    639         case '"':
    640         case '\\':
    641         case '/':
    642           SeqStringSet(seq_string, count++, c0_);
    643           break;
    644         case 'b':
    645           SeqStringSet(seq_string, count++, '\x08');
    646           break;
    647         case 'f':
    648           SeqStringSet(seq_string, count++, '\x0c');
    649           break;
    650         case 'n':
    651           SeqStringSet(seq_string, count++, '\x0a');
    652           break;
    653         case 'r':
    654           SeqStringSet(seq_string, count++, '\x0d');
    655           break;
    656         case 't':
    657           SeqStringSet(seq_string, count++, '\x09');
    658           break;
    659         case 'u': {
    660           uc32 value = 0;
    661           for (int i = 0; i < 4; i++) {
    662             Advance();
    663             int digit = HexValue(c0_);
    664             if (digit < 0) {
    665               return Handle<String>::null();
    666             }
    667             value = value * 16 + digit;
    668           }
    669           if (sizeof(SinkChar) == kUC16Size ||
    670               value <= String::kMaxOneByteCharCode) {
    671             SeqStringSet(seq_string, count++, value);
    672             break;
    673           } else {
    674             // StringType is SeqOneByteString and we just read a non-ASCII char.
    675             position_ -= 6;  // Rewind position_ to \ in \uxxxx.
    676             Advance();
    677             return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string,
    678                                                               0,
    679                                                               count);
    680           }
    681         }
    682         default:
    683           return Handle<String>::null();
    684       }
    685       Advance();
    686     }
    687   }
    688 
    689   ASSERT_EQ('"', c0_);
    690   // Advance past the last '"'.
    691   AdvanceSkipWhitespace();
    692 
    693   // Shrink seq_string length to count and return.
    694   return SeqString::Truncate(seq_string, count);
    695 }
    696 
    697 
    698 template <bool seq_ascii>
    699 template <bool is_internalized>
    700 Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
    701   ASSERT_EQ('"', c0_);
    702   Advance();
    703   if (c0_ == '"') {
    704     AdvanceSkipWhitespace();
    705     return factory()->empty_string();
    706   }
    707 
    708   if (seq_ascii && is_internalized) {
    709     // Fast path for existing internalized strings.  If the the string being
    710     // parsed is not a known internalized string, contains backslashes or
    711     // unexpectedly reaches the end of string, return with an empty handle.
    712     uint32_t running_hash = isolate()->heap()->HashSeed();
    713     int position = position_;
    714     uc32 c0 = c0_;
    715     do {
    716       if (c0 == '\\') {
    717         c0_ = c0;
    718         int beg_pos = position_;
    719         position_ = position;
    720         return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
    721                                                              beg_pos,
    722                                                              position_);
    723       }
    724       if (c0 < 0x20) return Handle<String>::null();
    725       if (static_cast<uint32_t>(c0) >
    726           unibrow::Utf16::kMaxNonSurrogateCharCode) {
    727         running_hash =
    728             StringHasher::AddCharacterCore(running_hash,
    729                                            unibrow::Utf16::LeadSurrogate(c0));
    730         running_hash =
    731             StringHasher::AddCharacterCore(running_hash,
    732                                            unibrow::Utf16::TrailSurrogate(c0));
    733       } else {
    734         running_hash = StringHasher::AddCharacterCore(running_hash, c0);
    735       }
    736       position++;
    737       if (position >= source_length_) return Handle<String>::null();
    738       c0 = seq_source_->SeqOneByteStringGet(position);
    739     } while (c0 != '"');
    740     int length = position - position_;
    741     uint32_t hash = (length <= String::kMaxHashCalcLength)
    742         ? StringHasher::GetHashCore(running_hash) : length;
    743     Vector<const uint8_t> string_vector(
    744         seq_source_->GetChars() + position_, length);
    745     StringTable* string_table = isolate()->heap()->string_table();
    746     uint32_t capacity = string_table->Capacity();
    747     uint32_t entry = StringTable::FirstProbe(hash, capacity);
    748     uint32_t count = 1;
    749     Handle<String> result;
    750     while (true) {
    751       Object* element = string_table->KeyAt(entry);
    752       if (element == isolate()->heap()->undefined_value()) {
    753         // Lookup failure.
    754         result = factory()->InternalizeOneByteString(
    755             seq_source_, position_, length);
    756         break;
    757       }
    758       if (element != isolate()->heap()->the_hole_value() &&
    759           String::cast(element)->IsOneByteEqualTo(string_vector)) {
    760         result = Handle<String>(String::cast(element), isolate());
    761 #ifdef DEBUG
    762         uint32_t hash_field =
    763             (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
    764         ASSERT_EQ(static_cast<int>(result->Hash()),
    765                   static_cast<int>(hash_field >> String::kHashShift));
    766 #endif
    767         break;
    768       }
    769       entry = StringTable::NextProbe(entry, count++, capacity);
    770     }
    771     position_ = position;
    772     // Advance past the last '"'.
    773     AdvanceSkipWhitespace();
    774     return result;
    775   }
    776 
    777   int beg_pos = position_;
    778   // Fast case for ASCII only without escape characters.
    779   do {
    780     // Check for control character (0x00-0x1f) or unterminated string (<0).
    781     if (c0_ < 0x20) return Handle<String>::null();
    782     if (c0_ != '\\') {
    783       if (seq_ascii || c0_ <= String::kMaxOneByteCharCode) {
    784         Advance();
    785       } else {
    786         return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
    787                                                           beg_pos,
    788                                                           position_);
    789       }
    790     } else {
    791       return SlowScanJsonString<SeqOneByteString, uint8_t>(source_,
    792                                                            beg_pos,
    793                                                            position_);
    794     }
    795   } while (c0_ != '"');
    796   int length = position_ - beg_pos;
    797   Handle<String> result = factory()->NewRawOneByteString(length, pretenure_);
    798   uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
    799   String::WriteToFlat(*source_, dest, beg_pos, position_);
    800 
    801   ASSERT_EQ('"', c0_);
    802   // Advance past the last '"'.
    803   AdvanceSkipWhitespace();
    804   return result;
    805 }
    806 
    807 } }  // namespace v8::internal
    808 
    809 #endif  // V8_JSON_PARSER_H_
    810