Home | History | Annotate | Download | only in src
      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 $WeakMap = global.WeakMap;
     12 var $WeakSet = global.WeakSet;
     13 
     14 
     15 // -------------------------------------------------------------------
     16 // Harmony WeakMap
     17 
     18 function 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 
     51 function 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 
     63 function 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 
     75 function 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 
     87 function 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 
     99 function 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 
    111 function 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 
    128 SetUpWeakMap();
    129 
    130 
    131 // -------------------------------------------------------------------
    132 // Harmony WeakSet
    133 
    134 function 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 
    163 function 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 
    175 function 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 
    187 function 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 
    199 function 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 
    211 function 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 
    227 SetUpWeakSet();
    228