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