Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(358)

Side by Side Diff: src/v8natives.js

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

Powered by Google App Engine
This is Rietveld 408576698