OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <memory> | 9 #include <memory> |
10 #include <sstream> | 10 #include <sstream> |
(...skipping 1399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1410 if (structure->IsAccessorInfo()) { | 1410 if (structure->IsAccessorInfo()) { |
1411 Handle<JSObject> holder = it->GetHolder<JSObject>(); | 1411 Handle<JSObject> holder = it->GetHolder<JSObject>(); |
1412 Handle<Name> name = it->GetName(); | 1412 Handle<Name> name = it->GetName(); |
1413 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure); | 1413 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure); |
1414 if (!info->IsCompatibleReceiver(*receiver)) { | 1414 if (!info->IsCompatibleReceiver(*receiver)) { |
1415 isolate->Throw(*isolate->factory()->NewTypeError( | 1415 isolate->Throw(*isolate->factory()->NewTypeError( |
1416 MessageTemplate::kIncompatibleMethodReceiver, name, receiver)); | 1416 MessageTemplate::kIncompatibleMethodReceiver, name, receiver)); |
1417 return Nothing<bool>(); | 1417 return Nothing<bool>(); |
1418 } | 1418 } |
1419 | 1419 |
1420 v8::AccessorNameSetterCallback call_fun = | 1420 // The actual type of call_fun is either v8::AccessorNameSetterCallback or |
1421 v8::ToCData<v8::AccessorNameSetterCallback>(info->setter()); | 1421 // i::Accesors::AccessorNameBooleanSetterCallback, depending on whether the |
1422 // TODO(verwaest): We should not get here anymore once all AccessorInfos are | 1422 // AccessorInfo was created by the API or internally (see accessors.cc). |
1423 // marked as special_data_property. They cannot both be writable and not | 1423 // Here we handle both cases using GenericNamedPropertySetterCallback and |
1424 // have a setter. | 1424 // its Call method. |
1425 if (call_fun == nullptr) return Just(true); | 1425 GenericNamedPropertySetterCallback call_fun = |
| 1426 v8::ToCData<GenericNamedPropertySetterCallback>(info->setter()); |
| 1427 |
| 1428 if (call_fun == nullptr) { |
| 1429 // TODO(verwaest): We should not get here anymore once all AccessorInfos |
| 1430 // are marked as special_data_property. They cannot both be writable and |
| 1431 // not have a setter. |
| 1432 return Just(true); |
| 1433 } |
1426 | 1434 |
1427 if (info->is_sloppy() && !receiver->IsJSReceiver()) { | 1435 if (info->is_sloppy() && !receiver->IsJSReceiver()) { |
1428 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1436 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
1429 isolate, receiver, Object::ConvertReceiver(isolate, receiver), | 1437 isolate, receiver, Object::ConvertReceiver(isolate, receiver), |
1430 Nothing<bool>()); | 1438 Nothing<bool>()); |
1431 } | 1439 } |
1432 | 1440 |
1433 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder, | 1441 PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder, |
1434 should_throw); | 1442 should_throw); |
1435 args.Call(call_fun, name, value); | 1443 Handle<Object> result = args.Call(call_fun, name, value); |
| 1444 // In the case of AccessorNameSetterCallback, we know that the result value |
| 1445 // cannot have been set, so the result of Call will be null. In the case of |
| 1446 // AccessorNameBooleanSetterCallback, the result will either be null |
| 1447 // (signalling an exception) or a boolean Oddball. |
1436 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); | 1448 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>()); |
1437 return Just(true); | 1449 if (result.is_null()) return Just(true); |
| 1450 DCHECK(result->BooleanValue() || should_throw == DONT_THROW); |
| 1451 return Just(result->BooleanValue()); |
1438 } | 1452 } |
1439 | 1453 |
1440 // Regular accessor. | 1454 // Regular accessor. |
1441 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); | 1455 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
1442 if (setter->IsFunctionTemplateInfo()) { | 1456 if (setter->IsFunctionTemplateInfo()) { |
1443 Handle<Object> argv[] = {value}; | 1457 Handle<Object> argv[] = {value}; |
1444 RETURN_ON_EXCEPTION_VALUE( | 1458 RETURN_ON_EXCEPTION_VALUE( |
1445 isolate, Builtins::InvokeApiFunction( | 1459 isolate, Builtins::InvokeApiFunction( |
1446 isolate, false, Handle<FunctionTemplateInfo>::cast(setter), | 1460 isolate, false, Handle<FunctionTemplateInfo>::cast(setter), |
1447 receiver, arraysize(argv), argv, | 1461 receiver, arraysize(argv), argv, |
(...skipping 4326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5774 PropertyAttributes current_attributes = it->property_attributes(); | 5788 PropertyAttributes current_attributes = it->property_attributes(); |
5775 // Ensure the context isn't changed after calling into accessors. | 5789 // Ensure the context isn't changed after calling into accessors. |
5776 AssertNoContextChange ncc(it->isolate()); | 5790 AssertNoContextChange ncc(it->isolate()); |
5777 | 5791 |
5778 // Update the attributes before calling the setter. The setter may | 5792 // Update the attributes before calling the setter. The setter may |
5779 // later change the shape of the property. | 5793 // later change the shape of the property. |
5780 if (current_attributes != attributes) { | 5794 if (current_attributes != attributes) { |
5781 it->TransitionToAccessorPair(accessors, attributes); | 5795 it->TransitionToAccessorPair(accessors, attributes); |
5782 } | 5796 } |
5783 | 5797 |
5784 Maybe<bool> result = | 5798 return JSObject::SetPropertyWithAccessor(it, value, should_throw); |
5785 JSObject::SetPropertyWithAccessor(it, value, should_throw); | |
5786 | |
5787 if (current_attributes == attributes || result.IsNothing()) { | |
5788 return result; | |
5789 } | |
5790 | |
5791 } else { | |
5792 it->ReconfigureDataProperty(value, attributes); | |
5793 } | 5799 } |
5794 | 5800 |
| 5801 it->ReconfigureDataProperty(value, attributes); |
5795 return Just(true); | 5802 return Just(true); |
5796 } | 5803 } |
5797 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 5804 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
5798 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value, | 5805 return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value, |
5799 should_throw); | 5806 should_throw); |
5800 | 5807 |
5801 case LookupIterator::DATA: { | 5808 case LookupIterator::DATA: { |
5802 // Regular property update if the attributes match. | 5809 // Regular property update if the attributes match. |
5803 if (it->property_attributes() == attributes) { | 5810 if (it->property_attributes() == attributes) { |
5804 return SetDataProperty(it, value); | 5811 return SetDataProperty(it, value); |
(...skipping 14413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20218 ns, Accessors::ModuleNamespaceEntryInfo(isolate, name, attr)) | 20225 ns, Accessors::ModuleNamespaceEntryInfo(isolate, name, attr)) |
20219 .Check(); | 20226 .Check(); |
20220 } | 20227 } |
20221 JSObject::PreventExtensions(ns, THROW_ON_ERROR).ToChecked(); | 20228 JSObject::PreventExtensions(ns, THROW_ON_ERROR).ToChecked(); |
20222 | 20229 |
20223 return ns; | 20230 return ns; |
20224 } | 20231 } |
20225 | 20232 |
20226 } // namespace internal | 20233 } // namespace internal |
20227 } // namespace v8 | 20234 } // namespace v8 |
OLD | NEW |