blob: 94bda703578ea73829efda3a7db96705f614d54b [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004
5"use strict";
6
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007// This file relies on the fact that the following declaration has been made
8// in runtime.js:
9// var $Array = global.Array;
10
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011var $Set = global.Set;
12var $Map = global.Map;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013
14
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015// -------------------------------------------------------------------
16// Harmony Set
17
18function 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -040033 %_SetInitialize(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034
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);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010043 }
44}
45
46
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047function SetAddJS(key) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010048 if (!IS_SET(this)) {
49 throw MakeTypeError('incompatible_method_receiver',
50 ['Set.prototype.add', this]);
51 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000052 // 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;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010058 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040059 return %_SetAdd(this, key);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010060}
61
62
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063function SetHasJS(key) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010064 if (!IS_SET(this)) {
65 throw MakeTypeError('incompatible_method_receiver',
66 ['Set.prototype.has', this]);
67 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040068 return %_SetHas(this, key);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010069}
70
71
Ben Murdochb8a8cc12014-11-26 15:28:44 +000072function SetDeleteJS(key) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010073 if (!IS_SET(this)) {
74 throw MakeTypeError('incompatible_method_receiver',
75 ['Set.prototype.delete', this]);
76 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040077 return %_SetDelete(this, key);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010078}
79
80
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081function SetGetSizeJS() {
82 if (!IS_SET(this)) {
83 throw MakeTypeError('incompatible_method_receiver',
84 ['Set.prototype.size', this]);
85 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040086 return %_SetGetSize(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087}
88
89
90function SetClearJS() {
91 if (!IS_SET(this)) {
92 throw MakeTypeError('incompatible_method_receiver',
93 ['Set.prototype.clear', this]);
94 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040095 %_SetClear(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000096}
97
98
99function 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 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400108 var needs_wrapper = false;
109 if (IS_NULL_OR_UNDEFINED(receiver)) {
110 receiver = %GetDefaultReceiver(f) || receiver;
111 } else {
112 needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
113 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114
115 var iterator = new SetIterator(this, ITERATOR_KIND_VALUES);
116 var key;
117 var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
118 var value_array = [UNDEFINED];
119 while (%SetIteratorNext(iterator, value_array)) {
120 if (stepping) %DebugPrepareStepInIfStepping(f);
121 key = value_array[0];
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400122 var new_receiver = needs_wrapper ? ToObject(receiver) : receiver;
123 %_CallFunction(new_receiver, key, key, this, f);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100124 }
125}
126
127
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128// -------------------------------------------------------------------
129
130function SetUpSet() {
131 %CheckIsBootstrapping();
132
133 %SetCode($Set, SetConstructor);
134 %FunctionSetPrototype($Set, new $Object());
135 %AddNamedProperty($Set.prototype, "constructor", $Set, DONT_ENUM);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400136 %AddNamedProperty(
137 $Set.prototype, symbolToStringTag, "Set", DONT_ENUM | READ_ONLY);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138
139 %FunctionSetLength(SetForEach, 1);
140
141 // Set up the non-enumerable functions on the Set prototype object.
142 InstallGetter($Set.prototype, "size", SetGetSizeJS);
143 InstallFunctions($Set.prototype, DONT_ENUM, $Array(
144 "add", SetAddJS,
145 "has", SetHasJS,
146 "delete", SetDeleteJS,
147 "clear", SetClearJS,
148 "forEach", SetForEach
149 ));
150}
151
152SetUpSet();
153
154
155// -------------------------------------------------------------------
156// Harmony Map
157
158function MapConstructor(iterable) {
159 if (!%_IsConstructCall()) {
160 throw MakeTypeError('constructor_not_function', ['Map']);
161 }
162
163 var iter, adder;
164
165 if (!IS_NULL_OR_UNDEFINED(iterable)) {
166 iter = GetIterator(ToObject(iterable));
167 adder = this.set;
168 if (!IS_SPEC_FUNCTION(adder)) {
169 throw MakeTypeError('property_not_function', ['set', this]);
170 }
171 }
172
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400173 %_MapInitialize(this);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174
175 if (IS_UNDEFINED(iter)) return;
176
177 var next, done, nextItem;
178 while (!(next = iter.next()).done) {
179 if (!IS_SPEC_OBJECT(next)) {
180 throw MakeTypeError('iterator_result_not_an_object', [next]);
181 }
182 nextItem = next.value;
183 if (!IS_SPEC_OBJECT(nextItem)) {
184 throw MakeTypeError('iterator_value_not_an_object', [nextItem]);
185 }
186 %_CallFunction(this, nextItem[0], nextItem[1], adder);
187 }
188}
189
190
191function MapGetJS(key) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100192 if (!IS_MAP(this)) {
193 throw MakeTypeError('incompatible_method_receiver',
194 ['Map.prototype.get', this]);
195 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400196 return %_MapGet(this, key);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100197}
198
199
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200function MapSetJS(key, value) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100201 if (!IS_MAP(this)) {
202 throw MakeTypeError('incompatible_method_receiver',
203 ['Map.prototype.set', this]);
204 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 // Normalize -0 to +0 as required by the spec.
206 // Even though we use SameValueZero as the comparison for the keys we don't
207 // want to ever store -0 as the key since the key is directly exposed when
208 // doing iteration.
209 if (key === 0) {
210 key = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100211 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400212 return %_MapSet(this, key, value);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100213}
214
215
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216function MapHasJS(key) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100217 if (!IS_MAP(this)) {
218 throw MakeTypeError('incompatible_method_receiver',
219 ['Map.prototype.has', this]);
220 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400221 return %_MapHas(this, key);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100222}
223
224
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225function MapDeleteJS(key) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100226 if (!IS_MAP(this)) {
227 throw MakeTypeError('incompatible_method_receiver',
228 ['Map.prototype.delete', this]);
229 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400230 return %_MapDelete(this, key);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100231}
232
233
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234function MapGetSizeJS() {
235 if (!IS_MAP(this)) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100236 throw MakeTypeError('incompatible_method_receiver',
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237 ['Map.prototype.size', this]);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100238 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400239 return %_MapGetSize(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100240}
241
242
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243function MapClearJS() {
244 if (!IS_MAP(this)) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100245 throw MakeTypeError('incompatible_method_receiver',
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246 ['Map.prototype.clear', this]);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100247 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400248 %_MapClear(this);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100249}
250
251
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252function MapForEach(f, receiver) {
253 if (!IS_MAP(this)) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100254 throw MakeTypeError('incompatible_method_receiver',
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 ['Map.prototype.forEach', this]);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100256 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257
258 if (!IS_SPEC_FUNCTION(f)) {
259 throw MakeTypeError('called_non_callable', [f]);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100260 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400261 var needs_wrapper = false;
262 if (IS_NULL_OR_UNDEFINED(receiver)) {
263 receiver = %GetDefaultReceiver(f) || receiver;
264 } else {
265 needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
266 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267
268 var iterator = new MapIterator(this, ITERATOR_KIND_ENTRIES);
269 var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
270 var value_array = [UNDEFINED, UNDEFINED];
271 while (%MapIteratorNext(iterator, value_array)) {
272 if (stepping) %DebugPrepareStepInIfStepping(f);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400273 var new_receiver = needs_wrapper ? ToObject(receiver) : receiver;
274 %_CallFunction(new_receiver, value_array[1], value_array[0], this, f);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100276}
277
278
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100279// -------------------------------------------------------------------
280
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281function SetUpMap() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100282 %CheckIsBootstrapping();
283
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100284 %SetCode($Map, MapConstructor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 %FunctionSetPrototype($Map, new $Object());
286 %AddNamedProperty($Map.prototype, "constructor", $Map, DONT_ENUM);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400287 %AddNamedProperty(
288 $Map.prototype, symbolToStringTag, "Map", DONT_ENUM | READ_ONLY);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100289
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000290 %FunctionSetLength(MapForEach, 1);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100291
292 // Set up the non-enumerable functions on the Map prototype object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 InstallGetter($Map.prototype, "size", MapGetSizeJS);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100294 InstallFunctions($Map.prototype, DONT_ENUM, $Array(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295 "get", MapGetJS,
296 "set", MapSetJS,
297 "has", MapHasJS,
298 "delete", MapDeleteJS,
299 "clear", MapClearJS,
300 "forEach", MapForEach
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100301 ));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100303
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000304SetUpMap();