Home | History | Annotate | Download | only in src
      1 // Copyright 2016 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/json-parser.h"
      6 
      7 #include "src/char-predicates-inl.h"
      8 #include "src/conversions.h"
      9 #include "src/debug/debug.h"
     10 #include "src/factory.h"
     11 #include "src/field-type.h"
     12 #include "src/messages.h"
     13 #include "src/objects-inl.h"
     14 #include "src/parsing/token.h"
     15 #include "src/property-descriptor.h"
     16 #include "src/transitions.h"
     17 #include "src/unicode-cache.h"
     18 
     19 namespace v8 {
     20 namespace internal {
     21 
     22 MaybeHandle<Object> JsonParseInternalizer::Internalize(Isolate* isolate,
     23                                                        Handle<Object> object,
     24                                                        Handle<Object> reviver) {
     25   DCHECK(reviver->IsCallable());
     26   JsonParseInternalizer internalizer(isolate,
     27                                      Handle<JSReceiver>::cast(reviver));
     28   Handle<JSObject> holder =
     29       isolate->factory()->NewJSObject(isolate->object_function());
     30   Handle<String> name = isolate->factory()->empty_string();
     31   JSObject::AddProperty(holder, name, object, NONE);
     32   return internalizer.InternalizeJsonProperty(holder, name);
     33 }
     34 
     35 MaybeHandle<Object> JsonParseInternalizer::InternalizeJsonProperty(
     36     Handle<JSReceiver> holder, Handle<String> name) {
     37   HandleScope outer_scope(isolate_);
     38   Handle<Object> value;
     39   ASSIGN_RETURN_ON_EXCEPTION(
     40       isolate_, value, Object::GetPropertyOrElement(holder, name), Object);
     41   if (value->IsJSReceiver()) {
     42     Handle<JSReceiver> object = Handle<JSReceiver>::cast(value);
     43     Maybe<bool> is_array = Object::IsArray(object);
     44     if (is_array.IsNothing()) return MaybeHandle<Object>();
     45     if (is_array.FromJust()) {
     46       Handle<Object> length_object;
     47       ASSIGN_RETURN_ON_EXCEPTION(
     48           isolate_, length_object,
     49           Object::GetLengthFromArrayLike(isolate_, object), Object);
     50       double length = length_object->Number();
     51       for (double i = 0; i < length; i++) {
     52         HandleScope inner_scope(isolate_);
     53         Handle<Object> index = isolate_->factory()->NewNumber(i);
     54         Handle<String> name = isolate_->factory()->NumberToString(index);
     55         if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
     56       }
     57     } else {
     58       Handle<FixedArray> contents;
     59       ASSIGN_RETURN_ON_EXCEPTION(
     60           isolate_, contents,
     61           KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
     62                                   ENUMERABLE_STRINGS,
     63                                   GetKeysConversion::kConvertToString),
     64           Object);
     65       for (int i = 0; i < contents->length(); i++) {
     66         HandleScope inner_scope(isolate_);
     67         Handle<String> name(String::cast(contents->get(i)), isolate_);
     68         if (!RecurseAndApply(object, name)) return MaybeHandle<Object>();
     69       }
     70     }
     71   }
     72   Handle<Object> argv[] = {name, value};
     73   Handle<Object> result;
     74   ASSIGN_RETURN_ON_EXCEPTION(
     75       isolate_, result, Execution::Call(isolate_, reviver_, holder, 2, argv),
     76       Object);
     77   return outer_scope.CloseAndEscape(result);
     78 }
     79 
     80 bool JsonParseInternalizer::RecurseAndApply(Handle<JSReceiver> holder,
     81                                             Handle<String> name) {
     82   Handle<Object> result;
     83   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     84       isolate_, result, InternalizeJsonProperty(holder, name), false);
     85   Maybe<bool> change_result = Nothing<bool>();
     86   if (result->IsUndefined(isolate_)) {
     87     change_result = JSReceiver::DeletePropertyOrElement(holder, name, SLOPPY);
     88   } else {
     89     PropertyDescriptor desc;
     90     desc.set_value(result);
     91     desc.set_configurable(true);
     92     desc.set_enumerable(true);
     93     desc.set_writable(true);
     94     change_result = JSReceiver::DefineOwnProperty(isolate_, holder, name, &desc,
     95                                                   Object::DONT_THROW);
     96   }
     97   MAYBE_RETURN(change_result, false);
     98   return true;
     99 }
    100 
    101 template <bool seq_one_byte>
    102 JsonParser<seq_one_byte>::JsonParser(Isolate* isolate, Handle<String> source)
    103     : source_(source),
    104       source_length_(source->length()),
    105       isolate_(isolate),
    106       factory_(isolate_->factory()),
    107       zone_(isolate_->allocator(), ZONE_NAME),
    108       object_constructor_(isolate_->native_context()->object_function(),
    109                           isolate_),
    110       position_(-1) {
    111   source_ = String::Flatten(source_);
    112   pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED : NOT_TENURED;
    113 
    114   // Optimized fast case where we only have Latin1 characters.
    115   if (seq_one_byte) {
    116     seq_source_ = Handle<SeqOneByteString>::cast(source_);
    117   }
    118 }
    119 
    120 template <bool seq_one_byte>
    121 MaybeHandle<Object> JsonParser<seq_one_byte>::ParseJson() {
    122   // Advance to the first character (possibly EOS)
    123   AdvanceSkipWhitespace();
    124   Handle<Object> result = ParseJsonValue();
    125   if (result.is_null() || c0_ != kEndOfString) {
    126     // Some exception (for example stack overflow) is already pending.
    127     if (isolate_->has_pending_exception()) return Handle<Object>::null();
    128 
    129     // Parse failed. Current character is the unexpected token.
    130     Factory* factory = this->factory();
    131     MessageTemplate::Template message;
    132     Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(position_), isolate());
    133     Handle<Object> arg2;
    134 
    135     switch (c0_) {
    136       case kEndOfString:
    137         message = MessageTemplate::kJsonParseUnexpectedEOS;
    138         break;
    139       case '-':
    140       case '0':
    141       case '1':
    142       case '2':
    143       case '3':
    144       case '4':
    145       case '5':
    146       case '6':
    147       case '7':
    148       case '8':
    149       case '9':
    150         message = MessageTemplate::kJsonParseUnexpectedTokenNumber;
    151         break;
    152       case '"':
    153         message = MessageTemplate::kJsonParseUnexpectedTokenString;
    154         break;
    155       default:
    156         message = MessageTemplate::kJsonParseUnexpectedToken;
    157         arg2 = arg1;
    158         arg1 = factory->LookupSingleCharacterStringFromCode(c0_);
    159         break;
    160     }
    161 
    162     Handle<Script> script(factory->NewScript(source_));
    163     // We should sent compile error event because we compile JSON object in
    164     // separated source file.
    165     isolate()->debug()->OnCompileError(script);
    166     MessageLocation location(script, position_, position_ + 1);
    167     Handle<Object> error = factory->NewSyntaxError(message, arg1, arg2);
    168     return isolate()->template Throw<Object>(error, &location);
    169   }
    170   return result;
    171 }
    172 
    173 MaybeHandle<Object> InternalizeJsonProperty(Handle<JSObject> holder,
    174                                             Handle<String> key);
    175 
    176 template <bool seq_one_byte>
    177 void JsonParser<seq_one_byte>::Advance() {
    178   position_++;
    179   if (position_ >= source_length_) {
    180     c0_ = kEndOfString;
    181   } else if (seq_one_byte) {
    182     c0_ = seq_source_->SeqOneByteStringGet(position_);
    183   } else {
    184     c0_ = source_->Get(position_);
    185   }
    186 }
    187 
    188 template <bool seq_one_byte>
    189 void JsonParser<seq_one_byte>::AdvanceSkipWhitespace() {
    190   do {
    191     Advance();
    192   } while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r');
    193 }
    194 
    195 template <bool seq_one_byte>
    196 void JsonParser<seq_one_byte>::SkipWhitespace() {
    197   while (c0_ == ' ' || c0_ == '\t' || c0_ == '\n' || c0_ == '\r') {
    198     Advance();
    199   }
    200 }
    201 
    202 template <bool seq_one_byte>
    203 uc32 JsonParser<seq_one_byte>::AdvanceGetChar() {
    204   Advance();
    205   return c0_;
    206 }
    207 
    208 template <bool seq_one_byte>
    209 bool JsonParser<seq_one_byte>::MatchSkipWhiteSpace(uc32 c) {
    210   if (c0_ == c) {
    211     AdvanceSkipWhitespace();
    212     return true;
    213   }
    214   return false;
    215 }
    216 
    217 template <bool seq_one_byte>
    218 bool JsonParser<seq_one_byte>::ParseJsonString(Handle<String> expected) {
    219   int length = expected->length();
    220   if (source_->length() - position_ - 1 > length) {
    221     DisallowHeapAllocation no_gc;
    222     String::FlatContent content = expected->GetFlatContent();
    223     if (content.IsOneByte()) {
    224       DCHECK_EQ('"', c0_);
    225       const uint8_t* input_chars = seq_source_->GetChars() + position_ + 1;
    226       const uint8_t* expected_chars = content.ToOneByteVector().start();
    227       for (int i = 0; i < length; i++) {
    228         uint8_t c0 = input_chars[i];
    229         if (c0 != expected_chars[i] || c0 == '"' || c0 < 0x20 || c0 == '\\') {
    230           return false;
    231         }
    232       }
    233       if (input_chars[length] == '"') {
    234         position_ = position_ + length + 1;
    235         AdvanceSkipWhitespace();
    236         return true;
    237       }
    238     }
    239   }
    240   return false;
    241 }
    242 
    243 // Parse any JSON value.
    244 template <bool seq_one_byte>
    245 Handle<Object> JsonParser<seq_one_byte>::ParseJsonValue() {
    246   StackLimitCheck stack_check(isolate_);
    247   if (stack_check.HasOverflowed()) {
    248     isolate_->StackOverflow();
    249     return Handle<Object>::null();
    250   }
    251 
    252   if (stack_check.InterruptRequested() &&
    253       isolate_->stack_guard()->HandleInterrupts()->IsException(isolate_)) {
    254     return Handle<Object>::null();
    255   }
    256 
    257   if (c0_ == '"') return ParseJsonString();
    258   if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
    259   if (c0_ == '{') return ParseJsonObject();
    260   if (c0_ == '[') return ParseJsonArray();
    261   if (c0_ == 'f') {
    262     if (AdvanceGetChar() == 'a' && AdvanceGetChar() == 'l' &&
    263         AdvanceGetChar() == 's' && AdvanceGetChar() == 'e') {
    264       AdvanceSkipWhitespace();
    265       return factory()->false_value();
    266     }
    267     return ReportUnexpectedCharacter();
    268   }
    269   if (c0_ == 't') {
    270     if (AdvanceGetChar() == 'r' && AdvanceGetChar() == 'u' &&
    271         AdvanceGetChar() == 'e') {
    272       AdvanceSkipWhitespace();
    273       return factory()->true_value();
    274     }
    275     return ReportUnexpectedCharacter();
    276   }
    277   if (c0_ == 'n') {
    278     if (AdvanceGetChar() == 'u' && AdvanceGetChar() == 'l' &&
    279         AdvanceGetChar() == 'l') {
    280       AdvanceSkipWhitespace();
    281       return factory()->null_value();
    282     }
    283     return ReportUnexpectedCharacter();
    284   }
    285   return ReportUnexpectedCharacter();
    286 }
    287 
    288 template <bool seq_one_byte>
    289 ParseElementResult JsonParser<seq_one_byte>::ParseElement(
    290     Handle<JSObject> json_object) {
    291   uint32_t index = 0;
    292   // Maybe an array index, try to parse it.
    293   if (c0_ == '0') {
    294     // With a leading zero, the string has to be "0" only to be an index.
    295     Advance();
    296   } else {
    297     do {
    298       int d = c0_ - '0';
    299       if (index > 429496729U - ((d + 3) >> 3)) break;
    300       index = (index * 10) + d;
    301       Advance();
    302     } while (IsDecimalDigit(c0_));
    303   }
    304 
    305   if (c0_ == '"') {
    306     // Successfully parsed index, parse and store element.
    307     AdvanceSkipWhitespace();
    308 
    309     if (c0_ == ':') {
    310       AdvanceSkipWhitespace();
    311       Handle<Object> value = ParseJsonValue();
    312       if (!value.is_null()) {
    313         JSObject::SetOwnElementIgnoreAttributes(json_object, index, value, NONE)
    314             .Assert();
    315         return kElementFound;
    316       } else {
    317         return kNullHandle;
    318       }
    319     }
    320   }
    321   return kElementNotFound;
    322 }
    323 
    324 // Parse a JSON object. Position must be right at '{'.
    325 template <bool seq_one_byte>
    326 Handle<Object> JsonParser<seq_one_byte>::ParseJsonObject() {
    327   HandleScope scope(isolate());
    328   Handle<JSObject> json_object =
    329       factory()->NewJSObject(object_constructor(), pretenure_);
    330   Handle<Map> map(json_object->map());
    331   int descriptor = 0;
    332   ZoneList<Handle<Object> > properties(8, zone());
    333   DCHECK_EQ(c0_, '{');
    334 
    335   bool transitioning = true;
    336 
    337   AdvanceSkipWhitespace();
    338   if (c0_ != '}') {
    339     do {
    340       if (c0_ != '"') return ReportUnexpectedCharacter();
    341 
    342       int start_position = position_;
    343       Advance();
    344 
    345       if (IsDecimalDigit(c0_)) {
    346         ParseElementResult element_result = ParseElement(json_object);
    347         if (element_result == kNullHandle) return Handle<Object>::null();
    348         if (element_result == kElementFound) continue;
    349       }
    350       // Not an index, fallback to the slow path.
    351 
    352       position_ = start_position;
    353 #ifdef DEBUG
    354       c0_ = '"';
    355 #endif
    356 
    357       Handle<String> key;
    358       Handle<Object> value;
    359 
    360       // Try to follow existing transitions as long as possible. Once we stop
    361       // transitioning, no transition can be found anymore.
    362       DCHECK(transitioning);
    363       // First check whether there is a single expected transition. If so, try
    364       // to parse it first.
    365       bool follow_expected = false;
    366       Handle<Map> target;
    367       if (seq_one_byte) {
    368         key = TransitionArray::ExpectedTransitionKey(map);
    369         follow_expected = !key.is_null() && ParseJsonString(key);
    370       }
    371       // If the expected transition hits, follow it.
    372       if (follow_expected) {
    373         target = TransitionArray::ExpectedTransitionTarget(map);
    374       } else {
    375         // If the expected transition failed, parse an internalized string and
    376         // try to find a matching transition.
    377         key = ParseJsonInternalizedString();
    378         if (key.is_null()) return ReportUnexpectedCharacter();
    379 
    380         target = TransitionArray::FindTransitionToField(map, key);
    381         // If a transition was found, follow it and continue.
    382         transitioning = !target.is_null();
    383       }
    384       if (c0_ != ':') return ReportUnexpectedCharacter();
    385 
    386       AdvanceSkipWhitespace();
    387       value = ParseJsonValue();
    388       if (value.is_null()) return ReportUnexpectedCharacter();
    389 
    390       if (transitioning) {
    391         PropertyDetails details =
    392             target->instance_descriptors()->GetDetails(descriptor);
    393         Representation expected_representation = details.representation();
    394 
    395         if (value->FitsRepresentation(expected_representation)) {
    396           if (expected_representation.IsHeapObject() &&
    397               !target->instance_descriptors()
    398                    ->GetFieldType(descriptor)
    399                    ->NowContains(value)) {
    400             Handle<FieldType> value_type(
    401                 value->OptimalType(isolate(), expected_representation));
    402             Map::GeneralizeField(target, descriptor, details.constness(),
    403                                  expected_representation, value_type);
    404           }
    405           DCHECK(target->instance_descriptors()
    406                      ->GetFieldType(descriptor)
    407                      ->NowContains(value));
    408           properties.Add(value, zone());
    409           map = target;
    410           descriptor++;
    411           continue;
    412         } else {
    413           transitioning = false;
    414         }
    415       }
    416 
    417       DCHECK(!transitioning);
    418 
    419       // Commit the intermediate state to the object and stop transitioning.
    420       CommitStateToJsonObject(json_object, map, &properties);
    421 
    422       JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key, value)
    423           .Check();
    424     } while (transitioning && MatchSkipWhiteSpace(','));
    425 
    426     // If we transitioned until the very end, transition the map now.
    427     if (transitioning) {
    428       CommitStateToJsonObject(json_object, map, &properties);
    429     } else {
    430       while (MatchSkipWhiteSpace(',')) {
    431         HandleScope local_scope(isolate());
    432         if (c0_ != '"') return ReportUnexpectedCharacter();
    433 
    434         int start_position = position_;
    435         Advance();
    436 
    437         if (IsDecimalDigit(c0_)) {
    438           ParseElementResult element_result = ParseElement(json_object);
    439           if (element_result == kNullHandle) return Handle<Object>::null();
    440           if (element_result == kElementFound) continue;
    441         }
    442         // Not an index, fallback to the slow path.
    443 
    444         position_ = start_position;
    445 #ifdef DEBUG
    446         c0_ = '"';
    447 #endif
    448 
    449         Handle<String> key;
    450         Handle<Object> value;
    451 
    452         key = ParseJsonInternalizedString();
    453         if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();
    454 
    455         AdvanceSkipWhitespace();
    456         value = ParseJsonValue();
    457         if (value.is_null()) return ReportUnexpectedCharacter();
    458 
    459         JSObject::DefinePropertyOrElementIgnoreAttributes(json_object, key,
    460                                                           value)
    461             .Check();
    462       }
    463     }
    464 
    465     if (c0_ != '}') {
    466       return ReportUnexpectedCharacter();
    467     }
    468   }
    469   AdvanceSkipWhitespace();
    470   return scope.CloseAndEscape(json_object);
    471 }
    472 
    473 template <bool seq_one_byte>
    474 void JsonParser<seq_one_byte>::CommitStateToJsonObject(
    475     Handle<JSObject> json_object, Handle<Map> map,
    476     ZoneList<Handle<Object> >* properties) {
    477   JSObject::AllocateStorageForMap(json_object, map);
    478   DCHECK(!json_object->map()->is_dictionary_map());
    479 
    480   DisallowHeapAllocation no_gc;
    481   DescriptorArray* descriptors = json_object->map()->instance_descriptors();
    482   int length = properties->length();
    483   for (int i = 0; i < length; i++) {
    484     Handle<Object> value = (*properties)[i];
    485     // Initializing store.
    486     json_object->WriteToField(i, descriptors->GetDetails(i), *value);
    487   }
    488 }
    489 
    490 // Parse a JSON array. Position must be right at '['.
    491 template <bool seq_one_byte>
    492 Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
    493   HandleScope scope(isolate());
    494   ZoneList<Handle<Object> > elements(4, zone());
    495   DCHECK_EQ(c0_, '[');
    496 
    497   AdvanceSkipWhitespace();
    498   if (c0_ != ']') {
    499     do {
    500       Handle<Object> element = ParseJsonValue();
    501       if (element.is_null()) return ReportUnexpectedCharacter();
    502       elements.Add(element, zone());
    503     } while (MatchSkipWhiteSpace(','));
    504     if (c0_ != ']') {
    505       return ReportUnexpectedCharacter();
    506     }
    507   }
    508   AdvanceSkipWhitespace();
    509   // Allocate a fixed array with all the elements.
    510   Handle<FixedArray> fast_elements =
    511       factory()->NewFixedArray(elements.length(), pretenure_);
    512   for (int i = 0, n = elements.length(); i < n; i++) {
    513     fast_elements->set(i, *elements[i]);
    514   }
    515   Handle<Object> json_array = factory()->NewJSArrayWithElements(
    516       fast_elements, FAST_ELEMENTS, pretenure_);
    517   return scope.CloseAndEscape(json_array);
    518 }
    519 
    520 template <bool seq_one_byte>
    521 Handle<Object> JsonParser<seq_one_byte>::ParseJsonNumber() {
    522   bool negative = false;
    523   int beg_pos = position_;
    524   if (c0_ == '-') {
    525     Advance();
    526     negative = true;
    527   }
    528   if (c0_ == '0') {
    529     Advance();
    530     // Prefix zero is only allowed if it's the only digit before
    531     // a decimal point or exponent.
    532     if (IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
    533   } else {
    534     int i = 0;
    535     int digits = 0;
    536     if (c0_ < '1' || c0_ > '9') return ReportUnexpectedCharacter();
    537     do {
    538       i = i * 10 + c0_ - '0';
    539       digits++;
    540       Advance();
    541     } while (IsDecimalDigit(c0_));
    542     if (c0_ != '.' && c0_ != 'e' && c0_ != 'E' && digits < 10) {
    543       SkipWhitespace();
    544       return Handle<Smi>(Smi::FromInt((negative ? -i : i)), isolate());
    545     }
    546   }
    547   if (c0_ == '.') {
    548     Advance();
    549     if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
    550     do {
    551       Advance();
    552     } while (IsDecimalDigit(c0_));
    553   }
    554   if (AsciiAlphaToLower(c0_) == 'e') {
    555     Advance();
    556     if (c0_ == '-' || c0_ == '+') Advance();
    557     if (!IsDecimalDigit(c0_)) return ReportUnexpectedCharacter();
    558     do {
    559       Advance();
    560     } while (IsDecimalDigit(c0_));
    561   }
    562   int length = position_ - beg_pos;
    563   double number;
    564   if (seq_one_byte) {
    565     Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
    566     number = StringToDouble(isolate()->unicode_cache(), chars,
    567                             NO_FLAGS,  // Hex, octal or trailing junk.
    568                             std::numeric_limits<double>::quiet_NaN());
    569   } else {
    570     Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
    571     String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
    572     Vector<const uint8_t> result =
    573         Vector<const uint8_t>(buffer.start(), length);
    574     number = StringToDouble(isolate()->unicode_cache(), result,
    575                             NO_FLAGS,  // Hex, octal or trailing junk.
    576                             0.0);
    577     buffer.Dispose();
    578   }
    579   SkipWhitespace();
    580   return factory()->NewNumber(number, pretenure_);
    581 }
    582 
    583 template <typename StringType>
    584 inline void SeqStringSet(Handle<StringType> seq_str, int i, uc32 c);
    585 
    586 template <>
    587 inline void SeqStringSet(Handle<SeqTwoByteString> seq_str, int i, uc32 c) {
    588   seq_str->SeqTwoByteStringSet(i, c);
    589 }
    590 
    591 template <>
    592 inline void SeqStringSet(Handle<SeqOneByteString> seq_str, int i, uc32 c) {
    593   seq_str->SeqOneByteStringSet(i, c);
    594 }
    595 
    596 template <typename StringType>
    597 inline Handle<StringType> NewRawString(Factory* factory, int length,
    598                                        PretenureFlag pretenure);
    599 
    600 template <>
    601 inline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length,
    602                                              PretenureFlag pretenure) {
    603   return factory->NewRawTwoByteString(length, pretenure).ToHandleChecked();
    604 }
    605 
    606 template <>
    607 inline Handle<SeqOneByteString> NewRawString(Factory* factory, int length,
    608                                              PretenureFlag pretenure) {
    609   return factory->NewRawOneByteString(length, pretenure).ToHandleChecked();
    610 }
    611 
    612 // Scans the rest of a JSON string starting from position_ and writes
    613 // prefix[start..end] along with the scanned characters into a
    614 // sequential string of type StringType.
    615 template <bool seq_one_byte>
    616 template <typename StringType, typename SinkChar>
    617 Handle<String> JsonParser<seq_one_byte>::SlowScanJsonString(
    618     Handle<String> prefix, int start, int end) {
    619   int count = end - start;
    620   int max_length = count + source_length_ - position_;
    621   int length = Min(max_length, Max(kInitialSpecialStringLength, 2 * count));
    622   Handle<StringType> seq_string =
    623       NewRawString<StringType>(factory(), length, pretenure_);
    624   // Copy prefix into seq_str.
    625   SinkChar* dest = seq_string->GetChars();
    626   String::WriteToFlat(*prefix, dest, start, end);
    627 
    628   while (c0_ != '"') {
    629     // Check for control character (0x00-0x1f) or unterminated string (<0).
    630     if (c0_ < 0x20) return Handle<String>::null();
    631     if (count >= length) {
    632       // We need to create a longer sequential string for the result.
    633       return SlowScanJsonString<StringType, SinkChar>(seq_string, 0, count);
    634     }
    635     if (c0_ != '\\') {
    636       // If the sink can contain UC16 characters, or source_ contains only
    637       // Latin1 characters, there's no need to test whether we can store the
    638       // character. Otherwise check whether the UC16 source character can fit
    639       // in the Latin1 sink.
    640       if (sizeof(SinkChar) == kUC16Size || seq_one_byte ||
    641           c0_ <= String::kMaxOneByteCharCode) {
    642         SeqStringSet(seq_string, count++, c0_);
    643         Advance();
    644       } else {
    645         // StringType is SeqOneByteString and we just read a non-Latin1 char.
    646         return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0, count);
    647       }
    648     } else {
    649       Advance();  // Advance past the \.
    650       switch (c0_) {
    651         case '"':
    652         case '\\':
    653         case '/':
    654           SeqStringSet(seq_string, count++, c0_);
    655           break;
    656         case 'b':
    657           SeqStringSet(seq_string, count++, '\x08');
    658           break;
    659         case 'f':
    660           SeqStringSet(seq_string, count++, '\x0c');
    661           break;
    662         case 'n':
    663           SeqStringSet(seq_string, count++, '\x0a');
    664           break;
    665         case 'r':
    666           SeqStringSet(seq_string, count++, '\x0d');
    667           break;
    668         case 't':
    669           SeqStringSet(seq_string, count++, '\x09');
    670           break;
    671         case 'u': {
    672           uc32 value = 0;
    673           for (int i = 0; i < 4; i++) {
    674             Advance();
    675             int digit = HexValue(c0_);
    676             if (digit < 0) {
    677               return Handle<String>::null();
    678             }
    679             value = value * 16 + digit;
    680           }
    681           if (sizeof(SinkChar) == kUC16Size ||
    682               value <= String::kMaxOneByteCharCode) {
    683             SeqStringSet(seq_string, count++, value);
    684             break;
    685           } else {
    686             // StringType is SeqOneByteString and we just read a non-Latin1
    687             // char.
    688             position_ -= 6;  // Rewind position_ to \ in \uxxxx.
    689             Advance();
    690             return SlowScanJsonString<SeqTwoByteString, uc16>(seq_string, 0,
    691                                                               count);
    692           }
    693         }
    694         default:
    695           return Handle<String>::null();
    696       }
    697       Advance();
    698     }
    699   }
    700 
    701   DCHECK_EQ('"', c0_);
    702   // Advance past the last '"'.
    703   AdvanceSkipWhitespace();
    704 
    705   // Shrink seq_string length to count and return.
    706   return SeqString::Truncate(seq_string, count);
    707 }
    708 
    709 template <bool seq_one_byte>
    710 template <bool is_internalized>
    711 Handle<String> JsonParser<seq_one_byte>::ScanJsonString() {
    712   DCHECK_EQ('"', c0_);
    713   Advance();
    714   if (c0_ == '"') {
    715     AdvanceSkipWhitespace();
    716     return factory()->empty_string();
    717   }
    718 
    719   if (seq_one_byte && 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.
    723     uint32_t running_hash = isolate()->heap()->HashSeed();
    724     int position = position_;
    725     uc32 c0 = c0_;
    726     do {
    727       if (c0 == '\\') {
    728         c0_ = c0;
    729         int beg_pos = position_;
    730         position_ = position;
    731         return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
    732                                                              position_);
    733       }
    734       if (c0 < 0x20) return Handle<String>::null();
    735       running_hash = StringHasher::AddCharacterCore(running_hash,
    736                                                     static_cast<uint16_t>(c0));
    737       position++;
    738       if (position >= source_length_) return Handle<String>::null();
    739       c0 = seq_source_->SeqOneByteStringGet(position);
    740     } while (c0 != '"');
    741     int length = position - position_;
    742     uint32_t hash = (length <= String::kMaxHashCalcLength)
    743                         ? StringHasher::GetHashCore(running_hash)
    744                         : static_cast<uint32_t>(length);
    745     Vector<const uint8_t> string_vector(seq_source_->GetChars() + position_,
    746                                         length);
    747     StringTable* string_table = isolate()->heap()->string_table();
    748     uint32_t capacity = string_table->Capacity();
    749     uint32_t entry = StringTable::FirstProbe(hash, capacity);
    750     uint32_t count = 1;
    751     Handle<String> result;
    752     while (true) {
    753       Object* element = string_table->KeyAt(entry);
    754       if (element->IsUndefined(isolate())) {
    755         // Lookup failure.
    756         result =
    757             factory()->InternalizeOneByteString(seq_source_, position_, length);
    758         break;
    759       }
    760       if (!element->IsTheHole(isolate()) &&
    761           String::cast(element)->IsOneByteEqualTo(string_vector)) {
    762         result = Handle<String>(String::cast(element), isolate());
    763 #ifdef DEBUG
    764         uint32_t hash_field =
    765             (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
    766         DCHECK_EQ(static_cast<int>(result->Hash()),
    767                   static_cast<int>(hash_field >> String::kHashShift));
    768 #endif
    769         break;
    770       }
    771       entry = StringTable::NextProbe(entry, count++, capacity);
    772     }
    773     position_ = position;
    774     // Advance past the last '"'.
    775     AdvanceSkipWhitespace();
    776     return result;
    777   }
    778 
    779   int beg_pos = position_;
    780   // Fast case for Latin1 only without escape characters.
    781   do {
    782     // Check for control character (0x00-0x1f) or unterminated string (<0).
    783     if (c0_ < 0x20) return Handle<String>::null();
    784     if (c0_ != '\\') {
    785       if (seq_one_byte || c0_ <= String::kMaxOneByteCharCode) {
    786         Advance();
    787       } else {
    788         return SlowScanJsonString<SeqTwoByteString, uc16>(source_, beg_pos,
    789                                                           position_);
    790       }
    791     } else {
    792       return SlowScanJsonString<SeqOneByteString, uint8_t>(source_, beg_pos,
    793                                                            position_);
    794     }
    795   } while (c0_ != '"');
    796   int length = position_ - beg_pos;
    797   Handle<String> result =
    798       factory()->NewRawOneByteString(length, pretenure_).ToHandleChecked();
    799   uint8_t* dest = SeqOneByteString::cast(*result)->GetChars();
    800   String::WriteToFlat(*source_, dest, beg_pos, position_);
    801 
    802   DCHECK_EQ('"', c0_);
    803   // Advance past the last '"'.
    804   AdvanceSkipWhitespace();
    805   return result;
    806 }
    807 
    808 // Explicit instantiation.
    809 template class JsonParser<true>;
    810 template class JsonParser<false>;
    811 
    812 }  // namespace internal
    813 }  // namespace v8
    814