collection.js revision c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9
1// Copyright 2011 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
29const $Set = global.Set;
30const $Map = global.Map;
31const $WeakMap = global.WeakMap;
32
33//-------------------------------------------------------------------
34
35// Global sentinel to be used instead of undefined keys, which are not
36// supported internally but required for Harmony sets and maps.
37var undefined_sentinel = {};
38
39
40function SetConstructor() {
41  if (%_IsConstructCall()) {
42    %SetInitialize(this);
43  } else {
44    return new $Set();
45  }
46}
47
48
49function SetAdd(key) {
50  if (!IS_SET(this)) {
51    throw MakeTypeError('incompatible_method_receiver',
52                        ['Set.prototype.add', this]);
53  }
54  if (IS_UNDEFINED(key)) {
55    key = undefined_sentinel;
56  }
57  return %SetAdd(this, key);
58}
59
60
61function SetHas(key) {
62  if (!IS_SET(this)) {
63    throw MakeTypeError('incompatible_method_receiver',
64                        ['Set.prototype.has', this]);
65  }
66  if (IS_UNDEFINED(key)) {
67    key = undefined_sentinel;
68  }
69  return %SetHas(this, key);
70}
71
72
73function SetDelete(key) {
74  if (!IS_SET(this)) {
75    throw MakeTypeError('incompatible_method_receiver',
76                        ['Set.prototype.delete', this]);
77  }
78  if (IS_UNDEFINED(key)) {
79    key = undefined_sentinel;
80  }
81  return %SetDelete(this, key);
82}
83
84
85function MapConstructor() {
86  if (%_IsConstructCall()) {
87    %MapInitialize(this);
88  } else {
89    return new $Map();
90  }
91}
92
93
94function MapGet(key) {
95  if (!IS_MAP(this)) {
96    throw MakeTypeError('incompatible_method_receiver',
97                        ['Map.prototype.get', this]);
98  }
99  if (IS_UNDEFINED(key)) {
100    key = undefined_sentinel;
101  }
102  return %MapGet(this, key);
103}
104
105
106function MapSet(key, value) {
107  if (!IS_MAP(this)) {
108    throw MakeTypeError('incompatible_method_receiver',
109                        ['Map.prototype.set', this]);
110  }
111  if (IS_UNDEFINED(key)) {
112    key = undefined_sentinel;
113  }
114  return %MapSet(this, key, value);
115}
116
117
118function MapHas(key) {
119  if (!IS_MAP(this)) {
120    throw MakeTypeError('incompatible_method_receiver',
121                        ['Map.prototype.has', this]);
122  }
123  if (IS_UNDEFINED(key)) {
124    key = undefined_sentinel;
125  }
126  return !IS_UNDEFINED(%MapGet(this, key));
127}
128
129
130function MapDelete(key) {
131  if (!IS_MAP(this)) {
132    throw MakeTypeError('incompatible_method_receiver',
133                        ['Map.prototype.delete', this]);
134  }
135  if (IS_UNDEFINED(key)) {
136    key = undefined_sentinel;
137  }
138  if (!IS_UNDEFINED(%MapGet(this, key))) {
139    %MapSet(this, key, void 0);
140    return true;
141  } else {
142    return false;
143  }
144}
145
146
147function WeakMapConstructor() {
148  if (%_IsConstructCall()) {
149    %WeakMapInitialize(this);
150  } else {
151    return new $WeakMap();
152  }
153}
154
155
156function WeakMapGet(key) {
157  if (!IS_WEAKMAP(this)) {
158    throw MakeTypeError('incompatible_method_receiver',
159                        ['WeakMap.prototype.get', this]);
160  }
161  if (!IS_SPEC_OBJECT(key)) {
162    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
163  }
164  return %WeakMapGet(this, key);
165}
166
167
168function WeakMapSet(key, value) {
169  if (!IS_WEAKMAP(this)) {
170    throw MakeTypeError('incompatible_method_receiver',
171                        ['WeakMap.prototype.set', this]);
172  }
173  if (!IS_SPEC_OBJECT(key)) {
174    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
175  }
176  return %WeakMapSet(this, key, value);
177}
178
179
180function WeakMapHas(key) {
181  if (!IS_WEAKMAP(this)) {
182    throw MakeTypeError('incompatible_method_receiver',
183                        ['WeakMap.prototype.has', this]);
184  }
185  if (!IS_SPEC_OBJECT(key)) {
186    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
187  }
188  return !IS_UNDEFINED(%WeakMapGet(this, key));
189}
190
191
192function WeakMapDelete(key) {
193  if (!IS_WEAKMAP(this)) {
194    throw MakeTypeError('incompatible_method_receiver',
195                        ['WeakMap.prototype.delete', this]);
196  }
197  if (!IS_SPEC_OBJECT(key)) {
198    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
199  }
200  if (!IS_UNDEFINED(%WeakMapGet(this, key))) {
201    %WeakMapSet(this, key, void 0);
202    return true;
203  } else {
204    return false;
205  }
206}
207
208// -------------------------------------------------------------------
209
210(function () {
211  %CheckIsBootstrapping();
212
213  // Set up the Set and Map constructor function.
214  %SetCode($Set, SetConstructor);
215  %SetCode($Map, MapConstructor);
216
217  // Set up the constructor property on the Set and Map prototype object.
218  %SetProperty($Set.prototype, "constructor", $Set, DONT_ENUM);
219  %SetProperty($Map.prototype, "constructor", $Map, DONT_ENUM);
220
221  // Set up the non-enumerable functions on the Set prototype object.
222  InstallFunctions($Set.prototype, DONT_ENUM, $Array(
223    "add", SetAdd,
224    "has", SetHas,
225    "delete", SetDelete
226  ));
227
228  // Set up the non-enumerable functions on the Map prototype object.
229  InstallFunctions($Map.prototype, DONT_ENUM, $Array(
230    "get", MapGet,
231    "set", MapSet,
232    "has", MapHas,
233    "delete", MapDelete
234  ));
235
236  // Set up the WeakMap constructor function.
237  %SetCode($WeakMap, WeakMapConstructor);
238
239  // Set up the constructor property on the WeakMap prototype object.
240  %SetProperty($WeakMap.prototype, "constructor", $WeakMap, DONT_ENUM);
241
242  // Set up the non-enumerable functions on the WeakMap prototype object.
243  InstallFunctions($WeakMap.prototype, DONT_ENUM, $Array(
244    "get", WeakMapGet,
245    "set", WeakMapSet,
246    "has", WeakMapHas,
247    "delete", WeakMapDelete
248  ));
249})();
250