123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- package goja
- import (
- "testing"
- )
- func TestGoReflectArray(t *testing.T) {
- vm := New()
- vm.Set("a", [...]int{1, 2, 3})
- _, err := vm.RunString(`
- if (!Array.isArray(a)) {
- throw new Error("isArray() returned false");
- }
- if (a[0] !== 1 || a[1] !== 2 || a[2] !== 3) {
- throw new Error("Array contents is incorrect");
- }
- if (!a.hasOwnProperty("length")) {
- throw new Error("hasOwnProperty() returned false");
- }
- let desc = Object.getOwnPropertyDescriptor(a, "length");
- if (desc.value !== 3 || desc.writable || desc.enumerable || desc.configurable) {
- throw new Error("incorrect property descriptor: " + JSON.stringify(desc));
- }
- `)
- if err != nil {
- t.Fatal(err)
- }
- }
- func TestGoReflectArraySort(t *testing.T) {
- vm := New()
- vm.Set("a", [...]int{3, 1, 2})
- v, err := vm.RunString(`
- a.sort();
- if (a[0] !== 1 || a[1] !== 2 || a[2] !== 3) {
- throw new Error(a.toString());
- }
- a;
- `)
- if err != nil {
- t.Fatal(err)
- }
- res := v.Export()
- if a, ok := res.([3]int); ok {
- if a[0] != 1 || a[1] != 2 || a[2] != 3 {
- t.Fatal(a)
- }
- } else {
- t.Fatalf("Wrong type: %T", res)
- }
- }
- func TestGoReflectArrayCopyOnChange(t *testing.T) {
- vm := New()
- v, err := vm.RunString(`
- a => {
- let tmp = a[0];
- if (tmp !== a[0]) {
- throw new Error("tmp !== a[0]");
- }
- a[0] = a[1];
- if (tmp === a[0]) {
- throw new Error("tmp === a[0]");
- }
- if (tmp.Test !== "1") {
- throw new Error("tmp.Test: " + tmp.Test + " (" + typeof tmp.Test + ")");
- }
- if (a[0].Test !== "2") {
- throw new Error("a[0].Test: " + a[0].Test);
- }
- a[0].Test = "3";
- if (a[0].Test !== "3") {
- throw new Error("a[0].Test (1): " + a[0].Test);
- }
- tmp = a[0];
- tmp.Test = "4";
- if (a[0].Test !== "4") {
- throw new Error("a[0].Test (2): " + a[0].Test);
- }
- delete a[0];
- if (a[0] && a[0].Test !== "") {
- throw new Error("a[0].Test (3): " + a[0].Test);
- }
- if (tmp.Test !== "4") {
- throw new Error("tmp.Test (1): " + tmp.Test);
- }
- a[1] = tmp;
- if (a[1].Test !== "4") {
- throw new Error("a[1].Test: " + a[1].Test);
- }
- // grow
- tmp = a[1];
- a.push(null);
- if (a.length !== 3) {
- throw new Error("a.length after push: " + a.length);
- }
- tmp.Test = "5";
- if (a[1].Test !== "5") {
- throw new Error("a[1].Test (1): " + a[1].Test);
- }
- // shrink
- a.length = 1;
- if (a.length !== 1) {
- throw new Error("a.length after shrink: " + a.length);
- }
- if (tmp.Test !== "5") {
- throw new Error("tmp.Test (shrink): " + tmp.Test);
- }
- }
- `)
- if err != nil {
- t.Fatal(err)
- }
- fn, ok := AssertFunction(v)
- if !ok {
- t.Fatal("Not a function")
- }
- t.Run("[]struct", func(t *testing.T) {
- a := []struct {
- Test string
- }{{"1"}, {"2"}}
- _, err := fn(nil, vm.ToValue(a))
- if err != nil {
- t.Fatal(err)
- }
- if a[0].Test != "" {
- t.Fatalf("a[0]: %#v", a[0])
- }
- if a[1].Test != "4" {
- t.Fatalf("a0[1]: %#v", a[1])
- }
- })
- // The copy-on-change mechanism doesn't apply to the types below because the contained values are references.
- // These tests are here for completeness and to prove that the behaviour is consistent.
- t.Run("[]I", func(t *testing.T) {
- type I interface {
- Get() string
- }
- a := []I{&testGoReflectMethod_O{Test: "1"}, &testGoReflectMethod_O{Test: "2"}}
- _, err = fn(nil, vm.ToValue(a))
- if err != nil {
- t.Fatal(err)
- }
- })
- t.Run("[]interface{}", func(t *testing.T) {
- a := []interface{}{&testGoReflectMethod_O{Test: "1"}, &testGoReflectMethod_O{Test: "2"}}
- _, err = fn(nil, vm.ToValue(a))
- if err != nil {
- t.Fatal(err)
- }
- })
- }
- func TestCopyOnChangeReflectSlice(t *testing.T) {
- vm := New()
- v, err := vm.RunString(`
- s => {
- s.A.push(1);
- if (s.A.length !== 1) {
- throw new Error("s.A.length: " + s.A.length);
- }
- if (s.A[0] !== 1) {
- throw new Error("s.A[0]: " + s.A[0]);
- }
- let tmp = s.A;
- if (tmp !== s.A) {
- throw new Error("tmp !== s.A");
- }
- s.A = [2];
- if (tmp === s.A) {
- throw new Error("tmp === s.A");
- }
- if (tmp[0] !== 1) {
- throw new Error("tmp[0]: " + tmp[0]);
- }
- if (s.A[0] !== 2) {
- throw new Error("s.A[0] (1): " + s.A[0]);
- }
- }
- `)
- if err != nil {
- t.Fatal(err)
- }
- fn, ok := AssertFunction(v)
- if !ok {
- t.Fatal("Not a function")
- }
- t.Run("[]int", func(t *testing.T) {
- type S struct {
- A []int
- }
- var s S
- _, err := fn(nil, vm.ToValue(&s))
- if err != nil {
- t.Fatal(err)
- }
- if len(s.A) != 1 {
- t.Fatal(s)
- }
- if s.A[0] != 2 {
- t.Fatal(s.A)
- }
- })
- t.Run("[]interface{}", func(t *testing.T) {
- type S struct {
- A []interface{}
- }
- var s S
- _, err := fn(nil, vm.ToValue(&s))
- if err != nil {
- t.Fatal(err)
- }
- if len(s.A) != 1 {
- t.Fatal(s)
- }
- if s.A[0] != int64(2) {
- t.Fatal(s.A)
- }
- })
- }
- func TestCopyOnChangeSort(t *testing.T) {
- a := []struct {
- Test string
- }{{"2"}, {"1"}}
- vm := New()
- vm.Set("a", &a)
- _, err := vm.RunString(`
- let a0 = a[0];
- let a1 = a[1];
- a.sort((a, b) => a.Test.localeCompare(b.Test));
- if (a[0].Test !== "1") {
- throw new Error("a[0]: " + a[0]);
- }
- if (a[1].Test !== "2") {
- throw new Error("a[1]: " + a[1]);
- }
- if (a0 !== a[1]) {
- throw new Error("a0 !== a[1]");
- }
- if (a1 !== a[0]) {
- throw new Error("a1 !== a[0]");
- }
- `)
- if err != nil {
- t.Fatal(err)
- }
- if a[0].Test != "1" || a[1].Test != "2" {
- t.Fatal(a)
- }
- }
- type testStringerArray [8]byte
- func (a testStringerArray) String() string {
- return "X"
- }
- func TestReflectArrayToString(t *testing.T) {
- vm := New()
- var a testStringerArray
- vm.Set("a", &a)
- res, err := vm.RunString("`${a}`")
- if err != nil {
- t.Fatal(err)
- }
- if exp := res.Export(); exp != "X" {
- t.Fatal(exp)
- }
- var a1 [2]byte
- vm.Set("a", &a1)
- res, err = vm.RunString("`${a}`")
- if err != nil {
- t.Fatal(err)
- }
- if exp := res.Export(); exp != "0,0" {
- t.Fatal(exp)
- }
- }
|