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
11var $WeakMap = global.WeakMap;
12var $WeakSet = global.WeakSet;
13
14
15// -------------------------------------------------------------------
16// Harmony WeakMap
17
18function WeakMapConstructor(iterable) {
19  if (!%_IsConstructCall()) {
20    throw MakeTypeError('constructor_not_function', ['WeakMap']);
21  }
22
23  var iter, adder;
24
25  if (!IS_NULL_OR_UNDEFINED(iterable)) {
26    iter = GetIterator(ToObject(iterable));
27    adder = this.set;
28    if (!IS_SPEC_FUNCTION(adder)) {
29      throw MakeTypeError('property_not_function', ['set', this]);
30    }
31  }
32
33  %WeakCollectionInitialize(this);
34
35  if (IS_UNDEFINED(iter)) return;
36
37  var next, done, nextItem;
38  while (!(next = iter.next()).done) {
39    if (!IS_SPEC_OBJECT(next)) {
40      throw MakeTypeError('iterator_result_not_an_object', [next]);
41    }
42    nextItem = next.value;
43    if (!IS_SPEC_OBJECT(nextItem)) {
44      throw MakeTypeError('iterator_value_not_an_object', [nextItem]);
45    }
46    %_CallFunction(this, nextItem[0], nextItem[1], adder);
47  }
48}
49
50
51function WeakMapGet(key) {
52  if (!IS_WEAKMAP(this)) {
53    throw MakeTypeError('incompatible_method_receiver',
54                        ['WeakMap.prototype.get', this]);
55  }
56  if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
57    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
58  }
59  return %WeakCollectionGet(this, key);
60}
61
62
63function WeakMapSet(key, value) {
64  if (!IS_WEAKMAP(this)) {
65    throw MakeTypeError('incompatible_method_receiver',
66                        ['WeakMap.prototype.set', this]);
67  }
68  if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
69    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
70  }
71  return %WeakCollectionSet(this, key, value);
72}
73
74
75function WeakMapHas(key) {
76  if (!IS_WEAKMAP(this)) {
77    throw MakeTypeError('incompatible_method_receiver',
78                        ['WeakMap.prototype.has', this]);
79  }
80  if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
81    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
82  }
83  return %WeakCollectionHas(this, key);
84}
85
86
87function WeakMapDelete(key) {
88  if (!IS_WEAKMAP(this)) {
89    throw MakeTypeError('incompatible_method_receiver',
90                        ['WeakMap.prototype.delete', this]);
91  }
92  if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
93    throw %MakeTypeError('invalid_weakmap_key', [this, key]);
94  }
95  return %WeakCollectionDelete(this, key);
96}
97
98
99function WeakMapClear() {
100  if (!IS_WEAKMAP(this)) {
101    throw MakeTypeError('incompatible_method_receiver',
102                        ['WeakMap.prototype.clear', this]);
103  }
104  // Replace the internal table with a new empty table.
105  %WeakCollectionInitialize(this);
106}
107
108
109// -------------------------------------------------------------------
110
111function SetUpWeakMap() {
112  %CheckIsBootstrapping();
113
114  %SetCode($WeakMap, WeakMapConstructor);
115  %FunctionSetPrototype($WeakMap, new $Object());
116  %AddNamedProperty($WeakMap.prototype, "constructor", $WeakMap, DONT_ENUM);
117
118  // Set up the non-enumerable functions on the WeakMap prototype object.
119  InstallFunctions($WeakMap.prototype, DONT_ENUM, $Array(
120    "get", WeakMapGet,
121    "set", WeakMapSet,
122    "has", WeakMapHas,
123    "delete", WeakMapDelete,
124    "clear", WeakMapClear
125  ));
126}
127
128SetUpWeakMap();
129
130
131// -------------------------------------------------------------------
132// Harmony WeakSet
133
134function WeakSetConstructor(iterable) {
135  if (!%_IsConstructCall()) {
136    throw MakeTypeError('constructor_not_function', ['WeakSet']);
137  }
138
139  var iter, adder;
140
141  if (!IS_NULL_OR_UNDEFINED(iterable)) {
142    iter = GetIterator(ToObject(iterable));
143    adder = this.add;
144    if (!IS_SPEC_FUNCTION(adder)) {
145      throw MakeTypeError('property_not_function', ['add', this]);
146    }
147  }
148
149  %WeakCollectionInitialize(this);
150
151  if (IS_UNDEFINED(iter)) return;
152
153  var next, done;
154  while (!(next = iter.next()).done) {
155    if (!IS_SPEC_OBJECT(next)) {
156      throw MakeTypeError('iterator_result_not_an_object', [next]);
157    }
158    %_CallFunction(this, next.value, adder);
159  }
160}
161
162
163function WeakSetAdd(value) {
164  if (!IS_WEAKSET(this)) {
165    throw MakeTypeError('incompatible_method_receiver',
166                        ['WeakSet.prototype.add', this]);
167  }
168  if (!(IS_SPEC_OBJECT(value) || IS_SYMBOL(value))) {
169    throw %MakeTypeError('invalid_weakset_value', [this, value]);
170  }
171  return %WeakCollectionSet(this, value, true);
172}
173
174
175function WeakSetHas(value) {
176  if (!IS_WEAKSET(this)) {
177    throw MakeTypeError('incompatible_method_receiver',
178                        ['WeakSet.prototype.has', this]);
179  }
180  if (!(IS_SPEC_OBJECT(value) || IS_SYMBOL(value))) {
181    throw %MakeTypeError('invalid_weakset_value', [this, value]);
182  }
183  return %WeakCollectionHas(this, value);
184}
185
186
187function WeakSetDelete(value) {
188  if (!IS_WEAKSET(this)) {
189    throw MakeTypeError('incompatible_method_receiver',
190                        ['WeakSet.prototype.delete', this]);
191  }
192  if (!(IS_SPEC_OBJECT(value) || IS_SYMBOL(value))) {
193    throw %MakeTypeError('invalid_weakset_value', [this, value]);
194  }
195  return %WeakCollectionDelete(this, value);
196}
197
198
199function WeakSetClear() {
200  if (!IS_WEAKSET(this)) {
201    throw MakeTypeError('incompatible_method_receiver',
202                        ['WeakSet.prototype.clear', this]);
203  }
204  // Replace the internal table with a new empty table.
205  %WeakCollectionInitialize(this);
206}
207
208
209// -------------------------------------------------------------------
210
211function SetUpWeakSet() {
212  %CheckIsBootstrapping();
213
214  %SetCode($WeakSet, WeakSetConstructor);
215  %FunctionSetPrototype($WeakSet, new $Object());
216  %AddNamedProperty($WeakSet.prototype, "constructor", $WeakSet, DONT_ENUM);
217
218  // Set up the non-enumerable functions on the WeakSet prototype object.
219  InstallFunctions($WeakSet.prototype, DONT_ENUM, $Array(
220    "add", WeakSetAdd,
221    "has", WeakSetHas,
222    "delete", WeakSetDelete,
223    "clear", WeakSetClear
224  ));
225}
226
227SetUpWeakSet();
228