summaryrefslogtreecommitdiff
path: root/deps/v8/src/json-parser.h
blob: 2d08fefda98cc3db00e5e04f24cd89b53b743681 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// Copyright 2011 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_JSON_PARSER_H_
#define V8_JSON_PARSER_H_

#include "src/factory.h"
#include "src/objects.h"

namespace v8 {
namespace internal {

enum ParseElementResult { kElementFound, kElementNotFound, kNullHandle };

class JsonParseInternalizer BASE_EMBEDDED {
 public:
  static MaybeHandle<Object> Internalize(Isolate* isolate,
                                         Handle<Object> object,
                                         Handle<Object> reviver);

 private:
  JsonParseInternalizer(Isolate* isolate, Handle<JSReceiver> reviver)
      : isolate_(isolate), reviver_(reviver) {}

  MaybeHandle<Object> InternalizeJsonProperty(Handle<JSReceiver> holder,
                                              Handle<String> key);

  bool RecurseAndApply(Handle<JSReceiver> holder, Handle<String> name);

  Isolate* isolate_;
  Handle<JSReceiver> reviver_;
};

// A simple json parser.
template <bool seq_one_byte>
class JsonParser BASE_EMBEDDED {
 public:
  MUST_USE_RESULT static MaybeHandle<Object> Parse(Isolate* isolate,
                                                   Handle<String> source,
                                                   Handle<Object> reviver) {
    Handle<Object> result;
    ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
                               JsonParser(isolate, source).ParseJson(), Object);
    if (reviver->IsCallable()) {
      return JsonParseInternalizer::Internalize(isolate, result, reviver);
    }
    return result;
  }

  static const int kEndOfString = -1;

 private:
  JsonParser(Isolate* isolate, Handle<String> source);

  // Parse a string containing a single JSON value.
  MaybeHandle<Object> ParseJson();

  INLINE(void Advance());

  // The JSON lexical grammar is specified in the ECMAScript 5 standard,
  // section 15.12.1.1. The only allowed whitespace characters between tokens
  // are tab, carriage-return, newline and space.

  INLINE(void AdvanceSkipWhitespace());
  INLINE(void SkipWhitespace());
  INLINE(uc32 AdvanceGetChar());

  // Checks that current charater is c.
  // If so, then consume c and skip whitespace.
  INLINE(bool MatchSkipWhiteSpace(uc32 c));

  // A JSON string (production JSONString) is subset of valid JavaScript string
  // literals. The string must only be double-quoted (not single-quoted), and
  // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and
  // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
  Handle<String> ParseJsonString() {
    return ScanJsonString<false>();
  }

  bool ParseJsonString(Handle<String> expected);

  Handle<String> ParseJsonInternalizedString() {
    Handle<String> result = ScanJsonString<true>();
    if (result.is_null()) return result;
    return factory()->InternalizeString(result);
  }

  template <bool is_internalized>
  Handle<String> ScanJsonString();
  // Creates a new string and copies prefix[start..end] into the beginning
  // of it. Then scans the rest of the string, adding characters after the
  // prefix. Called by ScanJsonString when reaching a '\' or non-Latin1 char.
  template <typename StringType, typename SinkChar>
  Handle<String> SlowScanJsonString(Handle<String> prefix, int start, int end);

  // A JSON number (production JSONNumber) is a subset of the valid JavaScript
  // decimal number literals.
  // It includes an optional minus sign, must have at least one
  // digit before and after a decimal point, may not have prefixed zeros (unless
  // the integer part is zero), and may include an exponent part (e.g., "e-10").
  // Hexadecimal and octal numbers are not allowed.
  Handle<Object> ParseJsonNumber();

  // Parse a single JSON value from input (grammar production JSONValue).
  // A JSON value is either a (double-quoted) string literal, a number literal,
  // one of "true", "false", or "null", or an object or array literal.
  Handle<Object> ParseJsonValue();

  // Parse a JSON object literal (grammar production JSONObject).
  // An object literal is a squiggly-braced and comma separated sequence
  // (possibly empty) of key/value pairs, where the key is a JSON string
  // literal, the value is a JSON value, and the two are separated by a colon.
  // A JSON array doesn't allow numbers and identifiers as keys, like a
  // JavaScript array.
  Handle<Object> ParseJsonObject();

  // Helper for ParseJsonObject. Parses the form "123": obj, which is recorded
  // as an element, not a property.
  ParseElementResult ParseElement(Handle<JSObject> json_object);

  // Parses a JSON array literal (grammar production JSONArray). An array
  // literal is a square-bracketed and comma separated sequence (possibly empty)
  // of JSON values.
  // A JSON array doesn't allow leaving out values from the sequence, nor does
  // it allow a terminal comma, like a JavaScript array does.
  Handle<Object> ParseJsonArray();


  // Mark that a parsing error has happened at the current token, and
  // return a null handle. Primarily for readability.
  inline Handle<Object> ReportUnexpectedCharacter() {
    return Handle<Object>::null();
  }

  inline Isolate* isolate() { return isolate_; }
  inline Factory* factory() { return factory_; }
  inline Handle<JSFunction> object_constructor() { return object_constructor_; }

  static const int kInitialSpecialStringLength = 32;
  static const int kPretenureTreshold = 100 * 1024;

 private:
  Zone* zone() { return &zone_; }

  void CommitStateToJsonObject(Handle<JSObject> json_object, Handle<Map> map,
                               ZoneList<Handle<Object> >* properties);

  Handle<String> source_;
  int source_length_;
  Handle<SeqOneByteString> seq_source_;

  PretenureFlag pretenure_;
  Isolate* isolate_;
  Factory* factory_;
  Zone zone_;
  Handle<JSFunction> object_constructor_;
  uc32 c0_;
  int position_;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_JSON_PARSER_H_