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 // This file relies on the fact that the following declarations have been made
      6 // in runtime.js:
      7 // var $Object = global.Object;
      8 // var $Boolean = global.Boolean;
      9 // var $Number = global.Number;
     10 // var $Function = global.Function;
     11 // var $Array = global.Array;
     12 //
     13 // in math.js:
     14 // var $floor = MathFloor
     15 
     16 var $isNaN = GlobalIsNaN;
     17 var $isFinite = GlobalIsFinite;
     18 
     19 // ----------------------------------------------------------------------------
     20 
     21 // Helper function used to install functions on objects.
     22 function InstallFunctions(object, attributes, functions) {
     23   if (functions.length >= 8) {
     24     %OptimizeObjectForAddingMultipleProperties(object, functions.length >> 1);
     25   }
     26   for (var i = 0; i < functions.length; i += 2) {
     27     var key = functions[i];
     28     var f = functions[i + 1];
     29     %FunctionSetName(f, key);
     30     %FunctionRemovePrototype(f);
     31     %AddNamedProperty(object, key, f, attributes);
     32     %SetNativeFlag(f);
     33   }
     34   %ToFastProperties(object);
     35 }
     36 
     37 
     38 // Helper function to install a getter-only accessor property.
     39 function InstallGetter(object, name, getter) {
     40   %FunctionSetName(getter, name);
     41   %FunctionRemovePrototype(getter);
     42   %DefineAccessorPropertyUnchecked(object, name, getter, null, DONT_ENUM);
     43   %SetNativeFlag(getter);
     44 }
     45 
     46 
     47 // Helper function to install a getter/setter accessor property.
     48 function InstallGetterSetter(object, name, getter, setter) {
     49   %FunctionSetName(getter, name);
     50   %FunctionSetName(setter, name);
     51   %FunctionRemovePrototype(getter);
     52   %FunctionRemovePrototype(setter);
     53   %DefineAccessorPropertyUnchecked(object, name, getter, setter, DONT_ENUM);
     54   %SetNativeFlag(getter);
     55   %SetNativeFlag(setter);
     56 }
     57 
     58 
     59 // Helper function for installing constant properties on objects.
     60 function InstallConstants(object, constants) {
     61   if (constants.length >= 4) {
     62     %OptimizeObjectForAddingMultipleProperties(object, constants.length >> 1);
     63   }
     64   var attributes = DONT_ENUM | DONT_DELETE | READ_ONLY;
     65   for (var i = 0; i < constants.length; i += 2) {
     66     var name = constants[i];
     67     var k = constants[i + 1];
     68     %AddNamedProperty(object, name, k, attributes);
     69   }
     70   %ToFastProperties(object);
     71 }
     72 
     73 
     74 // Prevents changes to the prototype of a built-in function.
     75 // The "prototype" property of the function object is made non-configurable,
     76 // and the prototype object is made non-extensible. The latter prevents
     77 // changing the __proto__ property.
     78 function SetUpLockedPrototype(constructor, fields, methods) {
     79   %CheckIsBootstrapping();
     80   var prototype = constructor.prototype;
     81   // Install functions first, because this function is used to initialize
     82   // PropertyDescriptor itself.
     83   var property_count = (methods.length >> 1) + (fields ? fields.length : 0);
     84   if (property_count >= 4) {
     85     %OptimizeObjectForAddingMultipleProperties(prototype, property_count);
     86   }
     87   if (fields) {
     88     for (var i = 0; i < fields.length; i++) {
     89       %AddNamedProperty(prototype, fields[i],
     90                         UNDEFINED, DONT_ENUM | DONT_DELETE);
     91     }
     92   }
     93   for (var i = 0; i < methods.length; i += 2) {
     94     var key = methods[i];
     95     var f = methods[i + 1];
     96     %AddNamedProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
     97     %SetNativeFlag(f);
     98   }
     99   %InternalSetPrototype(prototype, null);
    100   %ToFastProperties(prototype);
    101 }
    102 
    103 
    104 // ----------------------------------------------------------------------------
    105 
    106 
    107 // ECMA 262 - 15.1.4
    108 function GlobalIsNaN(number) {
    109   if (!IS_NUMBER(number)) number = NonNumberToNumber(number);
    110   return NUMBER_IS_NAN(number);
    111 }
    112 
    113 
    114 // ECMA 262 - 15.1.5
    115 function GlobalIsFinite(number) {
    116   if (!IS_NUMBER(number)) number = NonNumberToNumber(number);
    117   return NUMBER_IS_FINITE(number);
    118 }
    119 
    120 
    121 // ECMA-262 - 15.1.2.2
    122 function GlobalParseInt(string, radix) {
    123   if (IS_UNDEFINED(radix) || radix === 10 || radix === 0) {
    124     // Some people use parseInt instead of Math.floor.  This
    125     // optimization makes parseInt on a Smi 12 times faster (60ns
    126     // vs 800ns).  The following optimization makes parseInt on a
    127     // non-Smi number 9 times faster (230ns vs 2070ns).  Together
    128     // they make parseInt on a string 1.4% slower (274ns vs 270ns).
    129     if (%_IsSmi(string)) return string;
    130     if (IS_NUMBER(string) &&
    131         ((0.01 < string && string < 1e9) ||
    132             (-1e9 < string && string < -0.01))) {
    133       // Truncate number.
    134       return string | 0;
    135     }
    136     string = TO_STRING_INLINE(string);
    137     radix = radix | 0;
    138   } else {
    139     // The spec says ToString should be evaluated before ToInt32.
    140     string = TO_STRING_INLINE(string);
    141     radix = TO_INT32(radix);
    142     if (!(radix == 0 || (2 <= radix && radix <= 36))) {
    143       return NAN;
    144     }
    145   }
    146 
    147   if (%_HasCachedArrayIndex(string) &&
    148       (radix == 0 || radix == 10)) {
    149     return %_GetCachedArrayIndex(string);
    150   }
    151   return %StringParseInt(string, radix);
    152 }
    153 
    154 
    155 // ECMA-262 - 15.1.2.3
    156 function GlobalParseFloat(string) {
    157   string = TO_STRING_INLINE(string);
    158   if (%_HasCachedArrayIndex(string)) return %_GetCachedArrayIndex(string);
    159   return %StringParseFloat(string);
    160 }
    161 
    162 
    163 function GlobalEval(x) {
    164   if (!IS_STRING(x)) return x;
    165 
    166   // For consistency with JSC we require the global object passed to
    167   // eval to be the global object from which 'eval' originated. This
    168   // is not mandated by the spec.
    169   // We only throw if the global has been detached, since we need the
    170   // receiver as this-value for the call.
    171   if (!%IsAttachedGlobal(global)) {
    172     throw new $EvalError('The "this" value passed to eval must ' +
    173                          'be the global object from which eval originated');
    174   }
    175 
    176   var global_proxy = %GlobalProxy(global);
    177 
    178   var f = %CompileString(x, false);
    179   if (!IS_FUNCTION(f)) return f;
    180 
    181   return %_CallFunction(global_proxy, f);
    182 }
    183 
    184 
    185 // ----------------------------------------------------------------------------
    186 
    187 // Set up global object.
    188 function SetUpGlobal() {
    189   %CheckIsBootstrapping();
    190 
    191   var attributes = DONT_ENUM | DONT_DELETE | READ_ONLY;
    192 
    193   // ECMA 262 - 15.1.1.1.
    194   %AddNamedProperty(global, "NaN", NAN, attributes);
    195 
    196   // ECMA-262 - 15.1.1.2.
    197   %AddNamedProperty(global, "Infinity", INFINITY, attributes);
    198 
    199   // ECMA-262 - 15.1.1.3.
    200   %AddNamedProperty(global, "undefined", UNDEFINED, attributes);
    201 
    202   // Set up non-enumerable function on the global object.
    203   InstallFunctions(global, DONT_ENUM, $Array(
    204     "isNaN", GlobalIsNaN,
    205     "isFinite", GlobalIsFinite,
    206     "parseInt", GlobalParseInt,
    207     "parseFloat", GlobalParseFloat,
    208     "eval", GlobalEval
    209   ));
    210 }
    211 
    212 SetUpGlobal();
    213 
    214 
    215 // ----------------------------------------------------------------------------
    216 // Object
    217 
    218 // ECMA-262 - 15.2.4.2
    219 function ObjectToString() {
    220   if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
    221   if (IS_NULL(this)) return "[object Null]";
    222   return "[object " + %_ClassOf(ToObject(this)) + "]";
    223 }
    224 
    225 
    226 // ECMA-262 - 15.2.4.3
    227 function ObjectToLocaleString() {
    228   CHECK_OBJECT_COERCIBLE(this, "Object.prototype.toLocaleString");
    229   return this.toString();
    230 }
    231 
    232 
    233 // ECMA-262 - 15.2.4.4
    234 function ObjectValueOf() {
    235   return ToObject(this);
    236 }
    237 
    238 
    239 // ECMA-262 - 15.2.4.5
    240 function ObjectHasOwnProperty(V) {
    241   if (%IsJSProxy(this)) {
    242     // TODO(rossberg): adjust once there is a story for symbols vs proxies.
    243     if (IS_SYMBOL(V)) return false;
    244 
    245     var handler = %GetHandler(this);
    246     return CallTrap1(handler, "hasOwn", DerivedHasOwnTrap, ToName(V));
    247   }
    248   return %HasOwnProperty(TO_OBJECT_INLINE(this), ToName(V));
    249 }
    250 
    251 
    252 // ECMA-262 - 15.2.4.6
    253 function ObjectIsPrototypeOf(V) {
    254   CHECK_OBJECT_COERCIBLE(this, "Object.prototype.isPrototypeOf");
    255   if (!IS_SPEC_OBJECT(V)) return false;
    256   return %IsInPrototypeChain(this, V);
    257 }
    258 
    259 
    260 // ECMA-262 - 15.2.4.6
    261 function ObjectPropertyIsEnumerable(V) {
    262   var P = ToName(V);
    263   if (%IsJSProxy(this)) {
    264     // TODO(rossberg): adjust once there is a story for symbols vs proxies.
    265     if (IS_SYMBOL(V)) return false;
    266 
    267     var desc = GetOwnPropertyJS(this, P);
    268     return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
    269   }
    270   return %IsPropertyEnumerable(ToObject(this), P);
    271 }
    272 
    273 
    274 // Extensions for providing property getters and setters.
    275 function ObjectDefineGetter(name, fun) {
    276   var receiver = this;
    277   if (receiver == null && !IS_UNDETECTABLE(receiver)) {
    278     receiver = %GlobalProxy(global);
    279   }
    280   if (!IS_SPEC_FUNCTION(fun)) {
    281     throw new $TypeError(
    282         'Object.prototype.__defineGetter__: Expecting function');
    283   }
    284   var desc = new PropertyDescriptor();
    285   desc.setGet(fun);
    286   desc.setEnumerable(true);
    287   desc.setConfigurable(true);
    288   DefineOwnProperty(ToObject(receiver), ToName(name), desc, false);
    289 }
    290 
    291 
    292 function ObjectLookupGetter(name) {
    293   var receiver = this;
    294   if (receiver == null && !IS_UNDETECTABLE(receiver)) {
    295     receiver = %GlobalProxy(global);
    296   }
    297   return %LookupAccessor(ToObject(receiver), ToName(name), GETTER);
    298 }
    299 
    300 
    301 function ObjectDefineSetter(name, fun) {
    302   var receiver = this;
    303   if (receiver == null && !IS_UNDETECTABLE(receiver)) {
    304     receiver = %GlobalProxy(global);
    305   }
    306   if (!IS_SPEC_FUNCTION(fun)) {
    307     throw new $TypeError(
    308         'Object.prototype.__defineSetter__: Expecting function');
    309   }
    310   var desc = new PropertyDescriptor();
    311   desc.setSet(fun);
    312   desc.setEnumerable(true);
    313   desc.setConfigurable(true);
    314   DefineOwnProperty(ToObject(receiver), ToName(name), desc, false);
    315 }
    316 
    317 
    318 function ObjectLookupSetter(name) {
    319   var receiver = this;
    320   if (receiver == null && !IS_UNDETECTABLE(receiver)) {
    321     receiver = %GlobalProxy(global);
    322   }
    323   return %LookupAccessor(ToObject(receiver), ToName(name), SETTER);
    324 }
    325 
    326 
    327 function ObjectKeys(obj) {
    328   if (!IS_SPEC_OBJECT(obj)) {
    329     throw MakeTypeError("called_on_non_object", ["Object.keys"]);
    330   }
    331   if (%IsJSProxy(obj)) {
    332     var handler = %GetHandler(obj);
    333     var names = CallTrap0(handler, "keys", DerivedKeysTrap);
    334     return ToNameArray(names, "keys", false);
    335   }
    336   return %OwnKeys(obj);
    337 }
    338 
    339 
    340 // ES5 8.10.1.
    341 function IsAccessorDescriptor(desc) {
    342   if (IS_UNDEFINED(desc)) return false;
    343   return desc.hasGetter() || desc.hasSetter();
    344 }
    345 
    346 
    347 // ES5 8.10.2.
    348 function IsDataDescriptor(desc) {
    349   if (IS_UNDEFINED(desc)) return false;
    350   return desc.hasValue() || desc.hasWritable();
    351 }
    352 
    353 
    354 // ES5 8.10.3.
    355 function IsGenericDescriptor(desc) {
    356   if (IS_UNDEFINED(desc)) return false;
    357   return !(IsAccessorDescriptor(desc) || IsDataDescriptor(desc));
    358 }
    359 
    360 
    361 function IsInconsistentDescriptor(desc) {
    362   return IsAccessorDescriptor(desc) && IsDataDescriptor(desc);
    363 }
    364 
    365 
    366 // ES5 8.10.4
    367 function FromPropertyDescriptor(desc) {
    368   if (IS_UNDEFINED(desc)) return desc;
    369 
    370   if (IsDataDescriptor(desc)) {
    371     return { value: desc.getValue(),
    372              writable: desc.isWritable(),
    373              enumerable: desc.isEnumerable(),
    374              configurable: desc.isConfigurable() };
    375   }
    376   // Must be an AccessorDescriptor then. We never return a generic descriptor.
    377   return { get: desc.getGet(),
    378            set: desc.getSet(),
    379            enumerable: desc.isEnumerable(),
    380            configurable: desc.isConfigurable() };
    381 }
    382 
    383 
    384 // Harmony Proxies
    385 function FromGenericPropertyDescriptor(desc) {
    386   if (IS_UNDEFINED(desc)) return desc;
    387   var obj = new $Object();
    388 
    389   if (desc.hasValue()) {
    390     %AddNamedProperty(obj, "value", desc.getValue(), NONE);
    391   }
    392   if (desc.hasWritable()) {
    393     %AddNamedProperty(obj, "writable", desc.isWritable(), NONE);
    394   }
    395   if (desc.hasGetter()) {
    396     %AddNamedProperty(obj, "get", desc.getGet(), NONE);
    397   }
    398   if (desc.hasSetter()) {
    399     %AddNamedProperty(obj, "set", desc.getSet(), NONE);
    400   }
    401   if (desc.hasEnumerable()) {
    402     %AddNamedProperty(obj, "enumerable", desc.isEnumerable(), NONE);
    403   }
    404   if (desc.hasConfigurable()) {
    405     %AddNamedProperty(obj, "configurable", desc.isConfigurable(), NONE);
    406   }
    407   return obj;
    408 }
    409 
    410 
    411 // ES5 8.10.5.
    412 function ToPropertyDescriptor(obj) {
    413   if (!IS_SPEC_OBJECT(obj)) {
    414     throw MakeTypeError("property_desc_object", [obj]);
    415   }
    416   var desc = new PropertyDescriptor();
    417 
    418   if ("enumerable" in obj) {
    419     desc.setEnumerable(ToBoolean(obj.enumerable));
    420   }
    421 
    422   if ("configurable" in obj) {
    423     desc.setConfigurable(ToBoolean(obj.configurable));
    424   }
    425 
    426   if ("value" in obj) {
    427     desc.setValue(obj.value);
    428   }
    429 
    430   if ("writable" in obj) {
    431     desc.setWritable(ToBoolean(obj.writable));
    432   }
    433 
    434   if ("get" in obj) {
    435     var get = obj.get;
    436     if (!IS_UNDEFINED(get) && !IS_SPEC_FUNCTION(get)) {
    437       throw MakeTypeError("getter_must_be_callable", [get]);
    438     }
    439     desc.setGet(get);
    440   }
    441 
    442   if ("set" in obj) {
    443     var set = obj.set;
    444     if (!IS_UNDEFINED(set) && !IS_SPEC_FUNCTION(set)) {
    445       throw MakeTypeError("setter_must_be_callable", [set]);
    446     }
    447     desc.setSet(set);
    448   }
    449 
    450   if (IsInconsistentDescriptor(desc)) {
    451     throw MakeTypeError("value_and_accessor", [obj]);
    452   }
    453   return desc;
    454 }
    455 
    456 
    457 // For Harmony proxies.
    458 function ToCompletePropertyDescriptor(obj) {
    459   var desc = ToPropertyDescriptor(obj);
    460   if (IsGenericDescriptor(desc) || IsDataDescriptor(desc)) {
    461     if (!desc.hasValue()) desc.setValue(UNDEFINED);
    462     if (!desc.hasWritable()) desc.setWritable(false);
    463   } else {
    464     // Is accessor descriptor.
    465     if (!desc.hasGetter()) desc.setGet(UNDEFINED);
    466     if (!desc.hasSetter()) desc.setSet(UNDEFINED);
    467   }
    468   if (!desc.hasEnumerable()) desc.setEnumerable(false);
    469   if (!desc.hasConfigurable()) desc.setConfigurable(false);
    470   return desc;
    471 }
    472 
    473 
    474 function PropertyDescriptor() {
    475   // Initialize here so they are all in-object and have the same map.
    476   // Default values from ES5 8.6.1.
    477   this.value_ = UNDEFINED;
    478   this.hasValue_ = false;
    479   this.writable_ = false;
    480   this.hasWritable_ = false;
    481   this.enumerable_ = false;
    482   this.hasEnumerable_ = false;
    483   this.configurable_ = false;
    484   this.hasConfigurable_ = false;
    485   this.get_ = UNDEFINED;
    486   this.hasGetter_ = false;
    487   this.set_ = UNDEFINED;
    488   this.hasSetter_ = false;
    489 }
    490 
    491 SetUpLockedPrototype(PropertyDescriptor, $Array(
    492     "value_",
    493     "hasValue_",
    494     "writable_",
    495     "hasWritable_",
    496     "enumerable_",
    497     "hasEnumerable_",
    498     "configurable_",
    499     "hasConfigurable_",
    500     "get_",
    501     "hasGetter_",
    502     "set_",
    503     "hasSetter_"
    504   ), $Array(
    505     "toString", function() {
    506       return "[object PropertyDescriptor]";
    507     },
    508     "setValue", function(value) {
    509       this.value_ = value;
    510       this.hasValue_ = true;
    511     },
    512     "getValue", function() {
    513       return this.value_;
    514     },
    515     "hasValue", function() {
    516       return this.hasValue_;
    517     },
    518     "setEnumerable", function(enumerable) {
    519       this.enumerable_ = enumerable;
    520         this.hasEnumerable_ = true;
    521     },
    522     "isEnumerable", function () {
    523       return this.enumerable_;
    524     },
    525     "hasEnumerable", function() {
    526       return this.hasEnumerable_;
    527     },
    528     "setWritable", function(writable) {
    529       this.writable_ = writable;
    530       this.hasWritable_ = true;
    531     },
    532     "isWritable", function() {
    533       return this.writable_;
    534     },
    535     "hasWritable", function() {
    536       return this.hasWritable_;
    537     },
    538     "setConfigurable", function(configurable) {
    539       this.configurable_ = configurable;
    540       this.hasConfigurable_ = true;
    541     },
    542     "hasConfigurable", function() {
    543       return this.hasConfigurable_;
    544     },
    545     "isConfigurable", function() {
    546       return this.configurable_;
    547     },
    548     "setGet", function(get) {
    549       this.get_ = get;
    550         this.hasGetter_ = true;
    551     },
    552     "getGet", function() {
    553       return this.get_;
    554     },
    555     "hasGetter", function() {
    556       return this.hasGetter_;
    557     },
    558     "setSet", function(set) {
    559       this.set_ = set;
    560       this.hasSetter_ = true;
    561     },
    562     "getSet", function() {
    563       return this.set_;
    564     },
    565     "hasSetter", function() {
    566       return this.hasSetter_;
    567   }));
    568 
    569 
    570 // Converts an array returned from Runtime_GetOwnProperty to an actual
    571 // property descriptor. For a description of the array layout please
    572 // see the runtime.cc file.
    573 function ConvertDescriptorArrayToDescriptor(desc_array) {
    574   if (IS_UNDEFINED(desc_array)) {
    575     return UNDEFINED;
    576   }
    577 
    578   var desc = new PropertyDescriptor();
    579   // This is an accessor.
    580   if (desc_array[IS_ACCESSOR_INDEX]) {
    581     desc.setGet(desc_array[GETTER_INDEX]);
    582     desc.setSet(desc_array[SETTER_INDEX]);
    583   } else {
    584     desc.setValue(desc_array[VALUE_INDEX]);
    585     desc.setWritable(desc_array[WRITABLE_INDEX]);
    586   }
    587   desc.setEnumerable(desc_array[ENUMERABLE_INDEX]);
    588   desc.setConfigurable(desc_array[CONFIGURABLE_INDEX]);
    589 
    590   return desc;
    591 }
    592 
    593 
    594 // For Harmony proxies.
    595 function GetTrap(handler, name, defaultTrap) {
    596   var trap = handler[name];
    597   if (IS_UNDEFINED(trap)) {
    598     if (IS_UNDEFINED(defaultTrap)) {
    599       throw MakeTypeError("handler_trap_missing", [handler, name]);
    600     }
    601     trap = defaultTrap;
    602   } else if (!IS_SPEC_FUNCTION(trap)) {
    603     throw MakeTypeError("handler_trap_must_be_callable", [handler, name]);
    604   }
    605   return trap;
    606 }
    607 
    608 
    609 function CallTrap0(handler, name, defaultTrap) {
    610   return %_CallFunction(handler, GetTrap(handler, name, defaultTrap));
    611 }
    612 
    613 
    614 function CallTrap1(handler, name, defaultTrap, x) {
    615   return %_CallFunction(handler, x, GetTrap(handler, name, defaultTrap));
    616 }
    617 
    618 
    619 function CallTrap2(handler, name, defaultTrap, x, y) {
    620   return %_CallFunction(handler, x, y, GetTrap(handler, name, defaultTrap));
    621 }
    622 
    623 
    624 // ES5 section 8.12.1.
    625 function GetOwnPropertyJS(obj, v) {
    626   var p = ToName(v);
    627   if (%IsJSProxy(obj)) {
    628     // TODO(rossberg): adjust once there is a story for symbols vs proxies.
    629     if (IS_SYMBOL(v)) return UNDEFINED;
    630 
    631     var handler = %GetHandler(obj);
    632     var descriptor = CallTrap1(
    633                          handler, "getOwnPropertyDescriptor", UNDEFINED, p);
    634     if (IS_UNDEFINED(descriptor)) return descriptor;
    635     var desc = ToCompletePropertyDescriptor(descriptor);
    636     if (!desc.isConfigurable()) {
    637       throw MakeTypeError("proxy_prop_not_configurable",
    638                           [handler, "getOwnPropertyDescriptor", p, descriptor]);
    639     }
    640     return desc;
    641   }
    642 
    643   // GetOwnProperty returns an array indexed by the constants
    644   // defined in macros.py.
    645   // If p is not a property on obj undefined is returned.
    646   var props = %GetOwnProperty(ToObject(obj), p);
    647 
    648   return ConvertDescriptorArrayToDescriptor(props);
    649 }
    650 
    651 
    652 // ES5 section 8.12.7.
    653 function Delete(obj, p, should_throw) {
    654   var desc = GetOwnPropertyJS(obj, p);
    655   if (IS_UNDEFINED(desc)) return true;
    656   if (desc.isConfigurable()) {
    657     %DeleteProperty(obj, p, 0);
    658     return true;
    659   } else if (should_throw) {
    660     throw MakeTypeError("define_disallowed", [p]);
    661   } else {
    662     return;
    663   }
    664 }
    665 
    666 
    667 // Harmony proxies.
    668 function DefineProxyProperty(obj, p, attributes, should_throw) {
    669   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
    670   if (IS_SYMBOL(p)) return false;
    671 
    672   var handler = %GetHandler(obj);
    673   var result = CallTrap2(handler, "defineProperty", UNDEFINED, p, attributes);
    674   if (!ToBoolean(result)) {
    675     if (should_throw) {
    676       throw MakeTypeError("handler_returned_false",
    677                           [handler, "defineProperty"]);
    678     } else {
    679       return false;
    680     }
    681   }
    682   return true;
    683 }
    684 
    685 
    686 // ES5 8.12.9.
    687 function DefineObjectProperty(obj, p, desc, should_throw) {
    688   var current_array = %GetOwnProperty(ToObject(obj), ToName(p));
    689   var current = ConvertDescriptorArrayToDescriptor(current_array);
    690   var extensible = %IsExtensible(ToObject(obj));
    691 
    692   // Error handling according to spec.
    693   // Step 3
    694   if (IS_UNDEFINED(current) && !extensible) {
    695     if (should_throw) {
    696       throw MakeTypeError("define_disallowed", [p]);
    697     } else {
    698       return false;
    699     }
    700   }
    701 
    702   if (!IS_UNDEFINED(current)) {
    703     // Step 5 and 6
    704     if ((IsGenericDescriptor(desc) ||
    705          IsDataDescriptor(desc) == IsDataDescriptor(current)) &&
    706         (!desc.hasEnumerable() ||
    707          SameValue(desc.isEnumerable(), current.isEnumerable())) &&
    708         (!desc.hasConfigurable() ||
    709          SameValue(desc.isConfigurable(), current.isConfigurable())) &&
    710         (!desc.hasWritable() ||
    711          SameValue(desc.isWritable(), current.isWritable())) &&
    712         (!desc.hasValue() ||
    713          SameValue(desc.getValue(), current.getValue())) &&
    714         (!desc.hasGetter() ||
    715          SameValue(desc.getGet(), current.getGet())) &&
    716         (!desc.hasSetter() ||
    717          SameValue(desc.getSet(), current.getSet()))) {
    718       return true;
    719     }
    720     if (!current.isConfigurable()) {
    721       // Step 7
    722       if (desc.isConfigurable() ||
    723           (desc.hasEnumerable() &&
    724            desc.isEnumerable() != current.isEnumerable())) {
    725         if (should_throw) {
    726           throw MakeTypeError("redefine_disallowed", [p]);
    727         } else {
    728           return false;
    729         }
    730       }
    731       // Step 8
    732       if (!IsGenericDescriptor(desc)) {
    733         // Step 9a
    734         if (IsDataDescriptor(current) != IsDataDescriptor(desc)) {
    735           if (should_throw) {
    736             throw MakeTypeError("redefine_disallowed", [p]);
    737           } else {
    738             return false;
    739           }
    740         }
    741         // Step 10a
    742         if (IsDataDescriptor(current) && IsDataDescriptor(desc)) {
    743           if (!current.isWritable() && desc.isWritable()) {
    744             if (should_throw) {
    745               throw MakeTypeError("redefine_disallowed", [p]);
    746             } else {
    747               return false;
    748             }
    749           }
    750           if (!current.isWritable() && desc.hasValue() &&
    751               !SameValue(desc.getValue(), current.getValue())) {
    752             if (should_throw) {
    753               throw MakeTypeError("redefine_disallowed", [p]);
    754             } else {
    755               return false;
    756             }
    757           }
    758         }
    759         // Step 11
    760         if (IsAccessorDescriptor(desc) && IsAccessorDescriptor(current)) {
    761           if (desc.hasSetter() && !SameValue(desc.getSet(), current.getSet())) {
    762             if (should_throw) {
    763               throw MakeTypeError("redefine_disallowed", [p]);
    764             } else {
    765               return false;
    766             }
    767           }
    768           if (desc.hasGetter() && !SameValue(desc.getGet(),current.getGet())) {
    769             if (should_throw) {
    770               throw MakeTypeError("redefine_disallowed", [p]);
    771             } else {
    772               return false;
    773             }
    774           }
    775         }
    776       }
    777     }
    778   }
    779 
    780   // Send flags - enumerable and configurable are common - writable is
    781   // only send to the data descriptor.
    782   // Take special care if enumerable and configurable is not defined on
    783   // desc (we need to preserve the existing values from current).
    784   var flag = NONE;
    785   if (desc.hasEnumerable()) {
    786     flag |= desc.isEnumerable() ? 0 : DONT_ENUM;
    787   } else if (!IS_UNDEFINED(current)) {
    788     flag |= current.isEnumerable() ? 0 : DONT_ENUM;
    789   } else {
    790     flag |= DONT_ENUM;
    791   }
    792 
    793   if (desc.hasConfigurable()) {
    794     flag |= desc.isConfigurable() ? 0 : DONT_DELETE;
    795   } else if (!IS_UNDEFINED(current)) {
    796     flag |= current.isConfigurable() ? 0 : DONT_DELETE;
    797   } else
    798     flag |= DONT_DELETE;
    799 
    800   if (IsDataDescriptor(desc) ||
    801       (IsGenericDescriptor(desc) &&
    802        (IS_UNDEFINED(current) || IsDataDescriptor(current)))) {
    803     // There are 3 cases that lead here:
    804     // Step 4a - defining a new data property.
    805     // Steps 9b & 12 - replacing an existing accessor property with a data
    806     //                 property.
    807     // Step 12 - updating an existing data property with a data or generic
    808     //           descriptor.
    809 
    810     if (desc.hasWritable()) {
    811       flag |= desc.isWritable() ? 0 : READ_ONLY;
    812     } else if (!IS_UNDEFINED(current)) {
    813       flag |= current.isWritable() ? 0 : READ_ONLY;
    814     } else {
    815       flag |= READ_ONLY;
    816     }
    817 
    818     var value = UNDEFINED;  // Default value is undefined.
    819     if (desc.hasValue()) {
    820       value = desc.getValue();
    821     } else if (!IS_UNDEFINED(current) && IsDataDescriptor(current)) {
    822       value = current.getValue();
    823     }
    824 
    825     %DefineDataPropertyUnchecked(obj, p, value, flag);
    826   } else {
    827     // There are 3 cases that lead here:
    828     // Step 4b - defining a new accessor property.
    829     // Steps 9c & 12 - replacing an existing data property with an accessor
    830     //                 property.
    831     // Step 12 - updating an existing accessor property with an accessor
    832     //           descriptor.
    833     var getter = null;
    834     if (desc.hasGetter()) {
    835       getter = desc.getGet();
    836     } else if (IsAccessorDescriptor(current) && current.hasGetter()) {
    837       getter = current.getGet();
    838     }
    839     var setter = null;
    840     if (desc.hasSetter()) {
    841       setter = desc.getSet();
    842     } else if (IsAccessorDescriptor(current) && current.hasSetter()) {
    843       setter = current.getSet();
    844     }
    845     %DefineAccessorPropertyUnchecked(obj, p, getter, setter, flag);
    846   }
    847   return true;
    848 }
    849 
    850 
    851 // ES5 section 15.4.5.1.
    852 function DefineArrayProperty(obj, p, desc, should_throw) {
    853   // Note that the length of an array is not actually stored as part of the
    854   // property, hence we use generated code throughout this function instead of
    855   // DefineObjectProperty() to modify its value.
    856 
    857   // Step 3 - Special handling for length property.
    858   if (p === "length") {
    859     var length = obj.length;
    860     var old_length = length;
    861     if (!desc.hasValue()) {
    862       return DefineObjectProperty(obj, "length", desc, should_throw);
    863     }
    864     var new_length = ToUint32(desc.getValue());
    865     if (new_length != ToNumber(desc.getValue())) {
    866       throw new $RangeError('defineProperty() array length out of range');
    867     }
    868     var length_desc = GetOwnPropertyJS(obj, "length");
    869     if (new_length != length && !length_desc.isWritable()) {
    870       if (should_throw) {
    871         throw MakeTypeError("redefine_disallowed", [p]);
    872       } else {
    873         return false;
    874       }
    875     }
    876     var threw = false;
    877 
    878     var emit_splice = %IsObserved(obj) && new_length !== old_length;
    879     var removed;
    880     if (emit_splice) {
    881       BeginPerformSplice(obj);
    882       removed = [];
    883       if (new_length < old_length)
    884         removed.length = old_length - new_length;
    885     }
    886 
    887     while (new_length < length--) {
    888       var index = ToString(length);
    889       if (emit_splice) {
    890         var deletedDesc = GetOwnPropertyJS(obj, index);
    891         if (deletedDesc && deletedDesc.hasValue())
    892           removed[length - new_length] = deletedDesc.getValue();
    893       }
    894       if (!Delete(obj, index, false)) {
    895         new_length = length + 1;
    896         threw = true;
    897         break;
    898       }
    899     }
    900     // Make sure the below call to DefineObjectProperty() doesn't overwrite
    901     // any magic "length" property by removing the value.
    902     // TODO(mstarzinger): This hack should be removed once we have addressed the
    903     // respective TODO in Runtime_DefineDataPropertyUnchecked.
    904     // For the time being, we need a hack to prevent Object.observe from
    905     // generating two change records.
    906     obj.length = new_length;
    907     desc.value_ = UNDEFINED;
    908     desc.hasValue_ = false;
    909     threw = !DefineObjectProperty(obj, "length", desc, should_throw) || threw;
    910     if (emit_splice) {
    911       EndPerformSplice(obj);
    912       EnqueueSpliceRecord(obj,
    913           new_length < old_length ? new_length : old_length,
    914           removed,
    915           new_length > old_length ? new_length - old_length : 0);
    916     }
    917     if (threw) {
    918       if (should_throw) {
    919         throw MakeTypeError("redefine_disallowed", [p]);
    920       } else {
    921         return false;
    922       }
    923     }
    924     return true;
    925   }
    926 
    927   // Step 4 - Special handling for array index.
    928   if (!IS_SYMBOL(p)) {
    929     var index = ToUint32(p);
    930     var emit_splice = false;
    931     if (ToString(index) == p && index != 4294967295) {
    932       var length = obj.length;
    933       if (index >= length && %IsObserved(obj)) {
    934         emit_splice = true;
    935         BeginPerformSplice(obj);
    936       }
    937 
    938       var length_desc = GetOwnPropertyJS(obj, "length");
    939       if ((index >= length && !length_desc.isWritable()) ||
    940           !DefineObjectProperty(obj, p, desc, true)) {
    941         if (emit_splice)
    942           EndPerformSplice(obj);
    943         if (should_throw) {
    944           throw MakeTypeError("define_disallowed", [p]);
    945         } else {
    946           return false;
    947         }
    948       }
    949       if (index >= length) {
    950         obj.length = index + 1;
    951       }
    952       if (emit_splice) {
    953         EndPerformSplice(obj);
    954         EnqueueSpliceRecord(obj, length, [], index + 1 - length);
    955       }
    956       return true;
    957     }
    958   }
    959 
    960   // Step 5 - Fallback to default implementation.
    961   return DefineObjectProperty(obj, p, desc, should_throw);
    962 }
    963 
    964 
    965 // ES5 section 8.12.9, ES5 section 15.4.5.1 and Harmony proxies.
    966 function DefineOwnProperty(obj, p, desc, should_throw) {
    967   if (%IsJSProxy(obj)) {
    968     // TODO(rossberg): adjust once there is a story for symbols vs proxies.
    969     if (IS_SYMBOL(p)) return false;
    970 
    971     var attributes = FromGenericPropertyDescriptor(desc);
    972     return DefineProxyProperty(obj, p, attributes, should_throw);
    973   } else if (IS_ARRAY(obj)) {
    974     return DefineArrayProperty(obj, p, desc, should_throw);
    975   } else {
    976     return DefineObjectProperty(obj, p, desc, should_throw);
    977   }
    978 }
    979 
    980 
    981 // ES5 section 15.2.3.2.
    982 function ObjectGetPrototypeOf(obj) {
    983   if (!IS_SPEC_OBJECT(obj)) {
    984     throw MakeTypeError("called_on_non_object", ["Object.getPrototypeOf"]);
    985   }
    986   return %GetPrototype(obj);
    987 }
    988 
    989 // ES6 section 19.1.2.19.
    990 function ObjectSetPrototypeOf(obj, proto) {
    991   CHECK_OBJECT_COERCIBLE(obj, "Object.setPrototypeOf");
    992 
    993   if (proto !== null && !IS_SPEC_OBJECT(proto)) {
    994     throw MakeTypeError("proto_object_or_null", [proto]);
    995   }
    996 
    997   if (IS_SPEC_OBJECT(obj)) {
    998     %SetPrototype(obj, proto);
    999   }
   1000 
   1001   return obj;
   1002 }
   1003 
   1004 
   1005 // ES5 section 15.2.3.3
   1006 function ObjectGetOwnPropertyDescriptor(obj, p) {
   1007   if (!IS_SPEC_OBJECT(obj)) {
   1008     throw MakeTypeError("called_on_non_object",
   1009                         ["Object.getOwnPropertyDescriptor"]);
   1010   }
   1011   var desc = GetOwnPropertyJS(obj, p);
   1012   return FromPropertyDescriptor(desc);
   1013 }
   1014 
   1015 
   1016 // For Harmony proxies
   1017 function ToNameArray(obj, trap, includeSymbols) {
   1018   if (!IS_SPEC_OBJECT(obj)) {
   1019     throw MakeTypeError("proxy_non_object_prop_names", [obj, trap]);
   1020   }
   1021   var n = ToUint32(obj.length);
   1022   var array = new $Array(n);
   1023   var realLength = 0;
   1024   var names = { __proto__: null };  // TODO(rossberg): use sets once ready.
   1025   for (var index = 0; index < n; index++) {
   1026     var s = ToName(obj[index]);
   1027     // TODO(rossberg): adjust once there is a story for symbols vs proxies.
   1028     if (IS_SYMBOL(s) && !includeSymbols) continue;
   1029     if (%HasOwnProperty(names, s)) {
   1030       throw MakeTypeError("proxy_repeated_prop_name", [obj, trap, s]);
   1031     }
   1032     array[index] = s;
   1033     ++realLength;
   1034     names[s] = 0;
   1035   }
   1036   array.length = realLength;
   1037   return array;
   1038 }
   1039 
   1040 
   1041 function ObjectGetOwnPropertyKeys(obj, symbolsOnly) {
   1042   var nameArrays = new InternalArray();
   1043   var filter = symbolsOnly ?
   1044       PROPERTY_ATTRIBUTES_STRING | PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL :
   1045       PROPERTY_ATTRIBUTES_SYMBOLIC;
   1046 
   1047   // Find all the indexed properties.
   1048 
   1049   // Only get own element names if we want to include string keys.
   1050   if (!symbolsOnly) {
   1051     var ownElementNames = %GetOwnElementNames(obj);
   1052     for (var i = 0; i < ownElementNames.length; ++i) {
   1053       ownElementNames[i] = %_NumberToString(ownElementNames[i]);
   1054     }
   1055     nameArrays.push(ownElementNames);
   1056 
   1057     // Get names for indexed interceptor properties.
   1058     var interceptorInfo = %GetInterceptorInfo(obj);
   1059     if ((interceptorInfo & 1) != 0) {
   1060       var indexedInterceptorNames = %GetIndexedInterceptorElementNames(obj);
   1061       if (!IS_UNDEFINED(indexedInterceptorNames)) {
   1062         nameArrays.push(indexedInterceptorNames);
   1063       }
   1064     }
   1065   }
   1066 
   1067   // Find all the named properties.
   1068 
   1069   // Get own property names.
   1070   nameArrays.push(%GetOwnPropertyNames(obj, filter));
   1071 
   1072   // Get names for named interceptor properties if any.
   1073   if ((interceptorInfo & 2) != 0) {
   1074     var namedInterceptorNames =
   1075         %GetNamedInterceptorPropertyNames(obj);
   1076     if (!IS_UNDEFINED(namedInterceptorNames)) {
   1077       nameArrays.push(namedInterceptorNames);
   1078     }
   1079   }
   1080 
   1081   var propertyNames =
   1082       %Apply(InternalArray.prototype.concat,
   1083              nameArrays[0], nameArrays, 1, nameArrays.length - 1);
   1084 
   1085   // Property names are expected to be unique strings,
   1086   // but interceptors can interfere with that assumption.
   1087   if (interceptorInfo != 0) {
   1088     var seenKeys = { __proto__: null };
   1089     var j = 0;
   1090     for (var i = 0; i < propertyNames.length; ++i) {
   1091       var name = propertyNames[i];
   1092       if (symbolsOnly) {
   1093         if (!IS_SYMBOL(name) || IS_PRIVATE(name)) continue;
   1094       } else {
   1095         if (IS_SYMBOL(name)) continue;
   1096         name = ToString(name);
   1097       }
   1098       if (seenKeys[name]) continue;
   1099       seenKeys[name] = true;
   1100       propertyNames[j++] = name;
   1101     }
   1102     propertyNames.length = j;
   1103   }
   1104 
   1105   return propertyNames;
   1106 }
   1107 
   1108 
   1109 // ES5 section 15.2.3.4.
   1110 function ObjectGetOwnPropertyNames(obj) {
   1111   if (!IS_SPEC_OBJECT(obj)) {
   1112     throw MakeTypeError("called_on_non_object", ["Object.getOwnPropertyNames"]);
   1113   }
   1114   // Special handling for proxies.
   1115   if (%IsJSProxy(obj)) {
   1116     var handler = %GetHandler(obj);
   1117     var names = CallTrap0(handler, "getOwnPropertyNames", UNDEFINED);
   1118     return ToNameArray(names, "getOwnPropertyNames", false);
   1119   }
   1120 
   1121   return ObjectGetOwnPropertyKeys(obj, false);
   1122 }
   1123 
   1124 
   1125 // ES5 section 15.2.3.5.
   1126 function ObjectCreate(proto, properties) {
   1127   if (!IS_SPEC_OBJECT(proto) && proto !== null) {
   1128     throw MakeTypeError("proto_object_or_null", [proto]);
   1129   }
   1130   var obj = {};
   1131   %InternalSetPrototype(obj, proto);
   1132   if (!IS_UNDEFINED(properties)) ObjectDefineProperties(obj, properties);
   1133   return obj;
   1134 }
   1135 
   1136 
   1137 // ES5 section 15.2.3.6.
   1138 function ObjectDefineProperty(obj, p, attributes) {
   1139   if (!IS_SPEC_OBJECT(obj)) {
   1140     throw MakeTypeError("called_on_non_object", ["Object.defineProperty"]);
   1141   }
   1142   var name = ToName(p);
   1143   if (%IsJSProxy(obj)) {
   1144     // Clone the attributes object for protection.
   1145     // TODO(rossberg): not spec'ed yet, so not sure if this should involve
   1146     // non-own properties as it does (or non-enumerable ones, as it doesn't?).
   1147     var attributesClone = { __proto__: null };
   1148     for (var a in attributes) {
   1149       attributesClone[a] = attributes[a];
   1150     }
   1151     DefineProxyProperty(obj, name, attributesClone, true);
   1152     // The following would implement the spec as in the current proposal,
   1153     // but after recent comments on es-discuss, is most likely obsolete.
   1154     /*
   1155     var defineObj = FromGenericPropertyDescriptor(desc);
   1156     var names = ObjectGetOwnPropertyNames(attributes);
   1157     var standardNames =
   1158       {value: 0, writable: 0, get: 0, set: 0, enumerable: 0, configurable: 0};
   1159     for (var i = 0; i < names.length; i++) {
   1160       var N = names[i];
   1161       if (!(%HasOwnProperty(standardNames, N))) {
   1162         var attr = GetOwnPropertyJS(attributes, N);
   1163         DefineOwnProperty(descObj, N, attr, true);
   1164       }
   1165     }
   1166     // This is really confusing the types, but it is what the proxies spec
   1167     // currently requires:
   1168     desc = descObj;
   1169     */
   1170   } else {
   1171     var desc = ToPropertyDescriptor(attributes);
   1172     DefineOwnProperty(obj, name, desc, true);
   1173   }
   1174   return obj;
   1175 }
   1176 
   1177 
   1178 function GetOwnEnumerablePropertyNames(object) {
   1179   var names = new InternalArray();
   1180   for (var key in object) {
   1181     if (%HasOwnProperty(object, key)) {
   1182       names.push(key);
   1183     }
   1184   }
   1185 
   1186   var filter = PROPERTY_ATTRIBUTES_STRING | PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL;
   1187   var symbols = %GetOwnPropertyNames(object, filter);
   1188   for (var i = 0; i < symbols.length; ++i) {
   1189     var symbol = symbols[i];
   1190     if (IS_SYMBOL(symbol)) {
   1191       var desc = ObjectGetOwnPropertyDescriptor(object, symbol);
   1192       if (desc.enumerable) names.push(symbol);
   1193     }
   1194   }
   1195 
   1196   return names;
   1197 }
   1198 
   1199 
   1200 // ES5 section 15.2.3.7.
   1201 function ObjectDefineProperties(obj, properties) {
   1202   if (!IS_SPEC_OBJECT(obj)) {
   1203     throw MakeTypeError("called_on_non_object", ["Object.defineProperties"]);
   1204   }
   1205   var props = ToObject(properties);
   1206   var names = GetOwnEnumerablePropertyNames(props);
   1207   var descriptors = new InternalArray();
   1208   for (var i = 0; i < names.length; i++) {
   1209     descriptors.push(ToPropertyDescriptor(props[names[i]]));
   1210   }
   1211   for (var i = 0; i < names.length; i++) {
   1212     DefineOwnProperty(obj, names[i], descriptors[i], true);
   1213   }
   1214   return obj;
   1215 }
   1216 
   1217 
   1218 // Harmony proxies.
   1219 function ProxyFix(obj) {
   1220   var handler = %GetHandler(obj);
   1221   var props = CallTrap0(handler, "fix", UNDEFINED);
   1222   if (IS_UNDEFINED(props)) {
   1223     throw MakeTypeError("handler_returned_undefined", [handler, "fix"]);
   1224   }
   1225 
   1226   if (%IsJSFunctionProxy(obj)) {
   1227     var callTrap = %GetCallTrap(obj);
   1228     var constructTrap = %GetConstructTrap(obj);
   1229     var code = DelegateCallAndConstruct(callTrap, constructTrap);
   1230     %Fix(obj);  // becomes a regular function
   1231     %SetCode(obj, code);
   1232     // TODO(rossberg): What about length and other properties? Not specified.
   1233     // We just put in some half-reasonable defaults for now.
   1234     var prototype = new $Object();
   1235     $Object.defineProperty(prototype, "constructor",
   1236       {value: obj, writable: true, enumerable: false, configurable: true});
   1237     // TODO(v8:1530): defineProperty does not handle prototype and length.
   1238     %FunctionSetPrototype(obj, prototype);
   1239     obj.length = 0;
   1240   } else {
   1241     %Fix(obj);
   1242   }
   1243   ObjectDefineProperties(obj, props);
   1244 }
   1245 
   1246 
   1247 // ES5 section 15.2.3.8.
   1248 function ObjectSeal(obj) {
   1249   if (!IS_SPEC_OBJECT(obj)) {
   1250     throw MakeTypeError("called_on_non_object", ["Object.seal"]);
   1251   }
   1252   if (%IsJSProxy(obj)) {
   1253     ProxyFix(obj);
   1254   }
   1255   var names = ObjectGetOwnPropertyNames(obj);
   1256   for (var i = 0; i < names.length; i++) {
   1257     var name = names[i];
   1258     var desc = GetOwnPropertyJS(obj, name);
   1259     if (desc.isConfigurable()) {
   1260       desc.setConfigurable(false);
   1261       DefineOwnProperty(obj, name, desc, true);
   1262     }
   1263   }
   1264   %PreventExtensions(obj);
   1265   return obj;
   1266 }
   1267 
   1268 
   1269 // ES5 section 15.2.3.9.
   1270 function ObjectFreezeJS(obj) {
   1271   if (!IS_SPEC_OBJECT(obj)) {
   1272     throw MakeTypeError("called_on_non_object", ["Object.freeze"]);
   1273   }
   1274   var isProxy = %IsJSProxy(obj);
   1275   if (isProxy || %HasSloppyArgumentsElements(obj) || %IsObserved(obj)) {
   1276     if (isProxy) {
   1277       ProxyFix(obj);
   1278     }
   1279     var names = ObjectGetOwnPropertyNames(obj);
   1280     for (var i = 0; i < names.length; i++) {
   1281       var name = names[i];
   1282       var desc = GetOwnPropertyJS(obj, name);
   1283       if (desc.isWritable() || desc.isConfigurable()) {
   1284         if (IsDataDescriptor(desc)) desc.setWritable(false);
   1285         desc.setConfigurable(false);
   1286         DefineOwnProperty(obj, name, desc, true);
   1287       }
   1288     }
   1289     %PreventExtensions(obj);
   1290   } else {
   1291     // TODO(adamk): Is it worth going to this fast path if the
   1292     // object's properties are already in dictionary mode?
   1293     %ObjectFreeze(obj);
   1294   }
   1295   return obj;
   1296 }
   1297 
   1298 
   1299 // ES5 section 15.2.3.10
   1300 function ObjectPreventExtension(obj) {
   1301   if (!IS_SPEC_OBJECT(obj)) {
   1302     throw MakeTypeError("called_on_non_object", ["Object.preventExtension"]);
   1303   }
   1304   if (%IsJSProxy(obj)) {
   1305     ProxyFix(obj);
   1306   }
   1307   %PreventExtensions(obj);
   1308   return obj;
   1309 }
   1310 
   1311 
   1312 // ES5 section 15.2.3.11
   1313 function ObjectIsSealed(obj) {
   1314   if (!IS_SPEC_OBJECT(obj)) {
   1315     throw MakeTypeError("called_on_non_object", ["Object.isSealed"]);
   1316   }
   1317   if (%IsJSProxy(obj)) {
   1318     return false;
   1319   }
   1320   if (%IsExtensible(obj)) {
   1321     return false;
   1322   }
   1323   var names = ObjectGetOwnPropertyNames(obj);
   1324   for (var i = 0; i < names.length; i++) {
   1325     var name = names[i];
   1326     var desc = GetOwnPropertyJS(obj, name);
   1327     if (desc.isConfigurable()) {
   1328       return false;
   1329     }
   1330   }
   1331   return true;
   1332 }
   1333 
   1334 
   1335 // ES5 section 15.2.3.12
   1336 function ObjectIsFrozen(obj) {
   1337   if (!IS_SPEC_OBJECT(obj)) {
   1338     throw MakeTypeError("called_on_non_object", ["Object.isFrozen"]);
   1339   }
   1340   if (%IsJSProxy(obj)) {
   1341     return false;
   1342   }
   1343   if (%IsExtensible(obj)) {
   1344     return false;
   1345   }
   1346   var names = ObjectGetOwnPropertyNames(obj);
   1347   for (var i = 0; i < names.length; i++) {
   1348     var name = names[i];
   1349     var desc = GetOwnPropertyJS(obj, name);
   1350     if (IsDataDescriptor(desc) && desc.isWritable()) return false;
   1351     if (desc.isConfigurable()) return false;
   1352   }
   1353   return true;
   1354 }
   1355 
   1356 
   1357 // ES5 section 15.2.3.13
   1358 function ObjectIsExtensible(obj) {
   1359   if (!IS_SPEC_OBJECT(obj)) {
   1360     throw MakeTypeError("called_on_non_object", ["Object.isExtensible"]);
   1361   }
   1362   if (%IsJSProxy(obj)) {
   1363     return true;
   1364   }
   1365   return %IsExtensible(obj);
   1366 }
   1367 
   1368 
   1369 // Harmony egal.
   1370 function ObjectIs(obj1, obj2) {
   1371   if (obj1 === obj2) {
   1372     return (obj1 !== 0) || (1 / obj1 === 1 / obj2);
   1373   } else {
   1374     return (obj1 !== obj1) && (obj2 !== obj2);
   1375   }
   1376 }
   1377 
   1378 
   1379 // ECMA-262, Edition 6, section B.2.2.1.1
   1380 function ObjectGetProto() {
   1381   return %GetPrototype(ToObject(this));
   1382 }
   1383 
   1384 
   1385 // ECMA-262, Edition 6, section B.2.2.1.2
   1386 function ObjectSetProto(proto) {
   1387   CHECK_OBJECT_COERCIBLE(this, "Object.prototype.__proto__");
   1388 
   1389   if ((IS_SPEC_OBJECT(proto) || IS_NULL(proto)) && IS_SPEC_OBJECT(this)) {
   1390     %SetPrototype(this, proto);
   1391   }
   1392 }
   1393 
   1394 
   1395 function ObjectConstructor(x) {
   1396   if (%_IsConstructCall()) {
   1397     if (x == null) return this;
   1398     return ToObject(x);
   1399   } else {
   1400     if (x == null) return { };
   1401     return ToObject(x);
   1402   }
   1403 }
   1404 
   1405 
   1406 // ----------------------------------------------------------------------------
   1407 // Object
   1408 
   1409 function SetUpObject() {
   1410   %CheckIsBootstrapping();
   1411 
   1412   %SetNativeFlag($Object);
   1413   %SetCode($Object, ObjectConstructor);
   1414 
   1415   %AddNamedProperty($Object.prototype, "constructor", $Object, DONT_ENUM);
   1416 
   1417   // Set up non-enumerable functions on the Object.prototype object.
   1418   InstallFunctions($Object.prototype, DONT_ENUM, $Array(
   1419     "toString", ObjectToString,
   1420     "toLocaleString", ObjectToLocaleString,
   1421     "valueOf", ObjectValueOf,
   1422     "hasOwnProperty", ObjectHasOwnProperty,
   1423     "isPrototypeOf", ObjectIsPrototypeOf,
   1424     "propertyIsEnumerable", ObjectPropertyIsEnumerable,
   1425     "__defineGetter__", ObjectDefineGetter,
   1426     "__lookupGetter__", ObjectLookupGetter,
   1427     "__defineSetter__", ObjectDefineSetter,
   1428     "__lookupSetter__", ObjectLookupSetter
   1429   ));
   1430   InstallGetterSetter($Object.prototype, "__proto__",
   1431                       ObjectGetProto, ObjectSetProto);
   1432 
   1433   // Set up non-enumerable functions in the Object object.
   1434   InstallFunctions($Object, DONT_ENUM, $Array(
   1435     "keys", ObjectKeys,
   1436     "create", ObjectCreate,
   1437     "defineProperty", ObjectDefineProperty,
   1438     "defineProperties", ObjectDefineProperties,
   1439     "freeze", ObjectFreezeJS,
   1440     "getPrototypeOf", ObjectGetPrototypeOf,
   1441     "setPrototypeOf", ObjectSetPrototypeOf,
   1442     "getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor,
   1443     "getOwnPropertyNames", ObjectGetOwnPropertyNames,
   1444     // getOwnPropertySymbols is added in symbol.js.
   1445     "is", ObjectIs,
   1446     "isExtensible", ObjectIsExtensible,
   1447     "isFrozen", ObjectIsFrozen,
   1448     "isSealed", ObjectIsSealed,
   1449     "preventExtensions", ObjectPreventExtension,
   1450     "seal", ObjectSeal
   1451     // deliverChangeRecords, getNotifier, observe and unobserve are added
   1452     // in object-observe.js.
   1453   ));
   1454 }
   1455 
   1456 SetUpObject();
   1457 
   1458 
   1459 // ----------------------------------------------------------------------------
   1460 // Boolean
   1461 
   1462 function BooleanConstructor(x) {
   1463   if (%_IsConstructCall()) {
   1464     %_SetValueOf(this, ToBoolean(x));
   1465   } else {
   1466     return ToBoolean(x);
   1467   }
   1468 }
   1469 
   1470 
   1471 function BooleanToString() {
   1472   // NOTE: Both Boolean objects and values can enter here as
   1473   // 'this'. This is not as dictated by ECMA-262.
   1474   var b = this;
   1475   if (!IS_BOOLEAN(b)) {
   1476     if (!IS_BOOLEAN_WRAPPER(b)) {
   1477       throw new $TypeError('Boolean.prototype.toString is not generic');
   1478     }
   1479     b = %_ValueOf(b);
   1480   }
   1481   return b ? 'true' : 'false';
   1482 }
   1483 
   1484 
   1485 function BooleanValueOf() {
   1486   // NOTE: Both Boolean objects and values can enter here as
   1487   // 'this'. This is not as dictated by ECMA-262.
   1488   if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this)) {
   1489     throw new $TypeError('Boolean.prototype.valueOf is not generic');
   1490   }
   1491   return %_ValueOf(this);
   1492 }
   1493 
   1494 
   1495 // ----------------------------------------------------------------------------
   1496 
   1497 function SetUpBoolean () {
   1498   %CheckIsBootstrapping();
   1499 
   1500   %SetCode($Boolean, BooleanConstructor);
   1501   %FunctionSetPrototype($Boolean, new $Boolean(false));
   1502   %AddNamedProperty($Boolean.prototype, "constructor", $Boolean, DONT_ENUM);
   1503 
   1504   InstallFunctions($Boolean.prototype, DONT_ENUM, $Array(
   1505     "toString", BooleanToString,
   1506     "valueOf", BooleanValueOf
   1507   ));
   1508 }
   1509 
   1510 SetUpBoolean();
   1511 
   1512 
   1513 // ----------------------------------------------------------------------------
   1514 // Number
   1515 
   1516 function NumberConstructor(x) {
   1517   var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x);
   1518   if (%_IsConstructCall()) {
   1519     %_SetValueOf(this, value);
   1520   } else {
   1521     return value;
   1522   }
   1523 }
   1524 
   1525 
   1526 // ECMA-262 section 15.7.4.2.
   1527 function NumberToString(radix) {
   1528   // NOTE: Both Number objects and values can enter here as
   1529   // 'this'. This is not as dictated by ECMA-262.
   1530   var number = this;
   1531   if (!IS_NUMBER(this)) {
   1532     if (!IS_NUMBER_WRAPPER(this)) {
   1533       throw new $TypeError('Number.prototype.toString is not generic');
   1534     }
   1535     // Get the value of this number in case it's an object.
   1536     number = %_ValueOf(this);
   1537   }
   1538   // Fast case: Convert number in radix 10.
   1539   if (IS_UNDEFINED(radix) || radix === 10) {
   1540     return %_NumberToString(number);
   1541   }
   1542 
   1543   // Convert the radix to an integer and check the range.
   1544   radix = TO_INTEGER(radix);
   1545   if (radix < 2 || radix > 36) {
   1546     throw new $RangeError('toString() radix argument must be between 2 and 36');
   1547   }
   1548   // Convert the number to a string in the given radix.
   1549   return %NumberToRadixString(number, radix);
   1550 }
   1551 
   1552 
   1553 // ECMA-262 section 15.7.4.3
   1554 function NumberToLocaleString() {
   1555   return %_CallFunction(this, NumberToString);
   1556 }
   1557 
   1558 
   1559 // ECMA-262 section 15.7.4.4
   1560 function NumberValueOf() {
   1561   // NOTE: Both Number objects and values can enter here as
   1562   // 'this'. This is not as dictated by ECMA-262.
   1563   if (!IS_NUMBER(this) && !IS_NUMBER_WRAPPER(this)) {
   1564     throw new $TypeError('Number.prototype.valueOf is not generic');
   1565   }
   1566   return %_ValueOf(this);
   1567 }
   1568 
   1569 
   1570 // ECMA-262 section 15.7.4.5
   1571 function NumberToFixedJS(fractionDigits) {
   1572   var x = this;
   1573   if (!IS_NUMBER(this)) {
   1574     if (!IS_NUMBER_WRAPPER(this)) {
   1575       throw MakeTypeError("incompatible_method_receiver",
   1576                           ["Number.prototype.toFixed", this]);
   1577     }
   1578     // Get the value of this number in case it's an object.
   1579     x = %_ValueOf(this);
   1580   }
   1581   var f = TO_INTEGER(fractionDigits);
   1582 
   1583   if (f < 0 || f > 20) {
   1584     throw new $RangeError("toFixed() digits argument must be between 0 and 20");
   1585   }
   1586 
   1587   if (NUMBER_IS_NAN(x)) return "NaN";
   1588   if (x == INFINITY) return "Infinity";
   1589   if (x == -INFINITY) return "-Infinity";
   1590 
   1591   return %NumberToFixed(x, f);
   1592 }
   1593 
   1594 
   1595 // ECMA-262 section 15.7.4.6
   1596 function NumberToExponentialJS(fractionDigits) {
   1597   var x = this;
   1598   if (!IS_NUMBER(this)) {
   1599     if (!IS_NUMBER_WRAPPER(this)) {
   1600       throw MakeTypeError("incompatible_method_receiver",
   1601                           ["Number.prototype.toExponential", this]);
   1602     }
   1603     // Get the value of this number in case it's an object.
   1604     x = %_ValueOf(this);
   1605   }
   1606   var f = IS_UNDEFINED(fractionDigits) ? UNDEFINED : TO_INTEGER(fractionDigits);
   1607 
   1608   if (NUMBER_IS_NAN(x)) return "NaN";
   1609   if (x == INFINITY) return "Infinity";
   1610   if (x == -INFINITY) return "-Infinity";
   1611 
   1612   if (IS_UNDEFINED(f)) {
   1613     f = -1;  // Signal for runtime function that f is not defined.
   1614   } else if (f < 0 || f > 20) {
   1615     throw new $RangeError("toExponential() argument must be between 0 and 20");
   1616   }
   1617   return %NumberToExponential(x, f);
   1618 }
   1619 
   1620 
   1621 // ECMA-262 section 15.7.4.7
   1622 function NumberToPrecisionJS(precision) {
   1623   var x = this;
   1624   if (!IS_NUMBER(this)) {
   1625     if (!IS_NUMBER_WRAPPER(this)) {
   1626       throw MakeTypeError("incompatible_method_receiver",
   1627                           ["Number.prototype.toPrecision", this]);
   1628     }
   1629     // Get the value of this number in case it's an object.
   1630     x = %_ValueOf(this);
   1631   }
   1632   if (IS_UNDEFINED(precision)) return ToString(%_ValueOf(this));
   1633   var p = TO_INTEGER(precision);
   1634 
   1635   if (NUMBER_IS_NAN(x)) return "NaN";
   1636   if (x == INFINITY) return "Infinity";
   1637   if (x == -INFINITY) return "-Infinity";
   1638 
   1639   if (p < 1 || p > 21) {
   1640     throw new $RangeError("toPrecision() argument must be between 1 and 21");
   1641   }
   1642   return %NumberToPrecision(x, p);
   1643 }
   1644 
   1645 
   1646 // Harmony isFinite.
   1647 function NumberIsFinite(number) {
   1648   return IS_NUMBER(number) && NUMBER_IS_FINITE(number);
   1649 }
   1650 
   1651 
   1652 // Harmony isInteger
   1653 function NumberIsInteger(number) {
   1654   return NumberIsFinite(number) && TO_INTEGER(number) == number;
   1655 }
   1656 
   1657 
   1658 // Harmony isNaN.
   1659 function NumberIsNaN(number) {
   1660   return IS_NUMBER(number) && NUMBER_IS_NAN(number);
   1661 }
   1662 
   1663 
   1664 // Harmony isSafeInteger
   1665 function NumberIsSafeInteger(number) {
   1666   if (NumberIsFinite(number)) {
   1667     var integral = TO_INTEGER(number);
   1668     if (integral == number)
   1669       return MathAbs(integral) <= $Number.MAX_SAFE_INTEGER;
   1670   }
   1671   return false;
   1672 }
   1673 
   1674 
   1675 // ----------------------------------------------------------------------------
   1676 
   1677 function SetUpNumber() {
   1678   %CheckIsBootstrapping();
   1679 
   1680   %SetCode($Number, NumberConstructor);
   1681   %FunctionSetPrototype($Number, new $Number(0));
   1682 
   1683   %OptimizeObjectForAddingMultipleProperties($Number.prototype, 8);
   1684   // Set up the constructor property on the Number prototype object.
   1685   %AddNamedProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
   1686 
   1687   InstallConstants($Number, $Array(
   1688       // ECMA-262 section 15.7.3.1.
   1689       "MAX_VALUE", 1.7976931348623157e+308,
   1690       // ECMA-262 section 15.7.3.2.
   1691       "MIN_VALUE", 5e-324,
   1692       // ECMA-262 section 15.7.3.3.
   1693       "NaN", NAN,
   1694       // ECMA-262 section 15.7.3.4.
   1695       "NEGATIVE_INFINITY", -INFINITY,
   1696       // ECMA-262 section 15.7.3.5.
   1697       "POSITIVE_INFINITY", INFINITY,
   1698 
   1699       // --- Harmony constants (no spec refs until settled.)
   1700 
   1701       "MAX_SAFE_INTEGER", %_MathPow(2, 53) - 1,
   1702       "MIN_SAFE_INTEGER", -%_MathPow(2, 53) + 1,
   1703       "EPSILON", %_MathPow(2, -52)
   1704   ));
   1705 
   1706   // Set up non-enumerable functions on the Number prototype object.
   1707   InstallFunctions($Number.prototype, DONT_ENUM, $Array(
   1708     "toString", NumberToString,
   1709     "toLocaleString", NumberToLocaleString,
   1710     "valueOf", NumberValueOf,
   1711     "toFixed", NumberToFixedJS,
   1712     "toExponential", NumberToExponentialJS,
   1713     "toPrecision", NumberToPrecisionJS
   1714   ));
   1715 
   1716   // Harmony Number constructor additions
   1717   InstallFunctions($Number, DONT_ENUM, $Array(
   1718     "isFinite", NumberIsFinite,
   1719     "isInteger", NumberIsInteger,
   1720     "isNaN", NumberIsNaN,
   1721     "isSafeInteger", NumberIsSafeInteger,
   1722     "parseInt", GlobalParseInt,
   1723     "parseFloat", GlobalParseFloat
   1724   ));
   1725 }
   1726 
   1727 SetUpNumber();
   1728 
   1729 
   1730 // ----------------------------------------------------------------------------
   1731 // Function
   1732 
   1733 function FunctionSourceString(func) {
   1734   while (%IsJSFunctionProxy(func)) {
   1735     func = %GetCallTrap(func);
   1736   }
   1737 
   1738   if (!IS_FUNCTION(func)) {
   1739     throw new $TypeError('Function.prototype.toString is not generic');
   1740   }
   1741 
   1742   var source = %FunctionGetSourceCode(func);
   1743   if (!IS_STRING(source) || %FunctionIsBuiltin(func)) {
   1744     var name = %FunctionGetName(func);
   1745     if (name) {
   1746       // Mimic what KJS does.
   1747       return 'function ' + name + '() { [native code] }';
   1748     } else {
   1749       return 'function () { [native code] }';
   1750     }
   1751   }
   1752 
   1753   if (%FunctionIsArrow(func)) {
   1754     return source;
   1755   }
   1756 
   1757   var name = %FunctionNameShouldPrintAsAnonymous(func)
   1758       ? 'anonymous'
   1759       : %FunctionGetName(func);
   1760 
   1761   var isGenerator = %FunctionIsGenerator(func);
   1762   var head = %FunctionIsConciseMethod(func)
   1763       ? (isGenerator ? '*' : '')
   1764       : (isGenerator ? 'function* ' : 'function ');
   1765   return head + name + source;
   1766 }
   1767 
   1768 
   1769 function FunctionToString() {
   1770   return FunctionSourceString(this);
   1771 }
   1772 
   1773 
   1774 // ES5 15.3.4.5
   1775 function FunctionBind(this_arg) { // Length is 1.
   1776   if (!IS_SPEC_FUNCTION(this)) {
   1777     throw new $TypeError('Bind must be called on a function');
   1778   }
   1779   var boundFunction = function () {
   1780     // Poison .arguments and .caller, but is otherwise not detectable.
   1781     "use strict";
   1782     // This function must not use any object literals (Object, Array, RegExp),
   1783     // since the literals-array is being used to store the bound data.
   1784     if (%_IsConstructCall()) {
   1785       return %NewObjectFromBound(boundFunction);
   1786     }
   1787     var bindings = %BoundFunctionGetBindings(boundFunction);
   1788 
   1789     var argc = %_ArgumentsLength();
   1790     if (argc == 0) {
   1791       return %Apply(bindings[0], bindings[1], bindings, 2, bindings.length - 2);
   1792     }
   1793     if (bindings.length === 2) {
   1794       return %Apply(bindings[0], bindings[1], arguments, 0, argc);
   1795     }
   1796     var bound_argc = bindings.length - 2;
   1797     var argv = new InternalArray(bound_argc + argc);
   1798     for (var i = 0; i < bound_argc; i++) {
   1799       argv[i] = bindings[i + 2];
   1800     }
   1801     for (var j = 0; j < argc; j++) {
   1802       argv[i++] = %_Arguments(j);
   1803     }
   1804     return %Apply(bindings[0], bindings[1], argv, 0, bound_argc + argc);
   1805   };
   1806 
   1807   var new_length = 0;
   1808   var old_length = this.length;
   1809   // FunctionProxies might provide a non-UInt32 value. If so, ignore it.
   1810   if ((typeof old_length === "number") &&
   1811       ((old_length >>> 0) === old_length)) {
   1812     var argc = %_ArgumentsLength();
   1813     if (argc > 0) argc--;  // Don't count the thisArg as parameter.
   1814     new_length = old_length - argc;
   1815     if (new_length < 0) new_length = 0;
   1816   }
   1817   // This runtime function finds any remaining arguments on the stack,
   1818   // so we don't pass the arguments object.
   1819   var result = %FunctionBindArguments(boundFunction, this,
   1820                                       this_arg, new_length);
   1821 
   1822   // We already have caller and arguments properties on functions,
   1823   // which are non-configurable. It therefore makes no sence to
   1824   // try to redefine these as defined by the spec. The spec says
   1825   // that bind should make these throw a TypeError if get or set
   1826   // is called and make them non-enumerable and non-configurable.
   1827   // To be consistent with our normal functions we leave this as it is.
   1828   // TODO(lrn): Do set these to be thrower.
   1829   return result;
   1830 }
   1831 
   1832 
   1833 function NewFunctionString(arguments, function_token) {
   1834   var n = arguments.length;
   1835   var p = '';
   1836   if (n > 1) {
   1837     p = ToString(arguments[0]);
   1838     for (var i = 1; i < n - 1; i++) {
   1839       p += ',' + ToString(arguments[i]);
   1840     }
   1841     // If the formal parameters string include ) - an illegal
   1842     // character - it may make the combined function expression
   1843     // compile. We avoid this problem by checking for this early on.
   1844     if (%_CallFunction(p, ')', StringIndexOfJS) != -1) {
   1845       throw MakeSyntaxError('paren_in_arg_string', []);
   1846     }
   1847     // If the formal parameters include an unbalanced block comment, the
   1848     // function must be rejected. Since JavaScript does not allow nested
   1849     // comments we can include a trailing block comment to catch this.
   1850     p += '\n/' + '**/';
   1851   }
   1852   var body = (n > 0) ? ToString(arguments[n - 1]) : '';
   1853   return '(' + function_token + '(' + p + ') {\n' + body + '\n})';
   1854 }
   1855 
   1856 
   1857 function FunctionConstructor(arg1) {  // length == 1
   1858   var source = NewFunctionString(arguments, 'function');
   1859   var global_proxy = %GlobalProxy(global);
   1860   // Compile the string in the constructor and not a helper so that errors
   1861   // appear to come from here.
   1862   var f = %_CallFunction(global_proxy, %CompileString(source, true));
   1863   %FunctionMarkNameShouldPrintAsAnonymous(f);
   1864   return f;
   1865 }
   1866 
   1867 
   1868 // ----------------------------------------------------------------------------
   1869 
   1870 function SetUpFunction() {
   1871   %CheckIsBootstrapping();
   1872 
   1873   %SetCode($Function, FunctionConstructor);
   1874   %AddNamedProperty($Function.prototype, "constructor", $Function, DONT_ENUM);
   1875 
   1876   InstallFunctions($Function.prototype, DONT_ENUM, $Array(
   1877     "bind", FunctionBind,
   1878     "toString", FunctionToString
   1879   ));
   1880 }
   1881 
   1882 SetUpFunction();
   1883 
   1884 
   1885 // ----------------------------------------------------------------------------
   1886 // Iterator related spec functions.
   1887 
   1888 // ES6 rev 26, 2014-07-18
   1889 // 7.4.1 CheckIterable ( obj )
   1890 function ToIterable(obj) {
   1891   if (!IS_SPEC_OBJECT(obj)) {
   1892     return UNDEFINED;
   1893   }
   1894   return obj[symbolIterator];
   1895 }
   1896 
   1897 
   1898 // ES6 rev 26, 2014-07-18
   1899 // 7.4.2 GetIterator ( obj, method )
   1900 function GetIterator(obj, method) {
   1901   if (IS_UNDEFINED(method)) {
   1902     method = ToIterable(obj);
   1903   }
   1904   if (!IS_SPEC_FUNCTION(method)) {
   1905     throw MakeTypeError('not_iterable', [obj]);
   1906   }
   1907   var iterator = %_CallFunction(obj, method);
   1908   if (!IS_SPEC_OBJECT(iterator)) {
   1909     throw MakeTypeError('not_an_iterator', [iterator]);
   1910   }
   1911   return iterator;
   1912 }
   1913