Skip to content

Commit 19ec71c

Browse files
Implement set, get internal fields, & set internal field count (#145)
Co-authored-by: Dylan Thacker-Smith <[email protected]>
1 parent f75f288 commit 19ec71c

File tree

7 files changed

+160
-0
lines changed

7 files changed

+160
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
- Undefined, Null functions to get these constant values for the isolate
1515
- Support for calling a method on an object.
1616
- Support for calling `IsExecutionTerminating` on isolate to check if execution is still terminating.
17+
- Support for setting and getting internal fields for template object instances
1718

1819
### Changed
1920
- Removed error return value from NewIsolate which never fails

helpers_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,11 @@ func fatalIf(t *testing.T, err error) {
88
t.Fatal(err)
99
}
1010
}
11+
12+
func recoverPanic(f func()) (recovered interface{}) {
13+
defer func() {
14+
recovered = recover()
15+
}()
16+
f()
17+
return nil
18+
}

object.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,34 @@ func (o *Object) SetIdx(idx uint32, val interface{}) error {
8080
}
8181

8282
C.ObjectSetIdx(o.ptr, C.uint32_t(idx), value.ptr)
83+
8384
return nil
8485
}
8586

87+
// SetInternalField sets the value of an internal field for an ObjectTemplate instance.
88+
// Panics if the index isn't in the range set by (*ObjectTemplate).SetInternalFieldCount.
89+
func (o *Object) SetInternalField(idx uint32, val interface{}) error {
90+
value, err := coerceValue(o.ctx.iso, val)
91+
92+
if err != nil {
93+
return err
94+
}
95+
96+
inserted := C.ObjectSetInternalField(o.ptr, C.uint32_t(idx), value.ptr)
97+
98+
if inserted == 0 {
99+
panic(fmt.Errorf("index out of range [%v] with length %v", idx, o.InternalFieldCount()))
100+
}
101+
102+
return nil
103+
}
104+
105+
// InternalFieldCount returns the number of internal fields this Object has.
106+
func (o *Object) InternalFieldCount() uint32 {
107+
count := C.ObjectInternalFieldCount(o.ptr)
108+
return uint32(count)
109+
}
110+
86111
// Get tries to get a Value for a given Object property key.
87112
func (o *Object) Get(key string) (*Value, error) {
88113
ckey := C.CString(key)
@@ -92,6 +117,18 @@ func (o *Object) Get(key string) (*Value, error) {
92117
return valueResult(o.ctx, rtn)
93118
}
94119

120+
// GetInternalField gets the Value set by SetInternalField for the given index
121+
// or the JS undefined value if the index hadn't been set.
122+
// Panics if given an out of range index.
123+
func (o *Object) GetInternalField(idx uint32) *Value {
124+
rtn := C.ObjectGetInternalField(o.ptr, C.uint32_t(idx))
125+
if rtn == nil {
126+
panic(fmt.Errorf("index out of range [%v] with length %v", idx, o.InternalFieldCount()))
127+
}
128+
return &Value{rtn, o.ctx}
129+
130+
}
131+
95132
// GetIdx tries to get a Value at a give Object index.
96133
func (o *Object) GetIdx(idx uint32) (*Value, error) {
97134
rtn := C.ObjectGetIdx(o.ptr, C.uint32_t(idx))

object_template.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,18 @@ func (o *ObjectTemplate) NewInstance(ctx *Context) (*Object, error) {
6060
return objectResult(ctx, rtn)
6161
}
6262

63+
// SetInternalFieldCount sets the number of internal fields that instances of this
64+
// template will have.
65+
func (o *ObjectTemplate) SetInternalFieldCount(fieldCount uint32) {
66+
C.ObjectTemplateSetInternalFieldCount(o.ptr, C.uint32_t(fieldCount))
67+
}
68+
69+
// InternalFieldCount returns the number of internal fields that instances of this
70+
// template will have.
71+
func (o *ObjectTemplate) InternalFieldCount() uint32 {
72+
return uint32(C.ObjectTemplateInternalFieldCount(o.ptr))
73+
}
74+
6375
func (o *ObjectTemplate) apply(opts *contextOptions) {
6476
opts.gTmpl = o
6577
}

object_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,53 @@ func TestObjectSet(t *testing.T) {
7373
}
7474
}
7575

76+
func TestObjectInternalFields(t *testing.T) {
77+
iso := v8.NewIsolate()
78+
defer iso.Dispose()
79+
ctx := v8.NewContext(iso)
80+
defer ctx.Close()
81+
82+
tmpl := v8.NewObjectTemplate(iso)
83+
obj, err := tmpl.NewInstance(ctx)
84+
fatalIf(t, err)
85+
if count := obj.InternalFieldCount(); count != 0 {
86+
t.Errorf("expected 0 got %v", count)
87+
}
88+
if recoverPanic(func() { obj.GetInternalField(0) }) == nil {
89+
t.Error("expected panic")
90+
}
91+
92+
tmpl = v8.NewObjectTemplate(iso)
93+
tmpl.SetInternalFieldCount(1)
94+
if count := tmpl.InternalFieldCount(); count != 1 {
95+
t.Errorf("expected 1 got %v", count)
96+
}
97+
98+
obj, err = tmpl.NewInstance(ctx)
99+
fatalIf(t, err)
100+
if count := obj.InternalFieldCount(); count != 1 {
101+
t.Errorf("expected 1 got %v", count)
102+
}
103+
104+
if v := obj.GetInternalField(0); !v.SameValue(v8.Undefined(iso)) {
105+
t.Errorf("unexpected value: %q", v)
106+
}
107+
108+
if err := obj.SetInternalField(0, t); err == nil {
109+
t.Error("expected unsupported value error")
110+
}
111+
112+
err = obj.SetInternalField(0, "baz")
113+
fatalIf(t, err)
114+
if v := obj.GetInternalField(0); v.String() != "baz" {
115+
t.Errorf("unexpected value: %q", v)
116+
}
117+
118+
if recoverPanic(func() { obj.SetInternalField(1, "baz") }) == nil {
119+
t.Error("expected panic from index out of bounds")
120+
}
121+
}
122+
76123
func TestObjectGet(t *testing.T) {
77124
t.Parallel()
78125

v8go.cc

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,20 @@ RtnValue ObjectTemplateNewInstance(TemplatePtr ptr, ContextPtr ctx) {
277277
return rtn;
278278
}
279279

280+
void ObjectTemplateSetInternalFieldCount(TemplatePtr ptr, uint32_t field_count) {
281+
LOCAL_TEMPLATE(ptr);
282+
283+
Local<ObjectTemplate> obj_tmpl = tmpl.As<ObjectTemplate>();
284+
obj_tmpl->SetInternalFieldCount(field_count);
285+
}
286+
287+
int ObjectTemplateInternalFieldCount(TemplatePtr ptr) {
288+
LOCAL_TEMPLATE(ptr);
289+
290+
Local<ObjectTemplate> obj_tmpl = tmpl.As<ObjectTemplate>();
291+
return obj_tmpl->InternalFieldCount();
292+
}
293+
280294
/********** FunctionTemplate **********/
281295

282296
static void FunctionTemplateCallback(const FunctionCallbackInfo<Value>& info) {
@@ -1048,6 +1062,24 @@ void ObjectSetIdx(ValuePtr ptr, uint32_t idx, ValuePtr prop_val) {
10481062
obj->Set(local_ctx, idx, prop_val->ptr.Get(iso)).Check();
10491063
}
10501064

1065+
int ObjectSetInternalField(ValuePtr ptr, uint32_t idx, ValuePtr val_ptr) {
1066+
LOCAL_OBJECT(ptr);
1067+
m_value* prop_val = static_cast<m_value*>(val_ptr);
1068+
1069+
if (idx >= obj->InternalFieldCount()) {
1070+
return 0;
1071+
}
1072+
1073+
obj->SetInternalField(idx, prop_val->ptr.Get(iso));
1074+
1075+
return 1;
1076+
}
1077+
1078+
int ObjectInternalFieldCount(ValuePtr ptr) {
1079+
LOCAL_OBJECT(ptr);
1080+
return obj->InternalFieldCount();
1081+
}
1082+
10511083
RtnValue ObjectGet(ValuePtr ptr, const char* key) {
10521084
LOCAL_OBJECT(ptr);
10531085
RtnValue rtn = {nullptr, nullptr};
@@ -1073,6 +1105,24 @@ RtnValue ObjectGet(ValuePtr ptr, const char* key) {
10731105
return rtn;
10741106
}
10751107

1108+
ValuePtr ObjectGetInternalField(ValuePtr ptr, uint32_t idx) {
1109+
LOCAL_OBJECT(ptr);
1110+
1111+
if (idx >= obj->InternalFieldCount()) {
1112+
return nullptr;
1113+
}
1114+
1115+
Local<Value> result = obj->GetInternalField(idx);
1116+
1117+
m_value* new_val = new m_value;
1118+
new_val->iso = iso;
1119+
new_val->ctx = ctx;
1120+
new_val->ptr = Persistent<Value, CopyablePersistentTraits<Value>>(
1121+
iso, result);
1122+
1123+
return tracked_value(ctx, new_val);
1124+
}
1125+
10761126
RtnValue ObjectGetIdx(ValuePtr ptr, uint32_t idx) {
10771127
LOCAL_OBJECT(ptr);
10781128
RtnValue rtn = {nullptr, nullptr};

v8go.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ extern void TemplateSetTemplate(TemplatePtr ptr,
9797

9898
extern TemplatePtr NewObjectTemplate(IsolatePtr iso_ptr);
9999
extern RtnValue ObjectTemplateNewInstance(TemplatePtr ptr, ContextPtr ctx_ptr);
100+
extern void ObjectTemplateSetInternalFieldCount(TemplatePtr ptr, uint32_t field_count);
101+
extern int ObjectTemplateInternalFieldCount(TemplatePtr ptr);
100102

101103
extern TemplatePtr NewFunctionTemplate(IsolatePtr iso_ptr, int callback_ref);
102104
extern RtnValue FunctionTemplateGetFunction(TemplatePtr ptr,
@@ -183,8 +185,11 @@ int ValueIsModuleNamespaceObject(ValuePtr ptr);
183185

184186
extern void ObjectSet(ValuePtr ptr, const char* key, ValuePtr val_ptr);
185187
extern void ObjectSetIdx(ValuePtr ptr, uint32_t idx, ValuePtr val_ptr);
188+
extern int ObjectSetInternalField(ValuePtr ptr, uint32_t idx, ValuePtr val_ptr);
189+
extern int ObjectInternalFieldCount(ValuePtr ptr);
186190
extern RtnValue ObjectGet(ValuePtr ptr, const char* key);
187191
extern RtnValue ObjectGetIdx(ValuePtr ptr, uint32_t idx);
192+
extern ValuePtr ObjectGetInternalField(ValuePtr ptr, uint32_t idx);
188193
int ObjectHas(ValuePtr ptr, const char* key);
189194
int ObjectHasIdx(ValuePtr ptr, uint32_t idx);
190195
int ObjectDelete(ValuePtr ptr, const char* key);

0 commit comments

Comments
 (0)