Skip to content

Commit

Permalink
Do not panic when trying to assign to a non-addressable reflect value…
Browse files Browse the repository at this point in the history
… (see dop251#78).
  • Loading branch information
dop251 committed Nov 3, 2018
1 parent ef8c030 commit 7239ea9
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
6 changes: 5 additions & 1 deletion object_goreflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func (o *objectGoReflect) getOwnProp(name string) Value {
if v := o._getField(name); v.IsValid() {
return &valueProperty{
value: o.val.runtime.ToValue(v.Interface()),
writable: true,
writable: v.CanSet(),
enumerable: true,
}
}
Expand Down Expand Up @@ -176,6 +176,10 @@ func (o *objectGoReflect) putStr(name string, val Value, throw bool) {
func (o *objectGoReflect) _put(name string, val Value, throw bool) bool {
if o.value.Kind() == reflect.Struct {
if v := o._getField(name); v.IsValid() {
if !v.CanSet() {
o.val.runtime.typeErrorResult(throw, "Cannot assign to a non-addressable or read-only property %s of a host object", name)
return false
}
vv, err := o.val.runtime.toReflectValue(val, v.Type())
if err != nil {
o.val.runtime.typeErrorResult(throw, "Go struct conversion error: %v", err)
Expand Down
45 changes: 45 additions & 0 deletions object_goreflect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,51 @@ func TestNonStructAnonFields(t *testing.T) {
}
}

func TestStructNonAddressable(t *testing.T) {
type S struct {
Field int
}

const SCRIPT = `
"use strict";
if (Object.getOwnPropertyDescriptor(s, "Field").writable) {
throw new Error("Field is writable");
}
if (!Object.getOwnPropertyDescriptor(s1, "Field").writable) {
throw new Error("Field is non-writable");
}
s1.Field = 42;
var result;
try {
s.Field = 42;
result = false;
} catch (e) {
result = e instanceof TypeError;
}
result;
`

var s S
vm := New()
vm.Set("s", s)
vm.Set("s1", &s)
v, err := vm.RunString(SCRIPT)
if err != nil {
t.Fatal(err)
}
if !v.StrictEquals(valueTrue) {
t.Fatalf("Unexpected result: %v", v)
}
if s.Field != 42 {
t.Fatalf("Unexpected s.Field value: %d", s.Field)
}
}

func BenchmarkGoReflectGet(b *testing.B) {
type parent struct {
field, Test1, Test2, Test3, Test4, Test5, Test string
Expand Down

0 comments on commit 7239ea9

Please sign in to comment.