...
1 package goja
2
3 import (
4 "testing"
5 )
6
7 func TestGoReflectArray(t *testing.T) {
8 vm := New()
9 vm.Set("a", [...]int{1, 2, 3})
10 _, err := vm.RunString(`
11 if (!Array.isArray(a)) {
12 throw new Error("isArray() returned false");
13 }
14 if (a[0] !== 1 || a[1] !== 2 || a[2] !== 3) {
15 throw new Error("Array contents is incorrect");
16 }
17 if (!a.hasOwnProperty("length")) {
18 throw new Error("hasOwnProperty() returned false");
19 }
20 let desc = Object.getOwnPropertyDescriptor(a, "length");
21 if (desc.value !== 3 || desc.writable || desc.enumerable || desc.configurable) {
22 throw new Error("incorrect property descriptor: " + JSON.stringify(desc));
23 }
24 `)
25 if err != nil {
26 t.Fatal(err)
27 }
28 }
29
30 func TestGoReflectArraySort(t *testing.T) {
31 vm := New()
32 vm.Set("a", [...]int{3, 1, 2})
33 v, err := vm.RunString(`
34 a.sort();
35 if (a[0] !== 1 || a[1] !== 2 || a[2] !== 3) {
36 throw new Error(a.toString());
37 }
38 a;
39 `)
40 if err != nil {
41 t.Fatal(err)
42 }
43 res := v.Export()
44 if a, ok := res.([3]int); ok {
45 if a[0] != 1 || a[1] != 2 || a[2] != 3 {
46 t.Fatal(a)
47 }
48 } else {
49 t.Fatalf("Wrong type: %T", res)
50 }
51 }
52
53 func TestGoReflectArrayCopyOnChange(t *testing.T) {
54 vm := New()
55
56 v, err := vm.RunString(`
57 a => {
58 let tmp = a[0];
59 if (tmp !== a[0]) {
60 throw new Error("tmp !== a[0]");
61 }
62
63 a[0] = a[1];
64 if (tmp === a[0]) {
65 throw new Error("tmp === a[0]");
66 }
67 if (tmp.Test !== "1") {
68 throw new Error("tmp.Test: " + tmp.Test + " (" + typeof tmp.Test + ")");
69 }
70 if (a[0].Test !== "2") {
71 throw new Error("a[0].Test: " + a[0].Test);
72 }
73
74 a[0].Test = "3";
75 if (a[0].Test !== "3") {
76 throw new Error("a[0].Test (1): " + a[0].Test);
77 }
78
79 tmp = a[0];
80 tmp.Test = "4";
81 if (a[0].Test !== "4") {
82 throw new Error("a[0].Test (2): " + a[0].Test);
83 }
84
85 delete a[0];
86 if (a[0] && a[0].Test !== "") {
87 throw new Error("a[0].Test (3): " + a[0].Test);
88 }
89 if (tmp.Test !== "4") {
90 throw new Error("tmp.Test (1): " + tmp.Test);
91 }
92
93 a[1] = tmp;
94 if (a[1].Test !== "4") {
95 throw new Error("a[1].Test: " + a[1].Test);
96 }
97
98 // grow
99 tmp = a[1];
100 a.push(null);
101 if (a.length !== 3) {
102 throw new Error("a.length after push: " + a.length);
103 }
104
105 tmp.Test = "5";
106 if (a[1].Test !== "5") {
107 throw new Error("a[1].Test (1): " + a[1].Test);
108 }
109
110 // shrink
111 a.length = 1;
112 if (a.length !== 1) {
113 throw new Error("a.length after shrink: " + a.length);
114 }
115
116 if (tmp.Test !== "5") {
117 throw new Error("tmp.Test (shrink): " + tmp.Test);
118 }
119 }
120 `)
121 if err != nil {
122 t.Fatal(err)
123 }
124
125 fn, ok := AssertFunction(v)
126 if !ok {
127 t.Fatal("Not a function")
128 }
129
130 t.Run("[]struct", func(t *testing.T) {
131 a := []struct {
132 Test string
133 }{{"1"}, {"2"}}
134 _, err := fn(nil, vm.ToValue(a))
135 if err != nil {
136 t.Fatal(err)
137 }
138 if a[0].Test != "" {
139 t.Fatalf("a[0]: %#v", a[0])
140 }
141
142 if a[1].Test != "4" {
143 t.Fatalf("a0[1]: %#v", a[1])
144 }
145 })
146
147
148
149
150 t.Run("[]I", func(t *testing.T) {
151 type I interface {
152 Get() string
153 }
154
155 a := []I{&testGoReflectMethod_O{Test: "1"}, &testGoReflectMethod_O{Test: "2"}}
156
157 _, err = fn(nil, vm.ToValue(a))
158 if err != nil {
159 t.Fatal(err)
160 }
161 })
162
163 t.Run("[]interface{}", func(t *testing.T) {
164 a := []interface{}{&testGoReflectMethod_O{Test: "1"}, &testGoReflectMethod_O{Test: "2"}}
165
166 _, err = fn(nil, vm.ToValue(a))
167 if err != nil {
168 t.Fatal(err)
169 }
170 })
171 }
172
173 func TestCopyOnChangeReflectSlice(t *testing.T) {
174 vm := New()
175 v, err := vm.RunString(`
176 s => {
177 s.A.push(1);
178 if (s.A.length !== 1) {
179 throw new Error("s.A.length: " + s.A.length);
180 }
181 if (s.A[0] !== 1) {
182 throw new Error("s.A[0]: " + s.A[0]);
183 }
184 let tmp = s.A;
185 if (tmp !== s.A) {
186 throw new Error("tmp !== s.A");
187 }
188 s.A = [2];
189 if (tmp === s.A) {
190 throw new Error("tmp === s.A");
191 }
192 if (tmp[0] !== 1) {
193 throw new Error("tmp[0]: " + tmp[0]);
194 }
195 if (s.A[0] !== 2) {
196 throw new Error("s.A[0] (1): " + s.A[0]);
197 }
198 }
199 `)
200 if err != nil {
201 t.Fatal(err)
202 }
203 fn, ok := AssertFunction(v)
204 if !ok {
205 t.Fatal("Not a function")
206 }
207
208 t.Run("[]int", func(t *testing.T) {
209 type S struct {
210 A []int
211 }
212 var s S
213 _, err := fn(nil, vm.ToValue(&s))
214 if err != nil {
215 t.Fatal(err)
216 }
217 if len(s.A) != 1 {
218 t.Fatal(s)
219 }
220 if s.A[0] != 2 {
221 t.Fatal(s.A)
222 }
223 })
224
225 t.Run("[]interface{}", func(t *testing.T) {
226 type S struct {
227 A []interface{}
228 }
229 var s S
230 _, err := fn(nil, vm.ToValue(&s))
231 if err != nil {
232 t.Fatal(err)
233 }
234 if len(s.A) != 1 {
235 t.Fatal(s)
236 }
237 if s.A[0] != int64(2) {
238 t.Fatal(s.A)
239 }
240 })
241 }
242
243 func TestCopyOnChangeSort(t *testing.T) {
244 a := []struct {
245 Test string
246 }{{"2"}, {"1"}}
247
248 vm := New()
249 vm.Set("a", &a)
250
251 _, err := vm.RunString(`
252 let a0 = a[0];
253 let a1 = a[1];
254 a.sort((a, b) => a.Test.localeCompare(b.Test));
255 if (a[0].Test !== "1") {
256 throw new Error("a[0]: " + a[0]);
257 }
258 if (a[1].Test !== "2") {
259 throw new Error("a[1]: " + a[1]);
260 }
261 if (a0 !== a[1]) {
262 throw new Error("a0 !== a[1]");
263 }
264 if (a1 !== a[0]) {
265 throw new Error("a1 !== a[0]");
266 }
267 `)
268 if err != nil {
269 t.Fatal(err)
270 }
271
272 if a[0].Test != "1" || a[1].Test != "2" {
273 t.Fatal(a)
274 }
275 }
276
277 type testStringerArray [8]byte
278
279 func (a testStringerArray) String() string {
280 return "X"
281 }
282
283 func TestReflectArrayToString(t *testing.T) {
284 vm := New()
285 var a testStringerArray
286 vm.Set("a", &a)
287 res, err := vm.RunString("`${a}`")
288 if err != nil {
289 t.Fatal(err)
290 }
291 if exp := res.Export(); exp != "X" {
292 t.Fatal(exp)
293 }
294
295 var a1 [2]byte
296 vm.Set("a", &a1)
297 res, err = vm.RunString("`${a}`")
298 if err != nil {
299 t.Fatal(err)
300 }
301 if exp := res.Export(); exp != "0,0" {
302 t.Fatal(exp)
303 }
304 }
305
View as plain text