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