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