Coverage Report

Created: 2025-10-31 09:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/src/inspector/node_json.cc
Line
Count
Source
1
#include "node_json.h"
2
3
#include "crdtp/json.h"
4
5
namespace node {
6
namespace inspector {
7
8
using crdtp::ParserHandler;
9
using crdtp::span;
10
using crdtp::Status;
11
using protocol::Binary;
12
using protocol::BinaryValue;
13
using protocol::DictionaryValue;
14
using protocol::FundamentalValue;
15
using protocol::ListValue;
16
using protocol::String;
17
using protocol::StringUtil;
18
using protocol::StringValue;
19
using protocol::Value;
20
21
namespace {
22
23
// Uses the parsing events received from driver of `ParserHandler`
24
// (e.g. crdtp::json::ParseJSON) into a protocol::Value instance.
25
class ValueParserHandler : public ParserHandler {
26
 public:
27
  // Provides the parsed protocol::Value.
28
0
  std::unique_ptr<Value> ReleaseRoot() { return std::move(root_); }
29
30
  // The first parsing error encountered; `status().ok()` is the default.
31
0
  Status status() const { return status_; }
32
33
 private:
34
  // Implementation of `ParserHandler`.
35
0
  void HandleMapBegin() override {
36
0
    if (!status_.ok()) return;
37
0
    std::unique_ptr<DictionaryValue> dict = DictionaryValue::create();
38
0
    DictionaryValue* dict_ptr = dict.get();
39
0
    AddValueToParent(std::move(dict));
40
0
    stack_.emplace_back(dict_ptr);
41
0
  }
42
43
0
  void HandleMapEnd() override {
44
0
    if (!status_.ok()) return;
45
0
    DCHECK(!stack_.empty());
46
0
    DCHECK(stack_.back().is_dict);
47
0
    stack_.pop_back();
48
0
  }
49
50
0
  void HandleArrayBegin() override {
51
0
    if (!status_.ok()) return;
52
0
    std::unique_ptr<ListValue> list = ListValue::create();
53
0
    ListValue* list_ptr = list.get();
54
0
    AddValueToParent(std::move(list));
55
0
    stack_.emplace_back(list_ptr);
56
0
  }
57
58
0
  void HandleArrayEnd() override {
59
0
    if (!status_.ok()) return;
60
0
    DCHECK(!stack_.empty());
61
0
    DCHECK(!stack_.back().is_dict);
62
0
    stack_.pop_back();
63
0
  }
64
65
0
  void HandleString8(span<uint8_t> chars) override {
66
0
    AddStringToParent(StringUtil::fromUTF8(chars.data(), chars.size()));
67
0
  }
68
69
0
  void HandleString16(span<uint16_t> chars) override {
70
0
    AddStringToParent(StringUtil::fromUTF16(chars.data(), chars.size()));
71
0
  }
72
73
0
  void HandleBinary(span<uint8_t> bytes) override {
74
0
    AddValueToParent(
75
0
        BinaryValue::create(Binary::fromSpan(bytes.data(), bytes.size())));
76
0
  }
77
78
0
  void HandleDouble(double value) override {
79
0
    AddValueToParent(FundamentalValue::create(value));
80
0
  }
81
82
0
  void HandleInt32(int32_t value) override {
83
0
    AddValueToParent(FundamentalValue::create(value));
84
0
  }
85
86
0
  void HandleBool(bool value) override {
87
0
    AddValueToParent(FundamentalValue::create(value));
88
0
  }
89
90
0
  void HandleNull() override { AddValueToParent(Value::null()); }
91
92
0
  void HandleError(Status error) override { status_ = error; }
93
94
  // Adding strings and values to the parent value.
95
  // Strings are handled separately because they can be keys for
96
  // dictionary values.
97
0
  void AddStringToParent(String str) {
98
0
    if (!status_.ok()) return;
99
0
    if (!root_) {
100
0
      DCHECK(!key_is_pending_);
101
0
      root_ = StringValue::create(str);
102
0
    } else if (stack_.back().is_dict) {
103
      // If we already have a pending key, then this is the value of the
104
      // key/value pair. Otherwise, it's the new pending key.
105
0
      if (key_is_pending_) {
106
0
        stack_.back().dict->setString(pending_key_, str);
107
0
        key_is_pending_ = false;
108
0
      } else {
109
0
        pending_key_ = std::move(str);
110
0
        key_is_pending_ = true;
111
0
      }
112
0
    } else {  // Top of the stack is a list.
113
0
      DCHECK(!key_is_pending_);
114
0
      stack_.back().list->pushValue(StringValue::create(str));
115
0
    }
116
0
  }
117
118
0
  void AddValueToParent(std::unique_ptr<Value> value) {
119
0
    if (!status_.ok()) return;
120
0
    if (!root_) {
121
0
      DCHECK(!key_is_pending_);
122
0
      root_ = std::move(value);
123
0
    } else if (stack_.back().is_dict) {
124
0
      DCHECK(key_is_pending_);
125
0
      stack_.back().dict->setValue(pending_key_, std::move(value));
126
0
      key_is_pending_ = false;
127
0
    } else {  // Top of the stack is a list.
128
0
      DCHECK(!key_is_pending_);
129
0
      stack_.back().list->pushValue(std::move(value));
130
0
    }
131
0
  }
132
133
  // `status_.ok()` is the default; if we receive an error event
134
  // we keep the first one and stop modifying any other state.
135
  Status status_;
136
137
  // The root of the parsed protocol::Value tree.
138
  std::unique_ptr<Value> root_;
139
140
  // If root_ is a list or a dictionary, this stack keeps track of
141
  // the container we're currently parsing as well as its ancestors.
142
  struct ContainerState {
143
    explicit ContainerState(DictionaryValue* dict)
144
0
        : is_dict(true), dict(dict) {}
145
0
    explicit ContainerState(ListValue* list) : is_dict(false), list(list) {}
146
147
    bool is_dict;
148
    union {
149
      DictionaryValue* dict;
150
      ListValue* list;
151
    };
152
  };
153
  std::vector<ContainerState> stack_;
154
155
  // For maps, keys and values are alternating events, so we keep the
156
  // key around and process it when the value arrives.
157
  bool key_is_pending_ = false;
158
  String pending_key_;
159
};
160
}  // anonymous namespace
161
162
0
std::unique_ptr<Value> JsonUtil::ParseJSON(const uint8_t* chars, size_t size) {
163
0
  ValueParserHandler handler;
164
0
  crdtp::json::ParseJSON(span<uint8_t>(chars, size), &handler);
165
0
  if (handler.status().ok()) return handler.ReleaseRoot();
166
0
  return nullptr;
167
0
}
168
169
0
std::unique_ptr<Value> JsonUtil::ParseJSON(const uint16_t* chars, size_t size) {
170
0
  ValueParserHandler handler;
171
0
  crdtp::json::ParseJSON(span<uint16_t>(chars, size), &handler);
172
0
  if (handler.status().ok()) return handler.ReleaseRoot();
173
0
  return nullptr;
174
0
}
175
176
0
std::unique_ptr<Value> JsonUtil::parseJSON(const std::string_view string) {
177
0
  if (string.empty()) return nullptr;
178
179
0
  return ParseJSON(reinterpret_cast<const uint8_t*>(string.data()),
180
0
                   string.size());
181
0
}
182
183
0
std::unique_ptr<Value> JsonUtil::parseJSON(v8_inspector::StringView string) {
184
0
  if (string.length() == 0) return nullptr;
185
0
  if (string.is8Bit()) return ParseJSON(string.characters8(), string.length());
186
0
  return ParseJSON(string.characters16(), string.length());
187
0
}
188
189
}  // namespace inspector
190
}  // namespace node