|
1 | 1 | #include "json_parser.h" |
2 | | -#include "node_errors.h" |
3 | | -#include "node_v8_platform-inl.h" |
4 | | -#include "util-inl.h" |
| 2 | +#include "debug_utils.h" |
5 | 3 |
|
6 | 4 | namespace node { |
7 | | -using v8::Array; |
8 | | -using v8::Context; |
9 | | -using v8::Isolate; |
10 | | -using v8::Local; |
11 | | -using v8::Object; |
12 | | -using v8::String; |
13 | | -using v8::Value; |
14 | 5 |
|
15 | 6 | JSONParser::JSONParser() {} |
16 | 7 |
|
17 | 8 | bool JSONParser::Parse(const std::string& content) { |
18 | 9 | DCHECK(!parsed_); |
19 | 10 |
|
20 | | - Isolate* isolate = isolate_.get(); |
21 | | - v8::Locker locker(isolate); |
22 | | - v8::Isolate::Scope isolate_scope(isolate); |
23 | | - v8::HandleScope handle_scope(isolate); |
24 | | - |
25 | | - Local<Context> context = Context::New(isolate); |
26 | | - Context::Scope context_scope(context); |
27 | | - |
28 | | - // It's not a real script, so don't print the source line. |
29 | | - errors::PrinterTryCatch bootstrapCatch( |
30 | | - isolate, errors::PrinterTryCatch::kDontPrintSourceLine); |
31 | | - Local<Value> json_string_value; |
32 | | - Local<Value> result_value; |
33 | | - if (!ToV8Value(context, content).ToLocal(&json_string_value) || |
34 | | - !json_string_value->IsString() || |
35 | | - !v8::JSON::Parse(context, json_string_value.As<String>()) |
36 | | - .ToLocal(&result_value) || |
37 | | - !result_value->IsObject()) { |
| 11 | + json_content_ = content; |
| 12 | + size_t json_length = json_content_.size(); |
| 13 | + json_content_.append(simdjson::SIMDJSON_PADDING, ' '); |
| 14 | + |
| 15 | + simdjson::padded_string_view json_view(json_content_.data(), |
| 16 | + json_length, |
| 17 | + json_content_.size()); |
| 18 | + |
| 19 | + simdjson::ondemand::document document; |
| 20 | + simdjson::error_code error = parser_.iterate(json_view).get(document); |
| 21 | + |
| 22 | + if (error != simdjson::SUCCESS) { |
38 | 23 | return false; |
39 | 24 | } |
40 | 25 |
|
41 | | - context_.Reset(isolate, context); |
42 | | - content_.Reset(isolate, result_value.As<Object>()); |
43 | | - parsed_ = true; |
| 26 | + simdjson::ondemand::object obj; |
| 27 | + error = document.get_object().get(obj); |
| 28 | + if (error != simdjson::SUCCESS) { |
| 29 | + return false; |
| 30 | + } |
44 | 31 |
|
| 32 | + parsed_ = true; |
45 | 33 | return true; |
46 | 34 | } |
47 | 35 |
|
48 | 36 | std::optional<std::string> JSONParser::GetTopLevelStringField( |
49 | 37 | std::string_view field) { |
50 | | - Isolate* isolate = isolate_.get(); |
51 | | - v8::Locker locker(isolate); |
52 | | - v8::Isolate::Scope isolate_scope(isolate); |
53 | | - v8::HandleScope handle_scope(isolate); |
54 | | - |
55 | | - Local<Context> context = context_.Get(isolate); |
56 | | - Context::Scope context_scope(context); |
57 | | - |
58 | | - Local<Object> content_object = content_.Get(isolate); |
59 | | - |
60 | | - Local<Value> value; |
61 | | - // It's not a real script, so don't print the source line. |
62 | | - errors::PrinterTryCatch bootstrapCatch( |
63 | | - isolate, errors::PrinterTryCatch::kDontPrintSourceLine); |
64 | | - Local<Value> field_local; |
65 | | - if (!ToV8Value(context, field, isolate).ToLocal(&field_local)) { |
| 38 | + if (!parsed_) { |
66 | 39 | return {}; |
67 | 40 | } |
68 | | - if (!content_object->Get(context, field_local).ToLocal(&value) || |
69 | | - !value->IsString()) { |
| 41 | + |
| 42 | + simdjson::padded_string_view json_view(json_content_.data(), |
| 43 | + json_content_.size() - simdjson::SIMDJSON_PADDING, |
| 44 | + json_content_.size()); |
| 45 | + |
| 46 | + simdjson::ondemand::document document; |
| 47 | + simdjson::error_code error = parser_.iterate(json_view).get(document); |
| 48 | + if (error != simdjson::SUCCESS) { |
70 | 49 | return {}; |
71 | 50 | } |
72 | | - Utf8Value utf8_value(isolate, value); |
73 | | - return utf8_value.ToString(); |
| 51 | + |
| 52 | + simdjson::ondemand::object obj; |
| 53 | + error = document.get_object().get(obj); |
| 54 | + if (error != simdjson::SUCCESS) { |
| 55 | + return {}; |
| 56 | + } |
| 57 | + |
| 58 | + std::string_view result; |
| 59 | + error = obj[field].get_string().get(result); |
| 60 | + if (error != simdjson::SUCCESS) { |
| 61 | + return {}; |
| 62 | + } |
| 63 | + |
| 64 | + return std::string(result); |
74 | 65 | } |
75 | 66 |
|
76 | 67 | std::optional<bool> JSONParser::GetTopLevelBoolField(std::string_view field) { |
77 | | - Isolate* isolate = isolate_.get(); |
78 | | - v8::Locker locker(isolate); |
79 | | - v8::Isolate::Scope isolate_scope(isolate); |
80 | | - v8::HandleScope handle_scope(isolate); |
81 | | - |
82 | | - Local<Context> context = context_.Get(isolate); |
83 | | - Context::Scope context_scope(context); |
84 | | - |
85 | | - Local<Object> content_object = content_.Get(isolate); |
86 | | - Local<Value> value; |
87 | | - bool has_field; |
88 | | - // It's not a real script, so don't print the source line. |
89 | | - errors::PrinterTryCatch bootstrapCatch( |
90 | | - isolate, errors::PrinterTryCatch::kDontPrintSourceLine); |
91 | | - Local<Value> field_local; |
92 | | - if (!ToV8Value(context, field, isolate).ToLocal(&field_local)) { |
| 68 | + if (!parsed_) { |
93 | 69 | return {}; |
94 | 70 | } |
95 | | - if (!content_object->Has(context, field_local).To(&has_field)) { |
| 71 | + |
| 72 | + simdjson::padded_string_view json_view(json_content_.data(), |
| 73 | + json_content_.size() - simdjson::SIMDJSON_PADDING, |
| 74 | + json_content_.size()); |
| 75 | + |
| 76 | + simdjson::ondemand::document document; |
| 77 | + simdjson::error_code error = parser_.iterate(json_view).get(document); |
| 78 | + if (error != simdjson::SUCCESS) { |
96 | 79 | return {}; |
97 | 80 | } |
98 | | - if (!has_field) { |
| 81 | + |
| 82 | + simdjson::ondemand::object obj; |
| 83 | + error = document.get_object().get(obj); |
| 84 | + if (error != simdjson::SUCCESS) { |
| 85 | + return {}; |
| 86 | + } |
| 87 | + |
| 88 | + simdjson::ondemand::value val; |
| 89 | + error = obj[field].get(val); |
| 90 | + if (error != simdjson::SUCCESS) { |
99 | 91 | return false; |
100 | 92 | } |
101 | | - if (!content_object->Get(context, field_local).ToLocal(&value) || |
102 | | - !value->IsBoolean()) { |
| 93 | + |
| 94 | + bool result; |
| 95 | + error = val.get_bool().get(result); |
| 96 | + if (error != simdjson::SUCCESS) { |
103 | 97 | return {}; |
104 | 98 | } |
105 | | - return value->BooleanValue(isolate); |
| 99 | + |
| 100 | + return result; |
106 | 101 | } |
107 | 102 |
|
108 | 103 | std::optional<JSONParser::StringDict> JSONParser::GetTopLevelStringDict( |
109 | 104 | std::string_view field) { |
110 | | - Isolate* isolate = isolate_.get(); |
111 | | - v8::Locker locker(isolate); |
112 | | - v8::Isolate::Scope isolate_scope(isolate); |
113 | | - v8::HandleScope handle_scope(isolate); |
114 | | - Local<Context> context = context_.Get(isolate); |
115 | | - Local<Object> content_object = content_.Get(isolate); |
116 | | - Local<Value> value; |
117 | | - bool has_field; |
118 | | - // It's not a real script, so don't print the source line. |
119 | | - errors::PrinterTryCatch bootstrapCatch( |
120 | | - isolate, errors::PrinterTryCatch::kDontPrintSourceLine); |
121 | | - Local<Value> field_local; |
122 | | - if (!ToV8Value(context, field, isolate).ToLocal(&field_local)) { |
| 105 | + if (!parsed_) { |
123 | 106 | return std::nullopt; |
124 | 107 | } |
125 | | - if (!content_object->Has(context, field_local).To(&has_field)) { |
| 108 | + |
| 109 | + simdjson::padded_string_view json_view(json_content_.data(), |
| 110 | + json_content_.size() - simdjson::SIMDJSON_PADDING, |
| 111 | + json_content_.size()); |
| 112 | + |
| 113 | + simdjson::ondemand::document document; |
| 114 | + simdjson::error_code error = parser_.iterate(json_view).get(document); |
| 115 | + if (error != simdjson::SUCCESS) { |
126 | 116 | return std::nullopt; |
127 | 117 | } |
128 | | - if (!has_field) { |
129 | | - return StringDict(); |
130 | | - } |
131 | | - if (!content_object->Get(context, field_local).ToLocal(&value) || |
132 | | - !value->IsObject()) { |
| 118 | + |
| 119 | + simdjson::ondemand::object obj; |
| 120 | + error = document.get_object().get(obj); |
| 121 | + if (error != simdjson::SUCCESS) { |
133 | 122 | return std::nullopt; |
134 | 123 | } |
135 | | - Local<Object> dict = value.As<Object>(); |
136 | | - Local<Array> keys; |
137 | | - if (!dict->GetOwnPropertyNames(context).ToLocal(&keys)) { |
| 124 | + |
| 125 | + simdjson::ondemand::value val; |
| 126 | + error = obj[field].get(val); |
| 127 | + if (error != simdjson::SUCCESS) { |
| 128 | + return StringDict(); |
| 129 | + } |
| 130 | + |
| 131 | + simdjson::ondemand::object dict; |
| 132 | + error = val.get_object().get(dict); |
| 133 | + if (error != simdjson::SUCCESS) { |
138 | 134 | return std::nullopt; |
139 | 135 | } |
140 | | - std::unordered_map<std::string, std::string> result; |
141 | | - uint32_t length = keys->Length(); |
142 | | - for (uint32_t i = 0; i < length; ++i) { |
143 | | - Local<Value> key; |
144 | | - Local<Value> value; |
145 | | - if (!keys->Get(context, i).ToLocal(&key) || !key->IsString()) |
| 136 | + |
| 137 | + StringDict result; |
| 138 | + for (auto field_value : dict) { |
| 139 | + std::string_view key_view; |
| 140 | + error = field_value.unescaped_key().get(key_view); |
| 141 | + if (error != simdjson::SUCCESS) { |
146 | 142 | return StringDict(); |
147 | | - if (!dict->Get(context, key).ToLocal(&value) || !value->IsString()) |
| 143 | + } |
| 144 | + |
| 145 | + std::string_view value_view; |
| 146 | + error = field_value.value().get_string().get(value_view); |
| 147 | + if (error != simdjson::SUCCESS) { |
148 | 148 | return StringDict(); |
| 149 | + } |
149 | 150 |
|
150 | | - Utf8Value key_utf8(isolate, key); |
151 | | - Utf8Value value_utf8(isolate, value); |
152 | | - result.emplace(*key_utf8, *value_utf8); |
| 151 | + result.emplace(std::string(key_view), std::string(value_view)); |
153 | 152 | } |
| 153 | + |
154 | 154 | return result; |
155 | 155 | } |
156 | 156 |
|
|
0 commit comments