OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 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/accessors.h" | 5 #include "src/accessors.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/contexts.h" | 8 #include "src/contexts.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/execution.h" | 10 #include "src/execution.h" |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 JSDataView::kByteLengthOffset, object_offset) || | 128 JSDataView::kByteLengthOffset, object_offset) || |
129 CheckForName(name, isolate->factory()->byte_offset_string(), | 129 CheckForName(name, isolate->factory()->byte_offset_string(), |
130 JSDataView::kByteOffsetOffset, object_offset); | 130 JSDataView::kByteOffsetOffset, object_offset); |
131 default: | 131 default: |
132 return false; | 132 return false; |
133 } | 133 } |
134 } | 134 } |
135 | 135 |
136 MUST_USE_RESULT static MaybeHandle<Object> ReplaceAccessorWithDataProperty( | 136 MUST_USE_RESULT static MaybeHandle<Object> ReplaceAccessorWithDataProperty( |
137 Isolate* isolate, Handle<JSObject> receiver, Handle<JSObject> holder, | 137 Isolate* isolate, Handle<JSObject> receiver, Handle<JSObject> holder, |
138 Handle<Name> name, Handle<Object> value, bool observe) { | 138 Handle<Name> name, Handle<Object> value) { |
139 LookupIterator it(receiver, name, holder, | 139 LookupIterator it(receiver, name, holder, |
140 LookupIterator::OWN_SKIP_INTERCEPTOR); | 140 LookupIterator::OWN_SKIP_INTERCEPTOR); |
141 // Skip any access checks we might hit. This accessor should never hit in a | 141 // Skip any access checks we might hit. This accessor should never hit in a |
142 // situation where the caller does not have access. | 142 // situation where the caller does not have access. |
143 if (it.state() == LookupIterator::ACCESS_CHECK) { | 143 if (it.state() == LookupIterator::ACCESS_CHECK) { |
144 CHECK(it.HasAccess()); | 144 CHECK(it.HasAccess()); |
145 it.Next(); | 145 it.Next(); |
146 } | 146 } |
147 CHECK_EQ(LookupIterator::ACCESSOR, it.state()); | 147 CHECK_EQ(LookupIterator::ACCESSOR, it.state()); |
148 | |
149 Handle<Object> old_value; | |
150 bool is_observed = observe && receiver->map()->is_observed(); | |
151 if (is_observed) { | |
152 MaybeHandle<Object> maybe_old = Object::GetPropertyWithAccessor(&it); | |
153 if (!maybe_old.ToHandle(&old_value)) return maybe_old; | |
154 } | |
155 | |
156 it.ReconfigureDataProperty(value, it.property_attributes()); | 148 it.ReconfigureDataProperty(value, it.property_attributes()); |
157 | |
158 if (is_observed && !old_value->SameValue(*value)) { | |
159 return JSObject::EnqueueChangeRecord(receiver, "update", name, old_value); | |
160 } | |
161 | |
162 return value; | 149 return value; |
163 } | 150 } |
164 | 151 |
165 void Accessors::ReconfigureToDataProperty( | 152 void Accessors::ReconfigureToDataProperty( |
166 v8::Local<v8::Name> key, v8::Local<v8::Value> val, | 153 v8::Local<v8::Name> key, v8::Local<v8::Value> val, |
167 const v8::PropertyCallbackInfo<void>& info) { | 154 const v8::PropertyCallbackInfo<void>& info) { |
168 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); | 155 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); |
169 HandleScope scope(isolate); | 156 HandleScope scope(isolate); |
170 Handle<JSObject> receiver = | 157 Handle<JSObject> receiver = |
171 Handle<JSObject>::cast(Utils::OpenHandle(*info.This())); | 158 Handle<JSObject>::cast(Utils::OpenHandle(*info.This())); |
172 Handle<JSObject> holder = | 159 Handle<JSObject> holder = |
173 Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder())); | 160 Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder())); |
174 Handle<Name> name = Utils::OpenHandle(*key); | 161 Handle<Name> name = Utils::OpenHandle(*key); |
175 Handle<Object> value = Utils::OpenHandle(*val); | 162 Handle<Object> value = Utils::OpenHandle(*val); |
176 MaybeHandle<Object> result = ReplaceAccessorWithDataProperty( | 163 MaybeHandle<Object> result = |
177 isolate, receiver, holder, name, value, false); | 164 ReplaceAccessorWithDataProperty(isolate, receiver, holder, name, value); |
178 if (result.is_null()) isolate->OptionalRescheduleException(false); | 165 if (result.is_null()) isolate->OptionalRescheduleException(false); |
179 } | 166 } |
180 | 167 |
181 // | 168 // |
182 // Accessors::ArgumentsIterator | 169 // Accessors::ArgumentsIterator |
183 // | 170 // |
184 | 171 |
185 | 172 |
186 void Accessors::ArgumentsIteratorGetter( | 173 void Accessors::ArgumentsIteratorGetter( |
187 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { | 174 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 Handle<JSReceiver> object = Utils::OpenHandle(*info.This()); | 215 Handle<JSReceiver> object = Utils::OpenHandle(*info.This()); |
229 Handle<JSArray> array = Handle<JSArray>::cast(object); | 216 Handle<JSArray> array = Handle<JSArray>::cast(object); |
230 Handle<Object> length_obj = Utils::OpenHandle(*val); | 217 Handle<Object> length_obj = Utils::OpenHandle(*val); |
231 | 218 |
232 uint32_t length = 0; | 219 uint32_t length = 0; |
233 if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) { | 220 if (!JSArray::AnythingToArrayLength(isolate, length_obj, &length)) { |
234 isolate->OptionalRescheduleException(false); | 221 isolate->OptionalRescheduleException(false); |
235 return; | 222 return; |
236 } | 223 } |
237 | 224 |
238 if (JSArray::ObservableSetLength(array, length).is_null()) { | 225 JSArray::SetLength(array, length); |
239 isolate->OptionalRescheduleException(false); | |
240 } | |
241 | 226 |
242 if (info.ShouldThrowOnError()) { | 227 if (info.ShouldThrowOnError()) { |
243 uint32_t actual_new_len = 0; | 228 uint32_t actual_new_len = 0; |
244 CHECK(array->length()->ToArrayLength(&actual_new_len)); | 229 CHECK(array->length()->ToArrayLength(&actual_new_len)); |
245 // Throw TypeError if there were non-deletable elements. | 230 // Throw TypeError if there were non-deletable elements. |
246 if (actual_new_len != length) { | 231 if (actual_new_len != length) { |
247 Factory* factory = isolate->factory(); | 232 Factory* factory = isolate->factory(); |
248 isolate->Throw(*factory->NewTypeError( | 233 isolate->Throw(*factory->NewTypeError( |
249 MessageTemplate::kStrictDeleteProperty, | 234 MessageTemplate::kStrictDeleteProperty, |
250 factory->NewNumberFromUint(actual_new_len - 1), array)); | 235 factory->NewNumberFromUint(actual_new_len - 1), array)); |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 if (!function->has_prototype()) { | 710 if (!function->has_prototype()) { |
726 Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function); | 711 Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function); |
727 JSFunction::SetPrototype(function, proto); | 712 JSFunction::SetPrototype(function, proto); |
728 } | 713 } |
729 return Handle<Object>(function->prototype(), isolate); | 714 return Handle<Object>(function->prototype(), isolate); |
730 } | 715 } |
731 | 716 |
732 | 717 |
733 MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype( | 718 MUST_USE_RESULT static MaybeHandle<Object> SetFunctionPrototype( |
734 Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) { | 719 Isolate* isolate, Handle<JSFunction> function, Handle<Object> value) { |
735 Handle<Object> old_value; | |
736 bool is_observed = function->map()->is_observed(); | |
737 if (is_observed) { | |
738 if (function->has_prototype()) | |
739 old_value = handle(function->prototype(), isolate); | |
740 else | |
741 old_value = isolate->factory()->NewFunctionPrototype(function); | |
742 } | |
743 | |
744 JSFunction::SetPrototype(function, value); | 720 JSFunction::SetPrototype(function, value); |
745 DCHECK(function->prototype() == *value); | 721 DCHECK(function->prototype() == *value); |
746 | |
747 if (is_observed && !old_value->SameValue(*value)) { | |
748 MaybeHandle<Object> result = JSObject::EnqueueChangeRecord( | |
749 function, "update", isolate->factory()->prototype_string(), old_value); | |
750 if (result.is_null()) return MaybeHandle<Object>(); | |
751 } | |
752 | |
753 return function; | 722 return function; |
754 } | 723 } |
755 | 724 |
756 | 725 |
757 MaybeHandle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function, | 726 MaybeHandle<Object> Accessors::FunctionSetPrototype(Handle<JSFunction> function, |
758 Handle<Object> prototype) { | 727 Handle<Object> prototype) { |
759 DCHECK(function->IsConstructor()); | 728 DCHECK(function->IsConstructor()); |
760 Isolate* isolate = function->GetIsolate(); | 729 Isolate* isolate = function->GetIsolate(); |
761 return SetFunctionPrototype(isolate, function, prototype); | 730 return SetFunctionPrototype(isolate, function, prototype); |
762 } | 731 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
813 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); | 782 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); |
814 Handle<Object> result; | 783 Handle<Object> result; |
815 if (!JSFunction::GetLength(isolate, function).ToHandle(&result)) { | 784 if (!JSFunction::GetLength(isolate, function).ToHandle(&result)) { |
816 result = handle(Smi::FromInt(0), isolate); | 785 result = handle(Smi::FromInt(0), isolate); |
817 isolate->OptionalRescheduleException(false); | 786 isolate->OptionalRescheduleException(false); |
818 } | 787 } |
819 | 788 |
820 info.GetReturnValue().Set(Utils::ToLocal(result)); | 789 info.GetReturnValue().Set(Utils::ToLocal(result)); |
821 } | 790 } |
822 | 791 |
823 void Accessors::ObservedReconfigureToDataProperty( | |
824 v8::Local<v8::Name> key, v8::Local<v8::Value> val, | |
825 const v8::PropertyCallbackInfo<void>& info) { | |
826 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); | |
827 HandleScope scope(isolate); | |
828 Handle<JSObject> receiver = | |
829 Handle<JSObject>::cast(Utils::OpenHandle(*info.This())); | |
830 Handle<JSObject> holder = | |
831 Handle<JSObject>::cast(Utils::OpenHandle(*info.Holder())); | |
832 Handle<Name> name = Utils::OpenHandle(*key); | |
833 Handle<Object> value = Utils::OpenHandle(*val); | |
834 MaybeHandle<Object> result = ReplaceAccessorWithDataProperty( | |
835 isolate, receiver, holder, name, value, true); | |
836 if (result.is_null()) isolate->OptionalRescheduleException(false); | |
837 } | |
838 | |
839 | |
840 Handle<AccessorInfo> Accessors::FunctionLengthInfo( | 792 Handle<AccessorInfo> Accessors::FunctionLengthInfo( |
841 Isolate* isolate, PropertyAttributes attributes) { | 793 Isolate* isolate, PropertyAttributes attributes) { |
842 return MakeAccessor(isolate, isolate->factory()->length_string(), | 794 return MakeAccessor(isolate, isolate->factory()->length_string(), |
843 &FunctionLengthGetter, &ObservedReconfigureToDataProperty, | 795 &FunctionLengthGetter, &ReconfigureToDataProperty, |
844 attributes); | 796 attributes); |
845 } | 797 } |
846 | 798 |
847 | 799 |
848 // | 800 // |
849 // Accessors::FunctionName | 801 // Accessors::FunctionName |
850 // | 802 // |
851 | 803 |
852 | 804 |
853 void Accessors::FunctionNameGetter( | 805 void Accessors::FunctionNameGetter( |
854 v8::Local<v8::Name> name, | 806 v8::Local<v8::Name> name, |
855 const v8::PropertyCallbackInfo<v8::Value>& info) { | 807 const v8::PropertyCallbackInfo<v8::Value>& info) { |
856 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); | 808 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); |
857 HandleScope scope(isolate); | 809 HandleScope scope(isolate); |
858 Handle<JSFunction> function = | 810 Handle<JSFunction> function = |
859 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); | 811 Handle<JSFunction>::cast(Utils::OpenHandle(*info.Holder())); |
860 Handle<Object> result = JSFunction::GetName(isolate, function); | 812 Handle<Object> result = JSFunction::GetName(isolate, function); |
861 info.GetReturnValue().Set(Utils::ToLocal(result)); | 813 info.GetReturnValue().Set(Utils::ToLocal(result)); |
862 } | 814 } |
863 | 815 |
864 Handle<AccessorInfo> Accessors::FunctionNameInfo( | 816 Handle<AccessorInfo> Accessors::FunctionNameInfo( |
865 Isolate* isolate, PropertyAttributes attributes) { | 817 Isolate* isolate, PropertyAttributes attributes) { |
866 return MakeAccessor(isolate, isolate->factory()->name_string(), | 818 return MakeAccessor(isolate, isolate->factory()->name_string(), |
867 &FunctionNameGetter, &ObservedReconfigureToDataProperty, | 819 &FunctionNameGetter, &ReconfigureToDataProperty, |
868 attributes); | 820 attributes); |
869 } | 821 } |
870 | 822 |
871 | 823 |
872 // | 824 // |
873 // Accessors::FunctionArguments | 825 // Accessors::FunctionArguments |
874 // | 826 // |
875 | 827 |
876 | 828 |
877 static Handle<Object> ArgumentsForInlinedFunction( | 829 static Handle<Object> ArgumentsForInlinedFunction( |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1163 int bound_length = function->bound_arguments()->length(); | 1115 int bound_length = function->bound_arguments()->length(); |
1164 int length = Max(0, target_length->value() - bound_length); | 1116 int length = Max(0, target_length->value() - bound_length); |
1165 | 1117 |
1166 Handle<Object> result(Smi::FromInt(length), isolate); | 1118 Handle<Object> result(Smi::FromInt(length), isolate); |
1167 info.GetReturnValue().Set(Utils::ToLocal(result)); | 1119 info.GetReturnValue().Set(Utils::ToLocal(result)); |
1168 } | 1120 } |
1169 | 1121 |
1170 Handle<AccessorInfo> Accessors::BoundFunctionLengthInfo( | 1122 Handle<AccessorInfo> Accessors::BoundFunctionLengthInfo( |
1171 Isolate* isolate, PropertyAttributes attributes) { | 1123 Isolate* isolate, PropertyAttributes attributes) { |
1172 return MakeAccessor(isolate, isolate->factory()->length_string(), | 1124 return MakeAccessor(isolate, isolate->factory()->length_string(), |
1173 &BoundFunctionLengthGetter, | 1125 &BoundFunctionLengthGetter, &ReconfigureToDataProperty, |
1174 &ObservedReconfigureToDataProperty, attributes); | 1126 attributes); |
1175 } | 1127 } |
1176 | 1128 |
1177 // | 1129 // |
1178 // Accessors::BoundFunctionName | 1130 // Accessors::BoundFunctionName |
1179 // | 1131 // |
1180 | 1132 |
1181 void Accessors::BoundFunctionNameGetter( | 1133 void Accessors::BoundFunctionNameGetter( |
1182 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { | 1134 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { |
1183 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); | 1135 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate()); |
1184 HandleScope scope(isolate); | 1136 HandleScope scope(isolate); |
1185 Handle<JSBoundFunction> function = | 1137 Handle<JSBoundFunction> function = |
1186 Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder())); | 1138 Handle<JSBoundFunction>::cast(Utils::OpenHandle(*info.Holder())); |
1187 Handle<Object> result; | 1139 Handle<Object> result; |
1188 if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) { | 1140 if (!JSBoundFunction::GetName(isolate, function).ToHandle(&result)) { |
1189 isolate->OptionalRescheduleException(false); | 1141 isolate->OptionalRescheduleException(false); |
1190 return; | 1142 return; |
1191 } | 1143 } |
1192 info.GetReturnValue().Set(Utils::ToLocal(result)); | 1144 info.GetReturnValue().Set(Utils::ToLocal(result)); |
1193 } | 1145 } |
1194 | 1146 |
1195 Handle<AccessorInfo> Accessors::BoundFunctionNameInfo( | 1147 Handle<AccessorInfo> Accessors::BoundFunctionNameInfo( |
1196 Isolate* isolate, PropertyAttributes attributes) { | 1148 Isolate* isolate, PropertyAttributes attributes) { |
1197 return MakeAccessor(isolate, isolate->factory()->name_string(), | 1149 return MakeAccessor(isolate, isolate->factory()->name_string(), |
1198 &BoundFunctionNameGetter, | 1150 &BoundFunctionNameGetter, &ReconfigureToDataProperty, |
1199 &ObservedReconfigureToDataProperty, attributes); | 1151 attributes); |
1200 } | 1152 } |
1201 | 1153 |
1202 // | 1154 // |
1203 // Accessors::MakeModuleExport | 1155 // Accessors::MakeModuleExport |
1204 // | 1156 // |
1205 | 1157 |
1206 static void ModuleGetExport(v8::Local<v8::Name> property, | 1158 static void ModuleGetExport(v8::Local<v8::Name> property, |
1207 const v8::PropertyCallbackInfo<v8::Value>& info) { | 1159 const v8::PropertyCallbackInfo<v8::Value>& info) { |
1208 JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder())); | 1160 JSModule* instance = JSModule::cast(*v8::Utils::OpenHandle(*info.Holder())); |
1209 Context* context = Context::cast(instance->context()); | 1161 Context* context = Context::cast(instance->context()); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1252 Isolate* isolate = name->GetIsolate(); | 1204 Isolate* isolate = name->GetIsolate(); |
1253 Handle<AccessorInfo> info = MakeAccessor(isolate, name, &ModuleGetExport, | 1205 Handle<AccessorInfo> info = MakeAccessor(isolate, name, &ModuleGetExport, |
1254 &ModuleSetExport, attributes); | 1206 &ModuleSetExport, attributes); |
1255 info->set_data(Smi::FromInt(index)); | 1207 info->set_data(Smi::FromInt(index)); |
1256 return info; | 1208 return info; |
1257 } | 1209 } |
1258 | 1210 |
1259 | 1211 |
1260 } // namespace internal | 1212 } // namespace internal |
1261 } // namespace v8 | 1213 } // namespace v8 |
OLD | NEW |