|
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" |
| 3 | +#include <cstdio> |
5 | 4 |
|
6 | 5 | 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 | 6 |
|
15 | 7 | JSONParser::JSONParser() {} |
16 | 8 |
|
17 | 9 | bool JSONParser::Parse(const std::string& content) { |
18 | 10 | DCHECK(!parsed_); |
19 | 11 |
|
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()) { |
| 12 | + json_content_ = content; |
| 13 | + size_t json_length = json_content_.size(); |
| 14 | + json_content_.append(simdjson::SIMDJSON_PADDING, ' '); |
| 15 | + |
| 16 | + simdjson::padded_string_view json_view( |
| 17 | + json_content_.data(), json_length, 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) { |
| 23 | + error_message_ = simdjson::error_message(error); |
| 24 | + // Print error to stderr to match V8 behavior |
| 25 | + std::fprintf(stderr, "JSON Parse error: %s\n", error_message_.c_str()); |
38 | 26 | return false; |
39 | 27 | } |
40 | 28 |
|
41 | | - context_.Reset(isolate, context); |
42 | | - content_.Reset(isolate, result_value.As<Object>()); |
43 | | - parsed_ = true; |
| 29 | + simdjson::ondemand::object obj; |
| 30 | + error = document.get_object().get(obj); |
| 31 | + if (error != simdjson::SUCCESS) { |
| 32 | + error_message_ = simdjson::error_message(error); |
| 33 | + // Print error to stderr to match V8 behavior |
| 34 | + std::fprintf(stderr, "JSON Parse error: %s\n", error_message_.c_str()); |
| 35 | + return false; |
| 36 | + } |
44 | 37 |
|
| 38 | + parsed_ = true; |
45 | 39 | return true; |
46 | 40 | } |
47 | 41 |
|
48 | 42 | std::optional<std::string> JSONParser::GetTopLevelStringField( |
49 | 43 | 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)) { |
| 44 | + if (!parsed_) { |
66 | 45 | return {}; |
67 | 46 | } |
68 | | - if (!content_object->Get(context, field_local).ToLocal(&value) || |
69 | | - !value->IsString()) { |
| 47 | + |
| 48 | + simdjson::padded_string_view json_view( |
| 49 | + json_content_.data(), |
| 50 | + json_content_.size() - simdjson::SIMDJSON_PADDING, |
| 51 | + json_content_.size()); |
| 52 | + |
| 53 | + simdjson::ondemand::document document; |
| 54 | + simdjson::error_code error = parser_.iterate(json_view).get(document); |
| 55 | + if (error != simdjson::SUCCESS) { |
70 | 56 | return {}; |
71 | 57 | } |
72 | | - Utf8Value utf8_value(isolate, value); |
73 | | - return utf8_value.ToString(); |
| 58 | + |
| 59 | + simdjson::ondemand::object obj; |
| 60 | + error = document.get_object().get(obj); |
| 61 | + if (error != simdjson::SUCCESS) { |
| 62 | + return {}; |
| 63 | + } |
| 64 | + |
| 65 | + std::string_view result; |
| 66 | + error = obj[field].get_string().get(result); |
| 67 | + if (error != simdjson::SUCCESS) { |
| 68 | + return {}; |
| 69 | + } |
| 70 | + |
| 71 | + return std::string(result); |
74 | 72 | } |
75 | 73 |
|
76 | 74 | 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)) { |
| 75 | + if (!parsed_) { |
93 | 76 | return {}; |
94 | 77 | } |
95 | | - if (!content_object->Has(context, field_local).To(&has_field)) { |
| 78 | + |
| 79 | + simdjson::padded_string_view json_view( |
| 80 | + json_content_.data(), |
| 81 | + json_content_.size() - simdjson::SIMDJSON_PADDING, |
| 82 | + json_content_.size()); |
| 83 | + |
| 84 | + simdjson::ondemand::document document; |
| 85 | + simdjson::error_code error = parser_.iterate(json_view).get(document); |
| 86 | + if (error != simdjson::SUCCESS) { |
96 | 87 | return {}; |
97 | 88 | } |
98 | | - if (!has_field) { |
| 89 | + |
| 90 | + simdjson::ondemand::object obj; |
| 91 | + error = document.get_object().get(obj); |
| 92 | + if (error != simdjson::SUCCESS) { |
| 93 | + return {}; |
| 94 | + } |
| 95 | + |
| 96 | + simdjson::ondemand::value val; |
| 97 | + error = obj[field].get(val); |
| 98 | + if (error != simdjson::SUCCESS) { |
99 | 99 | return false; |
100 | 100 | } |
101 | | - if (!content_object->Get(context, field_local).ToLocal(&value) || |
102 | | - !value->IsBoolean()) { |
| 101 | + |
| 102 | + bool result; |
| 103 | + error = val.get_bool().get(result); |
| 104 | + if (error != simdjson::SUCCESS) { |
103 | 105 | return {}; |
104 | 106 | } |
105 | | - return value->BooleanValue(isolate); |
| 107 | + |
| 108 | + return result; |
106 | 109 | } |
107 | 110 |
|
108 | 111 | std::optional<JSONParser::StringDict> JSONParser::GetTopLevelStringDict( |
109 | 112 | 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)) { |
| 113 | + if (!parsed_) { |
123 | 114 | return std::nullopt; |
124 | 115 | } |
125 | | - if (!content_object->Has(context, field_local).To(&has_field)) { |
| 116 | + |
| 117 | + simdjson::padded_string_view json_view( |
| 118 | + json_content_.data(), |
| 119 | + json_content_.size() - simdjson::SIMDJSON_PADDING, |
| 120 | + json_content_.size()); |
| 121 | + |
| 122 | + simdjson::ondemand::document document; |
| 123 | + simdjson::error_code error = parser_.iterate(json_view).get(document); |
| 124 | + if (error != simdjson::SUCCESS) { |
126 | 125 | return std::nullopt; |
127 | 126 | } |
128 | | - if (!has_field) { |
129 | | - return StringDict(); |
130 | | - } |
131 | | - if (!content_object->Get(context, field_local).ToLocal(&value) || |
132 | | - !value->IsObject()) { |
| 127 | + |
| 128 | + simdjson::ondemand::object obj; |
| 129 | + error = document.get_object().get(obj); |
| 130 | + if (error != simdjson::SUCCESS) { |
133 | 131 | return std::nullopt; |
134 | 132 | } |
135 | | - Local<Object> dict = value.As<Object>(); |
136 | | - Local<Array> keys; |
137 | | - if (!dict->GetOwnPropertyNames(context).ToLocal(&keys)) { |
| 133 | + |
| 134 | + simdjson::ondemand::value val; |
| 135 | + error = obj[field].get(val); |
| 136 | + if (error != simdjson::SUCCESS) { |
| 137 | + return StringDict(); |
| 138 | + } |
| 139 | + |
| 140 | + simdjson::ondemand::object dict; |
| 141 | + error = val.get_object().get(dict); |
| 142 | + if (error != simdjson::SUCCESS) { |
138 | 143 | return std::nullopt; |
139 | 144 | } |
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()) |
| 145 | + |
| 146 | + StringDict result; |
| 147 | + for (auto field_value : dict) { |
| 148 | + std::string_view key_view; |
| 149 | + error = field_value.unescaped_key().get(key_view); |
| 150 | + if (error != simdjson::SUCCESS) { |
146 | 151 | return StringDict(); |
147 | | - if (!dict->Get(context, key).ToLocal(&value) || !value->IsString()) |
| 152 | + } |
| 153 | + |
| 154 | + std::string_view value_view; |
| 155 | + error = field_value.value().get_string().get(value_view); |
| 156 | + if (error != simdjson::SUCCESS) { |
148 | 157 | return StringDict(); |
| 158 | + } |
149 | 159 |
|
150 | | - Utf8Value key_utf8(isolate, key); |
151 | | - Utf8Value value_utf8(isolate, value); |
152 | | - result.emplace(*key_utf8, *value_utf8); |
| 160 | + result.emplace(std::string(key_view), std::string(value_view)); |
153 | 161 | } |
| 162 | + |
154 | 163 | return result; |
155 | 164 | } |
156 | 165 |
|
|
0 commit comments