Coverage Report

Created: 2025-08-03 10:06

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