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