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