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