| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/debug.h" | 9 #include "src/debug.h" |
| 10 #include "src/messages.h" | 10 #include "src/messages.h" |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 | 125 |
| 126 JSObject::ValidateElements(js_object); | 126 JSObject::ValidateElements(js_object); |
| 127 if (js_object->HasExternalArrayElements() || | 127 if (js_object->HasExternalArrayElements() || |
| 128 js_object->HasFixedTypedArrayElements()) { | 128 js_object->HasFixedTypedArrayElements()) { |
| 129 if (!value->IsNumber() && !value->IsUndefined()) { | 129 if (!value->IsNumber() && !value->IsUndefined()) { |
| 130 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, | 130 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, |
| 131 Execution::ToNumber(isolate, value), Object); | 131 Execution::ToNumber(isolate, value), Object); |
| 132 } | 132 } |
| 133 } | 133 } |
| 134 | 134 |
| 135 MaybeHandle<Object> result = JSObject::SetElement( | 135 MaybeHandle<Object> result = |
| 136 js_object, index, value, NONE, language_mode, true, SET_PROPERTY); | 136 JSObject::SetElement(js_object, index, value, language_mode); |
| 137 JSObject::ValidateElements(js_object); | 137 JSObject::ValidateElements(js_object); |
| 138 | 138 |
| 139 return result.is_null() ? result : value; | 139 return result.is_null() ? result : value; |
| 140 } | 140 } |
| 141 | 141 |
| 142 if (key->IsName()) { | 142 if (key->IsName()) { |
| 143 Handle<Name> name = Handle<Name>::cast(key); | 143 Handle<Name> name = Handle<Name>::cast(key); |
| 144 if (name->AsArrayIndex(&index)) { | 144 if (name->AsArrayIndex(&index)) { |
| 145 // TODO(verwaest): Support non-JSObject receivers. | 145 // TODO(verwaest): Support non-JSObject receivers. |
| 146 if (!object->IsJSObject()) return value; | 146 if (!object->IsJSObject()) return value; |
| 147 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | 147 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
| 148 if (js_object->HasExternalArrayElements()) { | 148 if (js_object->HasExternalArrayElements()) { |
| 149 if (!value->IsNumber() && !value->IsUndefined()) { | 149 if (!value->IsNumber() && !value->IsUndefined()) { |
| 150 ASSIGN_RETURN_ON_EXCEPTION( | 150 ASSIGN_RETURN_ON_EXCEPTION( |
| 151 isolate, value, Execution::ToNumber(isolate, value), Object); | 151 isolate, value, Execution::ToNumber(isolate, value), Object); |
| 152 } | 152 } |
| 153 } | 153 } |
| 154 return JSObject::SetElement(js_object, index, value, NONE, language_mode, | 154 return JSObject::SetElement(js_object, index, value, language_mode); |
| 155 true, SET_PROPERTY); | |
| 156 } else { | 155 } else { |
| 157 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); | 156 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); |
| 158 return Object::SetProperty(object, name, value, language_mode); | 157 return Object::SetProperty(object, name, value, language_mode); |
| 159 } | 158 } |
| 160 } | 159 } |
| 161 | 160 |
| 162 // Call-back into JavaScript to convert the key to a string. | 161 // Call-back into JavaScript to convert the key to a string. |
| 163 Handle<Object> converted; | 162 Handle<Object> converted; |
| 164 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, | 163 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, |
| 165 Execution::ToString(isolate, key), Object); | 164 Execution::ToString(isolate, key), Object); |
| 166 Handle<String> name = Handle<String>::cast(converted); | 165 Handle<String> name = Handle<String>::cast(converted); |
| 167 | 166 |
| 168 if (name->AsArrayIndex(&index)) { | 167 if (name->AsArrayIndex(&index)) { |
| 169 // TODO(verwaest): Support non-JSObject receivers. | 168 // TODO(verwaest): Support non-JSObject receivers. |
| 170 if (!object->IsJSObject()) return value; | 169 if (!object->IsJSObject()) return value; |
| 171 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | 170 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
| 172 return JSObject::SetElement(js_object, index, value, NONE, language_mode, | 171 return JSObject::SetElement(js_object, index, value, language_mode); |
| 173 true, SET_PROPERTY); | |
| 174 } | 172 } |
| 175 return Object::SetProperty(object, name, value, language_mode); | 173 return Object::SetProperty(object, name, value, language_mode); |
| 176 } | 174 } |
| 177 | 175 |
| 178 | 176 |
| 179 MaybeHandle<Object> Runtime::DefineObjectProperty(Handle<JSObject> js_object, | 177 MaybeHandle<Object> Runtime::DefineObjectProperty(Handle<JSObject> js_object, |
| 180 Handle<Object> key, | 178 Handle<Object> key, |
| 181 Handle<Object> value, | 179 Handle<Object> value, |
| 182 PropertyAttributes attrs) { | 180 PropertyAttributes attrs) { |
| 183 Isolate* isolate = js_object->GetIsolate(); | 181 Isolate* isolate = js_object->GetIsolate(); |
| 184 // Check if the given key is an array index. | 182 // Check if the given key is an array index. |
| 185 uint32_t index = 0; | 183 uint32_t index = 0; |
| 186 if (key->ToArrayIndex(&index)) { | 184 if (key->ToArrayIndex(&index)) { |
| 187 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters | 185 return JSObject::SetOwnElementIgnoreAttributes(js_object, index, value, |
| 188 // of a string using [] notation. We need to support this too in | 186 attrs); |
| 189 // JavaScript. | |
| 190 // In the case of a String object we just need to redirect the assignment to | |
| 191 // the underlying string if the index is in range. Since the underlying | |
| 192 // string does nothing with the assignment then we can ignore such | |
| 193 // assignments. | |
| 194 if (js_object->IsStringObjectWithCharacterAt(index)) { | |
| 195 return value; | |
| 196 } | |
| 197 | |
| 198 return JSObject::SetElement(js_object, index, value, attrs, SLOPPY, false, | |
| 199 DEFINE_PROPERTY); | |
| 200 } | 187 } |
| 201 | 188 |
| 189 Handle<Name> name; |
| 202 if (key->IsName()) { | 190 if (key->IsName()) { |
| 203 Handle<Name> name = Handle<Name>::cast(key); | 191 name = Handle<Name>::cast(key); |
| 204 if (name->AsArrayIndex(&index)) { | 192 } else { |
| 205 return JSObject::SetElement(js_object, index, value, attrs, SLOPPY, false, | 193 // Call-back into JavaScript to convert the key to a string. |
| 206 DEFINE_PROPERTY); | 194 Handle<Object> converted; |
| 207 } else { | 195 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, |
| 208 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); | 196 Execution::ToString(isolate, key), Object); |
| 209 return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value, | 197 name = Handle<String>::cast(converted); |
| 210 attrs); | |
| 211 } | |
| 212 } | 198 } |
| 213 | 199 |
| 214 // Call-back into JavaScript to convert the key to a string. | |
| 215 Handle<Object> converted; | |
| 216 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, | |
| 217 Execution::ToString(isolate, key), Object); | |
| 218 Handle<String> name = Handle<String>::cast(converted); | |
| 219 | |
| 220 if (name->AsArrayIndex(&index)) { | 200 if (name->AsArrayIndex(&index)) { |
| 221 return JSObject::SetElement(js_object, index, value, attrs, SLOPPY, false, | 201 return JSObject::SetOwnElementIgnoreAttributes(js_object, index, value, |
| 222 DEFINE_PROPERTY); | 202 attrs); |
| 223 } else { | 203 } else { |
| 204 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); |
| 224 return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value, | 205 return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value, |
| 225 attrs); | 206 attrs); |
| 226 } | 207 } |
| 227 } | 208 } |
| 228 | 209 |
| 229 | 210 |
| 230 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate, | 211 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate, |
| 231 Handle<Object> obj) { | 212 Handle<Object> obj) { |
| 232 // We don't expect access checks to be needed on JSProxy objects. | 213 // We don't expect access checks to be needed on JSProxy objects. |
| 233 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); | 214 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 Runtime::GetObjectProperty(isolate, receiver_obj, key_obj)); | 598 Runtime::GetObjectProperty(isolate, receiver_obj, key_obj)); |
| 618 return *result; | 599 return *result; |
| 619 } | 600 } |
| 620 | 601 |
| 621 | 602 |
| 622 RUNTIME_FUNCTION(Runtime_AddNamedProperty) { | 603 RUNTIME_FUNCTION(Runtime_AddNamedProperty) { |
| 623 HandleScope scope(isolate); | 604 HandleScope scope(isolate); |
| 624 RUNTIME_ASSERT(args.length() == 4); | 605 RUNTIME_ASSERT(args.length() == 4); |
| 625 | 606 |
| 626 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 607 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| 627 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); | 608 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
| 628 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); | 609 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); |
| 629 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | 610 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); |
| 630 | 611 |
| 631 #ifdef DEBUG | 612 #ifdef DEBUG |
| 632 uint32_t index = 0; | 613 uint32_t index = 0; |
| 633 DCHECK(!key->ToArrayIndex(&index)); | 614 DCHECK(!name->ToArrayIndex(&index)); |
| 634 LookupIterator it(object, key, LookupIterator::OWN_SKIP_INTERCEPTOR); | 615 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 635 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | 616 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 636 if (!maybe.IsJust()) return isolate->heap()->exception(); | 617 if (!maybe.IsJust()) return isolate->heap()->exception(); |
| 637 RUNTIME_ASSERT(!it.IsFound()); | 618 RUNTIME_ASSERT(!it.IsFound()); |
| 638 #endif | 619 #endif |
| 639 | 620 |
| 640 Handle<Object> result; | 621 Handle<Object> result; |
| 641 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 622 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 642 isolate, result, | 623 isolate, result, |
| 643 JSObject::SetOwnPropertyIgnoreAttributes(object, key, value, attrs)); | 624 JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, attrs)); |
| 644 return *result; | 625 return *result; |
| 645 } | 626 } |
| 646 | 627 |
| 647 | |
| 648 RUNTIME_FUNCTION(Runtime_SetProperty) { | |
| 649 HandleScope scope(isolate); | |
| 650 RUNTIME_ASSERT(args.length() == 4); | |
| 651 | |
| 652 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); | |
| 653 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | |
| 654 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); | |
| 655 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3); | |
| 656 LanguageMode language_mode = language_mode_arg; | |
| 657 | |
| 658 Handle<Object> result; | |
| 659 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 660 isolate, result, | |
| 661 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); | |
| 662 return *result; | |
| 663 } | |
| 664 | |
| 665 | 628 |
| 666 // Adds an element to an array. | 629 // Adds an element to an array. |
| 667 // This is used to create an indexed data property into an array. | 630 // This is used to create an indexed data property into an array. |
| 668 RUNTIME_FUNCTION(Runtime_AddElement) { | 631 RUNTIME_FUNCTION(Runtime_AddElement) { |
| 669 HandleScope scope(isolate); | 632 HandleScope scope(isolate); |
| 670 RUNTIME_ASSERT(args.length() == 4); | 633 RUNTIME_ASSERT(args.length() == 3); |
| 671 | 634 |
| 672 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 635 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| 673 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); | 636 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); |
| 674 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); | 637 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); |
| 675 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | |
| 676 | 638 |
| 677 uint32_t index = 0; | 639 uint32_t index = 0; |
| 678 key->ToArrayIndex(&index); | 640 CHECK(key->ToArrayIndex(&index)); |
| 641 |
| 642 #ifdef DEBUG |
| 643 LookupIterator it(isolate, object, index, |
| 644 LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 645 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 646 if (!maybe.IsJust()) return isolate->heap()->exception(); |
| 647 RUNTIME_ASSERT(!it.IsFound()); |
| 648 |
| 649 if (object->IsJSArray()) { |
| 650 Handle<JSArray> array = Handle<JSArray>::cast(object); |
| 651 RUNTIME_ASSERT(!JSArray::WouldChangeReadOnlyLength(array, index)); |
| 652 } |
| 653 #endif |
| 679 | 654 |
| 680 Handle<Object> result; | 655 Handle<Object> result; |
| 681 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 656 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 682 isolate, result, JSObject::SetElement(object, index, value, attrs, SLOPPY, | 657 isolate, result, |
| 683 false, DEFINE_PROPERTY)); | 658 JSObject::SetOwnElementIgnoreAttributes(object, index, value, NONE)); |
| 684 return *result; | 659 return *result; |
| 685 } | 660 } |
| 686 | 661 |
| 687 | 662 |
| 688 RUNTIME_FUNCTION(Runtime_AppendElement) { | 663 RUNTIME_FUNCTION(Runtime_AppendElement) { |
| 689 HandleScope scope(isolate); | 664 HandleScope scope(isolate); |
| 690 RUNTIME_ASSERT(args.length() == 2); | 665 RUNTIME_ASSERT(args.length() == 2); |
| 691 | 666 |
| 692 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); | 667 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); |
| 693 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 668 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
| 694 | 669 |
| 695 int index = Smi::cast(array->length())->value(); | 670 uint32_t index; |
| 671 CHECK(array->length()->ToArrayIndex(&index)); |
| 696 | 672 |
| 697 Handle<Object> result; | 673 Handle<Object> result; |
| 698 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 674 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 699 isolate, result, JSObject::SetElement(array, index, value, NONE, SLOPPY, | 675 isolate, result, JSObject::AddDataElement(array, index, value, NONE)); |
| 700 false, DEFINE_PROPERTY)); | |
| 701 return *array; | 676 return *array; |
| 702 } | 677 } |
| 703 | 678 |
| 704 | 679 |
| 680 RUNTIME_FUNCTION(Runtime_SetProperty) { |
| 681 HandleScope scope(isolate); |
| 682 RUNTIME_ASSERT(args.length() == 4); |
| 683 |
| 684 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); |
| 685 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); |
| 686 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); |
| 687 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3); |
| 688 LanguageMode language_mode = language_mode_arg; |
| 689 |
| 690 Handle<Object> result; |
| 691 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 692 isolate, result, |
| 693 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); |
| 694 return *result; |
| 695 } |
| 696 |
| 697 |
| 705 RUNTIME_FUNCTION(Runtime_DeleteProperty) { | 698 RUNTIME_FUNCTION(Runtime_DeleteProperty) { |
| 706 HandleScope scope(isolate); | 699 HandleScope scope(isolate); |
| 707 DCHECK(args.length() == 3); | 700 DCHECK(args.length() == 3); |
| 708 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); | 701 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); |
| 709 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); | 702 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); |
| 710 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2); | 703 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2); |
| 711 Handle<Object> result; | 704 Handle<Object> result; |
| 712 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 705 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 713 isolate, result, JSReceiver::DeleteProperty(object, key, language_mode)); | 706 isolate, result, JSReceiver::DeleteProperty(object, key, language_mode)); |
| 714 return *result; | 707 return *result; |
| (...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1368 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | 1361 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); |
| 1369 | 1362 |
| 1370 LookupIterator it(js_object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); | 1363 LookupIterator it(js_object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); |
| 1371 if (it.IsFound() && it.state() == LookupIterator::ACCESS_CHECK) { | 1364 if (it.IsFound() && it.state() == LookupIterator::ACCESS_CHECK) { |
| 1372 if (!isolate->MayAccess(js_object)) { | 1365 if (!isolate->MayAccess(js_object)) { |
| 1373 return isolate->heap()->undefined_value(); | 1366 return isolate->heap()->undefined_value(); |
| 1374 } | 1367 } |
| 1375 it.Next(); | 1368 it.Next(); |
| 1376 } | 1369 } |
| 1377 | 1370 |
| 1378 // Take special care when attributes are different and there is already | |
| 1379 // a property. | |
| 1380 if (it.state() == LookupIterator::ACCESSOR) { | |
| 1381 // Use IgnoreAttributes version since a readonly property may be | |
| 1382 // overridden and SetProperty does not allow this. | |
| 1383 Handle<Object> result; | |
| 1384 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 1385 isolate, result, | |
| 1386 JSObject::SetOwnPropertyIgnoreAttributes( | |
| 1387 js_object, name, obj_value, attrs, JSObject::DONT_FORCE_FIELD)); | |
| 1388 return *result; | |
| 1389 } | |
| 1390 | |
| 1391 Handle<Object> result; | 1371 Handle<Object> result; |
| 1392 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1372 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1393 isolate, result, | 1373 isolate, result, |
| 1394 Runtime::DefineObjectProperty(js_object, name, obj_value, attrs)); | 1374 Runtime::DefineObjectProperty(js_object, name, obj_value, attrs)); |
| 1395 return *result; | 1375 return *result; |
| 1396 } | 1376 } |
| 1397 | 1377 |
| 1398 | 1378 |
| 1399 // Return property without being observable by accessors or interceptors. | 1379 // Return property without being observable by accessors or interceptors. |
| 1400 RUNTIME_FUNCTION(Runtime_GetDataProperty) { | 1380 RUNTIME_FUNCTION(Runtime_GetDataProperty) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1542 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | 1522 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); |
| 1543 | 1523 |
| 1544 RETURN_FAILURE_ON_EXCEPTION( | 1524 RETURN_FAILURE_ON_EXCEPTION( |
| 1545 isolate, | 1525 isolate, |
| 1546 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), | 1526 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), |
| 1547 setter, attrs)); | 1527 setter, attrs)); |
| 1548 return isolate->heap()->undefined_value(); | 1528 return isolate->heap()->undefined_value(); |
| 1549 } | 1529 } |
| 1550 } // namespace internal | 1530 } // namespace internal |
| 1551 } // namespace v8 | 1531 } // namespace v8 |
| OLD | NEW |