• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hanazuki / node-jsonnet / 26997076302

05 Jun 2026 05:21AM UTC coverage: 68.149% (-0.2%) from 68.343%
26997076302

Pull #449

github

web-flow
Merge 3ddb775be into f13e4686e
Pull Request #449: reject circular objects from native functions

371 of 756 branches covered (49.07%)

Branch coverage included in aggregate %.

15 of 16 new or added lines in 1 file covered. (93.75%)

579 of 638 relevant lines covered (90.75%)

228.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.62
/src/JsonValueConverter.cpp
1
// SPDX-License-Identifier: MIT
2
#include "JsonValueConverter.hpp"
3
#include <algorithm>
4
#include <memory>
5
#include <utility>
6

7
namespace nodejsonnet {
8

9
  JsonValueConverter::JsonValueConverter(std::shared_ptr<JsonnetVm> vm): vm{std::move(vm)} {
212✔
10
  }
212✔
11

12
  Napi::Value JsonValueConverter::toNapiValue(
80✔
13
    Napi::Env const &env, JsonnetJsonValue const *json) const {
14
    if(vm->extractJsonNull(json)) {
80✔
15
      return env.Null();
4✔
16
    }
17
    if(auto const b = vm->extractJsonBool(json)) {
84✔
18
      return Napi::Boolean::New(env, *b);
8✔
19
    }
20
    if(auto const n = vm->extractJsonNumber(json)) {
104✔
21
      return Napi::Number::New(env, *n);
36✔
22
    }
23
    if(auto const s = vm->extractJsonString(json)) {
64!
24
      return Napi::String::New(env, s->data(), s->size());
32✔
25
    }
26

27
    // NOTREACHED
28
    // Native extensions can only take primitives
29
    return env.Undefined();
×
30
  }
80✔
31

32
  JsonnetJsonValue *JsonValueConverter::toJsonnetJson(Napi::Value v) const {
96✔
33
    std::vector<Napi::Object> ancestors;
96✔
34
    return toJsonnetJsonImpl(v, ancestors);
96✔
35
  }
96✔
36

37
  JsonnetJsonValue *JsonValueConverter::toJsonnetJsonImpl(
156✔
38
    Napi::Value v, std::vector<Napi::Object> &ancestors) const {
39
    if(v.IsBoolean()) {
156✔
40
      return vm->makeJsonBool(v.As<Napi::Boolean>());
12✔
41
    }
42
    if(v.IsNumber()) {
144✔
43
      return vm->makeJsonNumber(v.As<Napi::Number>());
56✔
44
    }
45
    if(v.IsString()) {
88✔
46
      return vm->makeJsonString(v.As<Napi::String>());
28!
47
    }
48
    if(v.IsDate()) {
68✔
49
      auto const toISOString = v.As<Napi::Object>().Get("toISOString").As<Napi::Function>();
4✔
50
      return vm->makeJsonString(toISOString.Call(v, {}).As<Napi::String>());
4!
51
    }
4✔
52
    if(v.IsFunction() || v.IsSymbol()) {
64✔
53
      return vm->makeJsonNull();
12✔
54
    }
55
    if(v.IsArray()) {
52✔
56
      auto const array = v.As<Napi::Array>();
8✔
57
      if(std::any_of(ancestors.begin(), ancestors.end(),
16!
58
           [&](auto const &a) { return a.StrictEquals(array); })) {
8✔
NEW
59
        throw Napi::TypeError::New(array.Env(), "Converting circular structure to JSON");
×
60
      }
61
      ancestors.push_back(array);
8✔
62
      auto const json = vm->makeJsonArray();
8✔
63
      for(size_t i = 0, len = array.Length(); i < len; ++i) {
24✔
64
        vm->appendJsonArray(json, toJsonnetJsonImpl(array[i], ancestors));
16✔
65
      }
16✔
66
      ancestors.pop_back();
8✔
67
      return json;
8✔
68
    }
8✔
69
    if(v.IsObject()) {
44✔
70
      auto const object = v.As<Napi::Object>();
40✔
71
      if(std::any_of(ancestors.begin(), ancestors.end(),
80✔
72
           [&](auto const &a) { return a.StrictEquals(object); })) {
68✔
73
        throw Napi::TypeError::New(object.Env(), "Converting circular structure to JSON");
4!
74
      }
75
      ancestors.push_back(object);
36✔
76
      auto const json = vm->makeJsonObject();
36✔
77
      auto const props = object.GetPropertyNames();
36✔
78
      for(size_t i = 0, len = props.Length(); i < len; ++i) {
84✔
79
        auto const prop = props[i].ToString();
48✔
80
        if(object.HasOwnProperty(prop)) {
48!
81
          vm->appendJsonObject(json, prop, toJsonnetJsonImpl(object.Get(prop), ancestors));
48!
82
        }
44✔
83
      }
48✔
84
      ancestors.pop_back();
32✔
85
      return json;
32✔
86
    }
40✔
87
    return vm->makeJsonNull();
4✔
88
  }
156✔
89

90
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc