Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / test / mjsunit / es6 / symbols.js
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 // Flags: --expose-gc --allow-natives-syntax
29
30 var symbols = []
31
32
33 // Returns true if the string is a valid
34 // serialization of Symbols added to the 'symbols'
35 // array. Adjust if you extend 'symbols' with other
36 // values.
37 function isValidSymbolString(s) {
38   return ["Symbol(66)", "Symbol()"].indexOf(s) >= 0;
39 }
40
41
42 // Test different forms of constructor calls.
43 function TestNew() {
44   function indirectSymbol() { return Symbol() }
45   function indirect() { return indirectSymbol() }
46   for (var i = 0; i < 2; ++i) {
47     for (var j = 0; j < 5; ++j) {
48       symbols.push(Symbol())
49       symbols.push(Symbol(undefined))
50       symbols.push(Symbol("66"))
51       symbols.push(Symbol(66))
52       symbols.push(Symbol().valueOf())
53       symbols.push(indirect())
54     }
55     %OptimizeFunctionOnNextCall(indirect)
56     indirect()  // Call once before GC throws away type feedback.
57     gc()        // Promote existing symbols and then allocate some more.
58   }
59   assertThrows(function () { Symbol(Symbol()) }, TypeError)
60   assertThrows(function () { new Symbol(66) }, TypeError)
61 }
62 TestNew()
63
64
65 function TestType() {
66   for (var i in symbols) {
67     assertEquals("symbol", typeof symbols[i])
68     assertTrue(typeof symbols[i] === "symbol")
69     assertFalse(%SymbolIsPrivate(symbols[i]))
70     assertEquals(null, %_ClassOf(symbols[i]))
71     assertEquals("Symbol", %_ClassOf(Object(symbols[i])))
72   }
73 }
74 TestType()
75
76
77 function TestPrototype() {
78   assertSame(Object.prototype, Symbol.prototype.__proto__)
79   assertSame(Symbol.prototype, Symbol().__proto__)
80   assertSame(Symbol.prototype, Object(Symbol()).__proto__)
81   for (var i in symbols) {
82     assertSame(Symbol.prototype, symbols[i].__proto__)
83   }
84 }
85 TestPrototype()
86
87
88 function TestConstructor() {
89   assertSame(Function.prototype, Symbol.__proto__)
90   assertFalse(Object === Symbol.prototype.constructor)
91   assertFalse(Symbol === Object.prototype.constructor)
92   assertSame(Symbol, Symbol.prototype.constructor)
93   assertSame(Symbol, Symbol().__proto__.constructor)
94   assertSame(Symbol, Object(Symbol()).__proto__.constructor)
95   for (var i in symbols) {
96     assertSame(Symbol, symbols[i].__proto__.constructor)
97   }
98 }
99 TestConstructor()
100
101
102 function TestValueOf() {
103   for (var i in symbols) {
104     assertTrue(symbols[i] === Object(symbols[i]).valueOf())
105     assertTrue(symbols[i] === symbols[i].valueOf())
106     assertTrue(Symbol.prototype.valueOf.call(Object(symbols[i])) === symbols[i])
107     assertTrue(Symbol.prototype.valueOf.call(symbols[i]) === symbols[i])
108   }
109 }
110 TestValueOf()
111
112
113 function TestToString() {
114   for (var i in symbols) {
115     assertThrows(function() { String(symbols[i]) }, TypeError)
116     assertThrows(function() { symbols[i] + "" }, TypeError)
117     assertThrows(function() { String(Object(symbols[i])) }, TypeError)
118     assertTrue(isValidSymbolString(symbols[i].toString()))
119     assertTrue(isValidSymbolString(Object(symbols[i]).toString()))
120     assertTrue(
121       isValidSymbolString(Symbol.prototype.toString.call(symbols[i])))
122     assertEquals(
123       "[object Symbol]", Object.prototype.toString.call(symbols[i]))
124   }
125 }
126 TestToString()
127
128
129 function TestToBoolean() {
130   for (var i in symbols) {
131     assertTrue(Boolean(Object(symbols[i])))
132     assertFalse(!Object(symbols[i]))
133     assertTrue(Boolean(symbols[i]).valueOf())
134     assertFalse(!symbols[i])
135     assertTrue(!!symbols[i])
136     assertTrue(symbols[i] && true)
137     assertFalse(!symbols[i] && false)
138     assertTrue(!symbols[i] || true)
139     assertEquals(1, symbols[i] ? 1 : 2)
140     assertEquals(2, !symbols[i] ? 1 : 2)
141     if (!symbols[i]) assertUnreachable();
142     if (symbols[i]) {} else assertUnreachable();
143   }
144 }
145 TestToBoolean()
146
147
148 function TestToNumber() {
149   for (var i in symbols) {
150     assertThrows(function() { Number(Object(symbols[i])) }, TypeError)
151     assertThrows(function() { +Object(symbols[i]) }, TypeError)
152     assertThrows(function() { Number(symbols[i]) }, TypeError)
153     assertThrows(function() { symbols[i] + 0 }, TypeError)
154   }
155 }
156 TestToNumber()
157
158
159 function TestEquality() {
160   // Every symbol should equal itself, and non-strictly equal its wrapper.
161   for (var i in symbols) {
162     assertSame(symbols[i], symbols[i])
163     assertEquals(symbols[i], symbols[i])
164     assertTrue(Object.is(symbols[i], symbols[i]))
165     assertTrue(symbols[i] === symbols[i])
166     assertTrue(symbols[i] == symbols[i])
167     assertFalse(symbols[i] === Object(symbols[i]))
168     assertFalse(Object(symbols[i]) === symbols[i])
169     assertFalse(symbols[i] == Object(symbols[i]))
170     assertFalse(Object(symbols[i]) == symbols[i])
171     assertTrue(symbols[i] === symbols[i].valueOf())
172     assertTrue(symbols[i].valueOf() === symbols[i])
173     assertTrue(symbols[i] == symbols[i].valueOf())
174     assertTrue(symbols[i].valueOf() == symbols[i])
175     assertFalse(Object(symbols[i]) === Object(symbols[i]))
176     assertEquals(Object(symbols[i]).valueOf(), Object(symbols[i]).valueOf())
177   }
178
179   // All symbols should be distinct.
180   for (var i = 0; i < symbols.length; ++i) {
181     for (var j = i + 1; j < symbols.length; ++j) {
182       assertFalse(Object.is(symbols[i], symbols[j]))
183       assertFalse(symbols[i] === symbols[j])
184       assertFalse(symbols[i] == symbols[j])
185     }
186   }
187
188   // Symbols should not be equal to any other value (and the test terminates).
189   var values = [347, 1.275, NaN, "string", null, undefined, {}, function() {}]
190   for (var i in symbols) {
191     for (var j in values) {
192       assertFalse(symbols[i] === values[j])
193       assertFalse(values[j] === symbols[i])
194       assertFalse(symbols[i] == values[j])
195       assertFalse(values[j] == symbols[i])
196     }
197   }
198 }
199 TestEquality()
200
201
202 function TestGet() {
203   for (var i in symbols) {
204     assertTrue(isValidSymbolString(symbols[i].toString()))
205     assertEquals(symbols[i], symbols[i].valueOf())
206     assertEquals(undefined, symbols[i].a)
207     assertEquals(undefined, symbols[i]["a" + "b"])
208     assertEquals(undefined, symbols[i]["" + "1"])
209     assertEquals(undefined, symbols[i][62])
210   }
211 }
212 TestGet()
213
214
215 function TestSet() {
216   for (var i in symbols) {
217     symbols[i].toString = 0
218     assertTrue(isValidSymbolString(symbols[i].toString()))
219     symbols[i].valueOf = 0
220     assertEquals(symbols[i], symbols[i].valueOf())
221     symbols[i].a = 0
222     assertEquals(undefined, symbols[i].a)
223     symbols[i]["a" + "b"] = 0
224     assertEquals(undefined, symbols[i]["a" + "b"])
225     symbols[i][62] = 0
226     assertEquals(undefined, symbols[i][62])
227   }
228 }
229 TestSet()
230
231
232 // Test Symbol wrapping/boxing over non-builtins.
233 Symbol.prototype.getThisProto = function () {
234   return Object.getPrototypeOf(this);
235 }
236 function TestCall() {
237   for (var i in symbols) {
238     assertTrue(symbols[i].getThisProto() === Symbol.prototype)
239   }
240 }
241 TestCall()
242
243
244 function TestCollections() {
245   var set = new Set
246   var map = new Map
247   var weakmap = new WeakMap
248   for (var i in symbols) {
249     set.add(symbols[i])
250     map.set(symbols[i], i)
251     weakmap.set(symbols[i], i)
252   }
253   assertEquals(symbols.length, set.size)
254   assertEquals(symbols.length, map.size)
255   for (var i in symbols) {
256     assertTrue(set.has(symbols[i]))
257     assertTrue(map.has(symbols[i]))
258     assertTrue(weakmap.has(symbols[i]))
259     assertEquals(i, map.get(symbols[i]))
260     assertEquals(i, weakmap.get(symbols[i]))
261   }
262   for (var i in symbols) {
263     assertTrue(set.delete(symbols[i]))
264     assertTrue(map.delete(symbols[i]))
265     assertTrue(weakmap.delete(symbols[i]))
266   }
267   assertEquals(0, set.size)
268   assertEquals(0, map.size)
269 }
270 TestCollections()
271
272
273
274 function TestKeySet(obj) {
275   assertTrue(%HasFastProperties(obj))
276   // Set the even symbols via assignment.
277   for (var i = 0; i < symbols.length; i += 2) {
278     obj[symbols[i]] = i
279     // Object should remain in fast mode until too many properties were added.
280     assertTrue(%HasFastProperties(obj) || i >= 30)
281   }
282 }
283
284
285 function TestKeyDefine(obj) {
286   // Set the odd symbols via defineProperty (as non-enumerable).
287   for (var i = 1; i < symbols.length; i += 2) {
288     Object.defineProperty(obj, symbols[i], {value: i, configurable: true})
289   }
290 }
291
292
293 function TestKeyGet(obj) {
294   var obj2 = Object.create(obj)
295   for (var i in symbols) {
296     assertEquals(i|0, obj[symbols[i]])
297     assertEquals(i|0, obj2[symbols[i]])
298   }
299 }
300
301
302 function TestKeyHas(obj) {
303   for (var i in symbols) {
304     assertTrue(symbols[i] in obj)
305     assertTrue(Object.hasOwnProperty.call(obj, symbols[i]))
306   }
307 }
308
309
310 function TestKeyEnum(obj) {
311   for (var name in obj) {
312     assertEquals("string", typeof name)
313   }
314 }
315
316
317 function TestKeyNames(obj) {
318   assertEquals(0, Object.keys(obj).length)
319
320   var names = Object.getOwnPropertyNames(obj)
321   for (var i in names) {
322     assertEquals("string", typeof names[i])
323   }
324 }
325
326
327 function TestGetOwnPropertySymbols(obj) {
328   var syms = Object.getOwnPropertySymbols(obj)
329   assertEquals(syms.length, symbols.length)
330   for (var i in syms) {
331     assertEquals("symbol", typeof syms[i])
332   }
333 }
334
335
336 function TestKeyDescriptor(obj) {
337   for (var i in symbols) {
338     var desc = Object.getOwnPropertyDescriptor(obj, symbols[i])
339     assertEquals(i|0, desc.value)
340     assertTrue(desc.configurable)
341     assertEquals(i % 2 == 0, desc.writable)
342     assertEquals(i % 2 == 0, desc.enumerable)
343     assertEquals(i % 2 == 0,
344         Object.prototype.propertyIsEnumerable.call(obj, symbols[i]))
345   }
346 }
347
348
349 function TestKeyDelete(obj) {
350   for (var i in symbols) {
351     delete obj[symbols[i]]
352   }
353   for (var i in symbols) {
354     assertEquals(undefined, Object.getOwnPropertyDescriptor(obj, symbols[i]))
355   }
356 }
357
358
359 var objs = [{}, [], Object.create(null), Object(1), new Map, function(){}]
360
361 for (var i in objs) {
362   var obj = objs[i]
363   TestKeySet(obj)
364   TestKeyDefine(obj)
365   TestKeyGet(obj)
366   TestKeyHas(obj)
367   TestKeyEnum(obj)
368   TestKeyNames(obj)
369   TestGetOwnPropertySymbols(obj)
370   TestKeyDescriptor(obj)
371   TestKeyDelete(obj)
372 }
373
374
375 function TestDefineProperties() {
376   var properties = {}
377   for (var i in symbols) {
378     Object.defineProperty(
379         properties, symbols[i], {value: {value: i}, enumerable: i % 2 === 0})
380   }
381   var o = Object.defineProperties({}, properties)
382   for (var i in symbols) {
383     assertEquals(i % 2 === 0, symbols[i] in o)
384   }
385 }
386 TestDefineProperties()
387
388
389 function TestCreate() {
390   var properties = {}
391   for (var i in symbols) {
392     Object.defineProperty(
393       properties, symbols[i], {value: {value: i}, enumerable: i % 2 === 0})
394   }
395   var o = Object.create(Object.prototype, properties)
396   for (var i in symbols) {
397     assertEquals(i % 2 === 0, symbols[i] in o)
398   }
399 }
400 TestCreate()
401
402
403 function TestCachedKeyAfterScavenge() {
404   gc();
405   // Keyed property lookup are cached.  Hereby we assume that the keys are
406   // tenured, so that we only have to clear the cache between mark compacts,
407   // but not between scavenges.  This must also apply for symbol keys.
408   var key = Symbol("key");
409   var a = {};
410   a[key] = "abc";
411
412   for (var i = 0; i < 100000; i++) {
413     a[key] += "a";  // Allocations cause a scavenge.
414   }
415 }
416 TestCachedKeyAfterScavenge();
417
418
419 function TestGetOwnPropertySymbolsWithProto() {
420   // We need to be have fast properties to have insertion order for property
421   // keys. The current limit is currently 30 properties.
422   var syms = symbols.slice(0, 30);
423   var proto = {}
424   var object = Object.create(proto)
425   for (var i = 0; i < syms.length; i++) {
426     // Even on object, odd on proto.
427     if (i % 2) {
428       proto[syms[i]] = i
429     } else {
430       object[syms[i]] = i
431     }
432   }
433
434   assertTrue(%HasFastProperties(object));
435
436   var objectOwnSymbols = Object.getOwnPropertySymbols(object)
437   assertEquals(objectOwnSymbols.length, syms.length / 2)
438
439   for (var i = 0; i < objectOwnSymbols.length; i++) {
440     assertEquals(objectOwnSymbols[i], syms[i * 2])
441   }
442 }
443 TestGetOwnPropertySymbolsWithProto()
444
445
446 function TestWellKnown() {
447   var symbols = [
448     // TODO(rossberg): reactivate once implemented.
449     // "hasInstance", "isConcatSpreadable", "isRegExp",
450     "iterator", /* "toStringTag", */ "unscopables"
451   ]
452
453   for (var i in symbols) {
454     var name = symbols[i]
455     var desc = Object.getOwnPropertyDescriptor(Symbol, name)
456     assertSame("symbol", typeof desc.value)
457     assertSame("Symbol(Symbol." + name + ")", desc.value.toString())
458     assertFalse(desc.writable)
459     assertFalse(desc.configurable)
460     assertFalse(desc.enumerable)
461
462     assertFalse(Symbol.for("Symbol." + name) === desc.value)
463     assertTrue(Symbol.keyFor(desc.value) === undefined)
464   }
465 }
466 TestWellKnown()
467
468
469 function TestRegistry() {
470   var symbol1 = Symbol.for("x1")
471   var symbol2 = Symbol.for("x2")
472   assertFalse(symbol1 === symbol2)
473
474   assertSame(symbol1, Symbol.for("x1"))
475   assertSame(symbol2, Symbol.for("x2"))
476   assertSame("x1", Symbol.keyFor(symbol1))
477   assertSame("x2", Symbol.keyFor(symbol2))
478
479   assertSame(Symbol.for("1"), Symbol.for(1))
480   assertThrows(function() { Symbol.keyFor("bla") }, TypeError)
481   assertThrows(function() { Symbol.keyFor({}) }, TypeError)
482
483   var realm = Realm.create()
484   assertFalse(Symbol === Realm.eval(realm, "Symbol"))
485   assertFalse(Symbol.for === Realm.eval(realm, "Symbol.for"))
486   assertFalse(Symbol.keyFor === Realm.eval(realm, "Symbol.keyFor"))
487   assertSame(Symbol.create, Realm.eval(realm, "Symbol.create"))
488   assertSame(Symbol.iterator, Realm.eval(realm, "Symbol.iterator"))
489
490   assertSame(symbol1, Realm.eval(realm, "Symbol.for")("x1"))
491   assertSame(symbol1, Realm.eval(realm, "Symbol.for('x1')"))
492   assertSame("x1", Realm.eval(realm, "Symbol.keyFor")(symbol1))
493   Realm.shared = symbol1
494   assertSame("x1", Realm.eval(realm, "Symbol.keyFor(Realm.shared)"))
495
496   var symbol3 = Realm.eval(realm, "Symbol.for('x3')")
497   assertFalse(symbol1 === symbol3)
498   assertFalse(symbol2 === symbol3)
499   assertSame(symbol3, Symbol.for("x3"))
500   assertSame("x3", Symbol.keyFor(symbol3))
501 }
502 TestRegistry()