1 package goja
2
3 import (
4 "testing"
5 )
6
7 func TestGoMapReflectGetSet(t *testing.T) {
8 const SCRIPT = `
9 m.c = m.a + m.b;
10 `
11
12 vm := New()
13 m := map[string]string{
14 "a": "4",
15 "b": "2",
16 }
17 vm.Set("m", m)
18
19 _, err := vm.RunString(SCRIPT)
20 if err != nil {
21 t.Fatal(err)
22 }
23
24 if c := m["c"]; c != "42" {
25 t.Fatalf("Unexpected value: '%s'", c)
26 }
27 }
28
29 func TestGoMapReflectIntKey(t *testing.T) {
30 const SCRIPT = `
31 m[2] = m[0] + m[1];
32 `
33
34 vm := New()
35 m := map[int]int{
36 0: 40,
37 1: 2,
38 }
39 vm.Set("m", m)
40
41 _, err := vm.RunString(SCRIPT)
42 if err != nil {
43 t.Fatal(err)
44 }
45
46 if c := m[2]; c != 42 {
47 t.Fatalf("Unexpected value: '%d'", c)
48 }
49 }
50
51 func TestGoMapReflectDelete(t *testing.T) {
52 const SCRIPT = `
53 delete m.a;
54 `
55
56 vm := New()
57 m := map[string]string{
58 "a": "4",
59 "b": "2",
60 }
61 vm.Set("m", m)
62
63 _, err := vm.RunString(SCRIPT)
64 if err != nil {
65 t.Fatal(err)
66 }
67
68 if _, exists := m["a"]; exists {
69 t.Fatal("a still exists")
70 }
71
72 if b := m["b"]; b != "2" {
73 t.Fatalf("Unexpected b: '%s'", b)
74 }
75 }
76
77 func TestGoMapReflectJSON(t *testing.T) {
78 const SCRIPT = `
79 function f(m) {
80 return JSON.stringify(m);
81 }
82 `
83
84 vm := New()
85 m := map[string]string{
86 "t": "42",
87 }
88 _, err := vm.RunString(SCRIPT)
89 if err != nil {
90 t.Fatal(err)
91 }
92 f := vm.Get("f")
93 if call, ok := AssertFunction(f); ok {
94 v, err := call(nil, ([]Value{vm.ToValue(m)})...)
95 if err != nil {
96 t.Fatal(err)
97 }
98 if !v.StrictEquals(asciiString(`{"t":"42"}`)) {
99 t.Fatalf("Unexpected value: %v", v)
100 }
101 } else {
102 t.Fatalf("Not a function: %v", f)
103 }
104 }
105
106 func TestGoMapReflectProto(t *testing.T) {
107 const SCRIPT = `
108 m.hasOwnProperty("t");
109 `
110
111 vm := New()
112 m := map[string]string{
113 "t": "42",
114 }
115 vm.Set("m", m)
116 v, err := vm.RunString(SCRIPT)
117 if err != nil {
118 t.Fatal(err)
119 }
120 if !v.StrictEquals(valueTrue) {
121 t.Fatalf("Expected true, got %v", v)
122 }
123 }
124
125 type gomapReflect_noMethods map[string]interface{}
126 type gomapReflect_withMethods map[string]interface{}
127
128 func (m gomapReflect_withMethods) Method() bool {
129 return true
130 }
131
132 func TestGoMapReflectNoMethods(t *testing.T) {
133 const SCRIPT = `
134 typeof m === "object" && m.hasOwnProperty("t") && m.t === 42;
135 `
136
137 vm := New()
138 m := make(gomapReflect_noMethods)
139 m["t"] = 42
140 vm.Set("m", m)
141 v, err := vm.RunString(SCRIPT)
142 if err != nil {
143 t.Fatal(err)
144 }
145 if !v.StrictEquals(valueTrue) {
146 t.Fatalf("Expected true, got %v", v)
147 }
148
149 }
150
151 func TestGoMapReflectWithMethods(t *testing.T) {
152 const SCRIPT = `
153 typeof m === "object" && !m.hasOwnProperty("t") && m.hasOwnProperty("Method") && m.Method();
154 `
155
156 vm := New()
157 m := make(gomapReflect_withMethods)
158 m["t"] = 42
159 vm.Set("m", m)
160 v, err := vm.RunString(SCRIPT)
161 if err != nil {
162 t.Fatal(err)
163 }
164 if !v.StrictEquals(valueTrue) {
165 t.Fatalf("Expected true, got %v", v)
166 }
167
168 }
169
170 func TestGoMapReflectWithProto(t *testing.T) {
171 vm := New()
172 m := map[string]string{
173 "t": "42",
174 }
175 vm.Set("m", m)
176 vm.testScriptWithTestLib(`
177 (function() {
178 'use strict';
179 var proto = {};
180 var getterAllowed = false;
181 var setterAllowed = false;
182 var tHolder = "proto t";
183 Object.defineProperty(proto, "t", {
184 get: function() {
185 if (!getterAllowed) throw new Error("getter is called");
186 return tHolder;
187 },
188 set: function(v) {
189 if (!setterAllowed) throw new Error("setter is called");
190 tHolder = v;
191 }
192 });
193 var t1Holder;
194 Object.defineProperty(proto, "t1", {
195 get: function() {
196 return t1Holder;
197 },
198 set: function(v) {
199 t1Holder = v;
200 }
201 });
202 Object.setPrototypeOf(m, proto);
203 assert.sameValue(m.t, "42");
204 m.t = 43;
205 assert.sameValue(m.t, "43");
206 t1Holder = "test";
207 assert.sameValue(m.t1, "test");
208 m.t1 = "test1";
209 assert.sameValue(m.t1, "test1");
210 delete m.t;
211 getterAllowed = true;
212 assert.sameValue(m.t, "proto t", "after delete");
213 setterAllowed = true;
214 m.t = true;
215 assert.sameValue(m.t, true, "m.t === true");
216 assert.sameValue(tHolder, true, "tHolder === true");
217 Object.preventExtensions(m);
218 assert.throws(TypeError, function() {
219 m.t2 = 1;
220 });
221 m.t1 = "test2";
222 assert.sameValue(m.t1, "test2");
223 })();
224 `, _undefined, t)
225 }
226
227 func TestGoMapReflectProtoProp(t *testing.T) {
228 const SCRIPT = `
229 (function() {
230 "use strict";
231 var proto = {};
232 Object.defineProperty(proto, "ro", {value: 42});
233 Object.setPrototypeOf(m, proto);
234 assert.throws(TypeError, function() {
235 m.ro = 43;
236 });
237 Object.defineProperty(m, "ro", {value: 43});
238 assert.sameValue(m.ro, "43");
239 })();
240 `
241
242 r := New()
243 r.Set("m", map[string]string{})
244 r.testScriptWithTestLib(SCRIPT, _undefined, t)
245 }
246
247 func TestGoMapReflectUnicode(t *testing.T) {
248 const SCRIPT = `
249 Object.setPrototypeOf(m, s);
250 if (m.Тест !== "passed") {
251 throw new Error("m.Тест: " + m.Тест);
252 }
253 m["é"];
254 `
255 type S struct {
256 Тест string
257 }
258 vm := New()
259 m := map[string]int{
260 "é": 42,
261 }
262 s := S{
263 Тест: "passed",
264 }
265 vm.Set("m", m)
266 vm.Set("s", &s)
267 res, err := vm.RunString(SCRIPT)
268 if err != nil {
269 t.Fatal(err)
270 }
271 if res == nil || !res.StrictEquals(valueInt(42)) {
272 t.Fatalf("Unexpected value: %v", res)
273 }
274 }
275
276 func TestGoMapReflectStruct(t *testing.T) {
277 type S struct {
278 Test int
279 }
280
281 m := map[string]S{
282 "1": {Test: 1},
283 }
284
285 vm := New()
286 vm.Set("m", m)
287 res, err := vm.RunString("m[1].Test = 2; m[1].Test")
288 if err != nil {
289 t.Fatal(err)
290 }
291 if res.Export() != int64(1) {
292 t.Fatal(res)
293 }
294 }
295
296 func TestGoMapReflectElt(t *testing.T) {
297 type mapping map[string]interface{}
298
299 const SCRIPT = `a.s() && a.t === null && a.t1 === undefined;`
300
301 r := New()
302
303 r.Set("a", mapping{
304 "s": func() bool { return true },
305 "t": nil,
306 })
307
308 r.testScript(SCRIPT, valueTrue, t)
309 }
310
View as plain text