blob: 01537e87b0973cee8a65fc759c17fad43fbf7387 [file] [log] [blame]
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +00001// Copyright 2012 the V8 project authors. All rights reserved.
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +00002// 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
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000028"use strict";
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000029
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000030// This file relies on the fact that the following declaration has been made
31// in runtime.js:
32// var $Array = global.Array;
33
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000034var $Set = global.Set;
35var $Map = global.Map;
36var $WeakMap = global.WeakMap;
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +000037var $WeakSet = global.WeakSet;
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000038
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000039// Global sentinel to be used instead of undefined keys, which are not
40// supported internally but required for Harmony sets and maps.
41var undefined_sentinel = {};
42
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000043// -------------------------------------------------------------------
44// Harmony Set
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000045
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000046function SetConstructor() {
47 if (%_IsConstructCall()) {
48 %SetInitialize(this);
49 } else {
danno@chromium.orgd3c42102013-08-01 16:58:23 +000050 throw MakeTypeError('constructor_not_function', ['Set']);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000051 }
52}
53
54
55function SetAdd(key) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000056 if (!IS_SET(this)) {
57 throw MakeTypeError('incompatible_method_receiver',
58 ['Set.prototype.add', this]);
59 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000060 if (IS_UNDEFINED(key)) {
61 key = undefined_sentinel;
62 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000063 return %SetAdd(this, key);
64}
65
66
67function SetHas(key) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000068 if (!IS_SET(this)) {
69 throw MakeTypeError('incompatible_method_receiver',
70 ['Set.prototype.has', this]);
71 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000072 if (IS_UNDEFINED(key)) {
73 key = undefined_sentinel;
74 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000075 return %SetHas(this, key);
76}
77
78
79function SetDelete(key) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000080 if (!IS_SET(this)) {
81 throw MakeTypeError('incompatible_method_receiver',
82 ['Set.prototype.delete', this]);
83 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000084 if (IS_UNDEFINED(key)) {
85 key = undefined_sentinel;
86 }
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +000087 if (%SetHas(this, key)) {
88 %SetDelete(this, key);
89 return true;
90 } else {
91 return false;
92 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000093}
94
95
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +000096function SetGetSize() {
97 if (!IS_SET(this)) {
98 throw MakeTypeError('incompatible_method_receiver',
99 ['Set.prototype.size', this]);
100 }
101 return %SetGetSize(this);
102}
103
104
105function SetClear() {
106 if (!IS_SET(this)) {
107 throw MakeTypeError('incompatible_method_receiver',
108 ['Set.prototype.clear', this]);
109 }
110 // Replace the internal table with a new empty table.
111 %SetInitialize(this);
112}
113
114
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000115// -------------------------------------------------------------------
116
117function SetUpSet() {
118 %CheckIsBootstrapping();
119
120 %SetCode($Set, SetConstructor);
121 %FunctionSetPrototype($Set, new $Object());
122 %SetProperty($Set.prototype, "constructor", $Set, DONT_ENUM);
123
124 // Set up the non-enumerable functions on the Set prototype object.
125 InstallGetter($Set.prototype, "size", SetGetSize);
126 InstallFunctions($Set.prototype, DONT_ENUM, $Array(
127 "add", SetAdd,
128 "has", SetHas,
129 "delete", SetDelete,
130 "clear", SetClear
131 ));
132}
133
134SetUpSet();
135
136
137// -------------------------------------------------------------------
138// Harmony Map
139
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000140function MapConstructor() {
141 if (%_IsConstructCall()) {
142 %MapInitialize(this);
143 } else {
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000144 throw MakeTypeError('constructor_not_function', ['Map']);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000145 }
146}
147
148
149function MapGet(key) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000150 if (!IS_MAP(this)) {
151 throw MakeTypeError('incompatible_method_receiver',
152 ['Map.prototype.get', this]);
153 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000154 if (IS_UNDEFINED(key)) {
155 key = undefined_sentinel;
156 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000157 return %MapGet(this, key);
158}
159
160
161function MapSet(key, value) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000162 if (!IS_MAP(this)) {
163 throw MakeTypeError('incompatible_method_receiver',
164 ['Map.prototype.set', this]);
165 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000166 if (IS_UNDEFINED(key)) {
167 key = undefined_sentinel;
168 }
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000169 return %MapSet(this, key, value);
170}
171
172
173function MapHas(key) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000174 if (!IS_MAP(this)) {
175 throw MakeTypeError('incompatible_method_receiver',
176 ['Map.prototype.has', this]);
177 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000178 if (IS_UNDEFINED(key)) {
179 key = undefined_sentinel;
180 }
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000181 return %MapHas(this, key);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000182}
183
184
185function MapDelete(key) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000186 if (!IS_MAP(this)) {
187 throw MakeTypeError('incompatible_method_receiver',
188 ['Map.prototype.delete', this]);
189 }
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000190 if (IS_UNDEFINED(key)) {
191 key = undefined_sentinel;
192 }
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000193 return %MapDelete(this, key);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000194}
195
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000196
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +0000197function MapGetSize() {
198 if (!IS_MAP(this)) {
199 throw MakeTypeError('incompatible_method_receiver',
200 ['Map.prototype.size', this]);
201 }
202 return %MapGetSize(this);
203}
204
205
206function MapClear() {
207 if (!IS_MAP(this)) {
208 throw MakeTypeError('incompatible_method_receiver',
209 ['Map.prototype.clear', this]);
210 }
211 // Replace the internal table with a new empty table.
212 %MapInitialize(this);
213}
214
215
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000216// -------------------------------------------------------------------
217
218function SetUpMap() {
219 %CheckIsBootstrapping();
220
221 %SetCode($Map, MapConstructor);
222 %FunctionSetPrototype($Map, new $Object());
223 %SetProperty($Map.prototype, "constructor", $Map, DONT_ENUM);
224
225 // Set up the non-enumerable functions on the Map prototype object.
226 InstallGetter($Map.prototype, "size", MapGetSize);
227 InstallFunctions($Map.prototype, DONT_ENUM, $Array(
228 "get", MapGet,
229 "set", MapSet,
230 "has", MapHas,
231 "delete", MapDelete,
232 "clear", MapClear
233 ));
234}
235
236SetUpMap();
237
238
239// -------------------------------------------------------------------
240// Harmony WeakMap
241
danno@chromium.orgb6451162011-08-17 14:33:23 +0000242function WeakMapConstructor() {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000243 if (%_IsConstructCall()) {
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000244 %WeakCollectionInitialize(this);
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000245 } else {
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000246 throw MakeTypeError('constructor_not_function', ['WeakMap']);
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000247 }
danno@chromium.orgb6451162011-08-17 14:33:23 +0000248}
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000249
250
251function WeakMapGet(key) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000252 if (!IS_WEAKMAP(this)) {
253 throw MakeTypeError('incompatible_method_receiver',
254 ['WeakMap.prototype.get', this]);
255 }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000256 if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000257 throw %MakeTypeError('invalid_weakmap_key', [this, key]);
258 }
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000259 return %WeakCollectionGet(this, key);
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000260}
261
262
263function WeakMapSet(key, value) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000264 if (!IS_WEAKMAP(this)) {
265 throw MakeTypeError('incompatible_method_receiver',
266 ['WeakMap.prototype.set', this]);
267 }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000268 if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000269 throw %MakeTypeError('invalid_weakmap_key', [this, key]);
270 }
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000271 return %WeakCollectionSet(this, key, value);
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000272}
273
274
275function WeakMapHas(key) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000276 if (!IS_WEAKMAP(this)) {
277 throw MakeTypeError('incompatible_method_receiver',
278 ['WeakMap.prototype.has', this]);
279 }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000280 if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000281 throw %MakeTypeError('invalid_weakmap_key', [this, key]);
282 }
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000283 return %WeakCollectionHas(this, key);
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000284}
285
286
287function WeakMapDelete(key) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +0000288 if (!IS_WEAKMAP(this)) {
289 throw MakeTypeError('incompatible_method_receiver',
290 ['WeakMap.prototype.delete', this]);
291 }
ulan@chromium.org750145a2013-03-07 15:14:13 +0000292 if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000293 throw %MakeTypeError('invalid_weakmap_key', [this, key]);
294 }
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000295 return %WeakCollectionDelete(this, key);
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000296}
297
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000298
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000299function WeakMapClear() {
300 if (!IS_WEAKMAP(this)) {
301 throw MakeTypeError('incompatible_method_receiver',
302 ['WeakMap.prototype.clear', this]);
303 }
304 // Replace the internal table with a new empty table.
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000305 %WeakCollectionInitialize(this);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000306}
307
308
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000309// -------------------------------------------------------------------
310
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000311function SetUpWeakMap() {
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000312 %CheckIsBootstrapping();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000313
danno@chromium.orgb6451162011-08-17 14:33:23 +0000314 %SetCode($WeakMap, WeakMapConstructor);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000315 %FunctionSetPrototype($WeakMap, new $Object());
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +0000316 %SetProperty($WeakMap.prototype, "constructor", $WeakMap, DONT_ENUM);
317
318 // Set up the non-enumerable functions on the WeakMap prototype object.
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000319 InstallFunctions($WeakMap.prototype, DONT_ENUM, $Array(
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000320 "get", WeakMapGet,
321 "set", WeakMapSet,
322 "has", WeakMapHas,
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000323 "delete", WeakMapDelete,
324 "clear", WeakMapClear
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000325 ));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000326}
327
328SetUpWeakMap();
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000329
330
331// -------------------------------------------------------------------
332// Harmony WeakSet
333
334function WeakSetConstructor() {
335 if (%_IsConstructCall()) {
336 %WeakCollectionInitialize(this);
337 } else {
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000338 throw MakeTypeError('constructor_not_function', ['WeakSet']);
jkummerow@chromium.orgba72ec82013-07-22 09:21:20 +0000339 }
340}
341
342
343function WeakSetAdd(value) {
344 if (!IS_WEAKSET(this)) {
345 throw MakeTypeError('incompatible_method_receiver',
346 ['WeakSet.prototype.add', this]);
347 }
348 if (!(IS_SPEC_OBJECT(value) || IS_SYMBOL(value))) {
349 throw %MakeTypeError('invalid_weakset_value', [this, value]);
350 }
351 return %WeakCollectionSet(this, value, true);
352}
353
354
355function WeakSetHas(value) {
356 if (!IS_WEAKSET(this)) {
357 throw MakeTypeError('incompatible_method_receiver',
358 ['WeakSet.prototype.has', this]);
359 }
360 if (!(IS_SPEC_OBJECT(value) || IS_SYMBOL(value))) {
361 throw %MakeTypeError('invalid_weakset_value', [this, value]);
362 }
363 return %WeakCollectionHas(this, value);
364}
365
366
367function WeakSetDelete(value) {
368 if (!IS_WEAKSET(this)) {
369 throw MakeTypeError('incompatible_method_receiver',
370 ['WeakSet.prototype.delete', this]);
371 }
372 if (!(IS_SPEC_OBJECT(value) || IS_SYMBOL(value))) {
373 throw %MakeTypeError('invalid_weakset_value', [this, value]);
374 }
375 return %WeakCollectionDelete(this, value);
376}
377
378
379function WeakSetClear() {
380 if (!IS_WEAKSET(this)) {
381 throw MakeTypeError('incompatible_method_receiver',
382 ['WeakSet.prototype.clear', this]);
383 }
384 // Replace the internal table with a new empty table.
385 %WeakCollectionInitialize(this);
386}
387
388
389// -------------------------------------------------------------------
390
391function SetUpWeakSet() {
392 %CheckIsBootstrapping();
393
394 %SetCode($WeakSet, WeakSetConstructor);
395 %FunctionSetPrototype($WeakSet, new $Object());
396 %SetProperty($WeakSet.prototype, "constructor", $WeakSet, DONT_ENUM);
397
398 // Set up the non-enumerable functions on the WeakSet prototype object.
399 InstallFunctions($WeakSet.prototype, DONT_ENUM, $Array(
400 "add", WeakSetAdd,
401 "has", WeakSetHas,
402 "delete", WeakSetDelete,
403 "clear", WeakSetClear
404 ));
405}
406
407SetUpWeakSet();