Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / v8 / src / collection.js
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 "use strict";
6
7 // This file relies on the fact that the following declaration has been made
8 // in runtime.js:
9 // var $Array = global.Array;
10
11 var $Set = global.Set;
12 var $Map = global.Map;
13
14
15 // -------------------------------------------------------------------
16 // Harmony Set
17
18 function SetConstructor(iterable) {
19   if (!%_IsConstructCall()) {
20     throw MakeTypeError('constructor_not_function', ['Set']);
21   }
22
23   var iter, adder;
24
25   if (!IS_NULL_OR_UNDEFINED(iterable)) {
26     iter = GetIterator(ToObject(iterable));
27     adder = this.add;
28     if (!IS_SPEC_FUNCTION(adder)) {
29       throw MakeTypeError('property_not_function', ['add', this]);
30     }
31   }
32
33   %SetInitialize(this);
34
35   if (IS_UNDEFINED(iter)) return;
36
37   var next, done;
38   while (!(next = iter.next()).done) {
39     if (!IS_SPEC_OBJECT(next)) {
40       throw MakeTypeError('iterator_result_not_an_object', [next]);
41     }
42     %_CallFunction(this, next.value, adder);
43   }
44 }
45
46
47 function SetAddJS(key) {
48   if (!IS_SET(this)) {
49     throw MakeTypeError('incompatible_method_receiver',
50                         ['Set.prototype.add', this]);
51   }
52   // Normalize -0 to +0 as required by the spec.
53   // Even though we use SameValueZero as the comparison for the keys we don't
54   // want to ever store -0 as the key since the key is directly exposed when
55   // doing iteration.
56   if (key === 0) {
57     key = 0;
58   }
59   return %SetAdd(this, key);
60 }
61
62
63 function SetHasJS(key) {
64   if (!IS_SET(this)) {
65     throw MakeTypeError('incompatible_method_receiver',
66                         ['Set.prototype.has', this]);
67   }
68   return %SetHas(this, key);
69 }
70
71
72 function SetDeleteJS(key) {
73   if (!IS_SET(this)) {
74     throw MakeTypeError('incompatible_method_receiver',
75                         ['Set.prototype.delete', this]);
76   }
77   return %SetDelete(this, key);
78 }
79
80
81 function SetGetSizeJS() {
82   if (!IS_SET(this)) {
83     throw MakeTypeError('incompatible_method_receiver',
84                         ['Set.prototype.size', this]);
85   }
86   return %SetGetSize(this);
87 }
88
89
90 function SetClearJS() {
91   if (!IS_SET(this)) {
92     throw MakeTypeError('incompatible_method_receiver',
93                         ['Set.prototype.clear', this]);
94   }
95   %SetClear(this);
96 }
97
98
99 function SetForEach(f, receiver) {
100   if (!IS_SET(this)) {
101     throw MakeTypeError('incompatible_method_receiver',
102                         ['Set.prototype.forEach', this]);
103   }
104
105   if (!IS_SPEC_FUNCTION(f)) {
106     throw MakeTypeError('called_non_callable', [f]);
107   }
108
109   var iterator = new SetIterator(this, ITERATOR_KIND_VALUES);
110   var key;
111   var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
112   var value_array = [UNDEFINED];
113   while (%SetIteratorNext(iterator, value_array)) {
114     if (stepping) %DebugPrepareStepInIfStepping(f);
115     key = value_array[0];
116     %_CallFunction(receiver, key, key, this, f);
117   }
118 }
119
120
121 // -------------------------------------------------------------------
122
123 function SetUpSet() {
124   %CheckIsBootstrapping();
125
126   %SetCode($Set, SetConstructor);
127   %FunctionSetPrototype($Set, new $Object());
128   %AddNamedProperty($Set.prototype, "constructor", $Set, DONT_ENUM);
129
130   %FunctionSetLength(SetForEach, 1);
131
132   // Set up the non-enumerable functions on the Set prototype object.
133   InstallGetter($Set.prototype, "size", SetGetSizeJS);
134   InstallFunctions($Set.prototype, DONT_ENUM, $Array(
135     "add", SetAddJS,
136     "has", SetHasJS,
137     "delete", SetDeleteJS,
138     "clear", SetClearJS,
139     "forEach", SetForEach
140   ));
141 }
142
143 SetUpSet();
144
145
146 // -------------------------------------------------------------------
147 // Harmony Map
148
149 function MapConstructor(iterable) {
150   if (!%_IsConstructCall()) {
151     throw MakeTypeError('constructor_not_function', ['Map']);
152   }
153
154   var iter, adder;
155
156   if (!IS_NULL_OR_UNDEFINED(iterable)) {
157     iter = GetIterator(ToObject(iterable));
158     adder = this.set;
159     if (!IS_SPEC_FUNCTION(adder)) {
160       throw MakeTypeError('property_not_function', ['set', this]);
161     }
162   }
163
164   %MapInitialize(this);
165
166   if (IS_UNDEFINED(iter)) return;
167
168   var next, done, nextItem;
169   while (!(next = iter.next()).done) {
170     if (!IS_SPEC_OBJECT(next)) {
171       throw MakeTypeError('iterator_result_not_an_object', [next]);
172     }
173     nextItem = next.value;
174     if (!IS_SPEC_OBJECT(nextItem)) {
175       throw MakeTypeError('iterator_value_not_an_object', [nextItem]);
176     }
177     %_CallFunction(this, nextItem[0], nextItem[1], adder);
178   }
179 }
180
181
182 function MapGetJS(key) {
183   if (!IS_MAP(this)) {
184     throw MakeTypeError('incompatible_method_receiver',
185                         ['Map.prototype.get', this]);
186   }
187   return %MapGet(this, key);
188 }
189
190
191 function MapSetJS(key, value) {
192   if (!IS_MAP(this)) {
193     throw MakeTypeError('incompatible_method_receiver',
194                         ['Map.prototype.set', this]);
195   }
196   // Normalize -0 to +0 as required by the spec.
197   // Even though we use SameValueZero as the comparison for the keys we don't
198   // want to ever store -0 as the key since the key is directly exposed when
199   // doing iteration.
200   if (key === 0) {
201     key = 0;
202   }
203   return %MapSet(this, key, value);
204 }
205
206
207 function MapHasJS(key) {
208   if (!IS_MAP(this)) {
209     throw MakeTypeError('incompatible_method_receiver',
210                         ['Map.prototype.has', this]);
211   }
212   return %MapHas(this, key);
213 }
214
215
216 function MapDeleteJS(key) {
217   if (!IS_MAP(this)) {
218     throw MakeTypeError('incompatible_method_receiver',
219                         ['Map.prototype.delete', this]);
220   }
221   return %MapDelete(this, key);
222 }
223
224
225 function MapGetSizeJS() {
226   if (!IS_MAP(this)) {
227     throw MakeTypeError('incompatible_method_receiver',
228                         ['Map.prototype.size', this]);
229   }
230   return %MapGetSize(this);
231 }
232
233
234 function MapClearJS() {
235   if (!IS_MAP(this)) {
236     throw MakeTypeError('incompatible_method_receiver',
237                         ['Map.prototype.clear', this]);
238   }
239   %MapClear(this);
240 }
241
242
243 function MapForEach(f, receiver) {
244   if (!IS_MAP(this)) {
245     throw MakeTypeError('incompatible_method_receiver',
246                         ['Map.prototype.forEach', this]);
247   }
248
249   if (!IS_SPEC_FUNCTION(f)) {
250     throw MakeTypeError('called_non_callable', [f]);
251   }
252
253   var iterator = new MapIterator(this, ITERATOR_KIND_ENTRIES);
254   var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
255   var value_array = [UNDEFINED, UNDEFINED];
256   while (%MapIteratorNext(iterator, value_array)) {
257     if (stepping) %DebugPrepareStepInIfStepping(f);
258     %_CallFunction(receiver, value_array[1], value_array[0], this, f);
259   }
260 }
261
262
263 // -------------------------------------------------------------------
264
265 function SetUpMap() {
266   %CheckIsBootstrapping();
267
268   %SetCode($Map, MapConstructor);
269   %FunctionSetPrototype($Map, new $Object());
270   %AddNamedProperty($Map.prototype, "constructor", $Map, DONT_ENUM);
271
272   %FunctionSetLength(MapForEach, 1);
273
274   // Set up the non-enumerable functions on the Map prototype object.
275   InstallGetter($Map.prototype, "size", MapGetSizeJS);
276   InstallFunctions($Map.prototype, DONT_ENUM, $Array(
277     "get", MapGetJS,
278     "set", MapSetJS,
279     "has", MapHasJS,
280     "delete", MapDeleteJS,
281     "clear", MapClearJS,
282     "forEach", MapForEach
283   ));
284 }
285
286 SetUpMap();