OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 5013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5024 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { | 5024 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { |
5025 HandleScope scope(isolate); | 5025 HandleScope scope(isolate); |
5026 ASSERT(args.length() == 4); | 5026 ASSERT(args.length() == 4); |
5027 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0); | 5027 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0); |
5028 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | 5028 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
5029 CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2); | 5029 CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2); |
5030 CONVERT_SMI_ARG_CHECKED(unchecked, 3); | 5030 CONVERT_SMI_ARG_CHECKED(unchecked, 3); |
5031 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 5031 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
5032 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 5032 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); |
5033 | 5033 |
5034 LookupResult result(isolate); | 5034 LookupResult lookup(isolate); |
5035 js_object->LocalLookupRealNamedProperty(*name, &result); | 5035 js_object->LocalLookupRealNamedProperty(*name, &lookup); |
5036 | 5036 |
5037 // Special case for callback properties. | 5037 // Special case for callback properties. |
5038 if (result.IsPropertyCallbacks()) { | 5038 if (lookup.IsPropertyCallbacks()) { |
5039 Object* callback = result.GetCallbackObject(); | 5039 Handle<Object> callback(lookup.GetCallbackObject(), isolate); |
5040 // To be compatible with Safari we do not change the value on API objects | 5040 // To be compatible with Safari we do not change the value on API objects |
5041 // in Object.defineProperty(). Firefox disagrees here, and actually changes | 5041 // in Object.defineProperty(). Firefox disagrees here, and actually changes |
5042 // the value. | 5042 // the value. |
5043 if (callback->IsAccessorInfo()) { | 5043 if (callback->IsAccessorInfo()) { |
5044 return isolate->heap()->undefined_value(); | 5044 return isolate->heap()->undefined_value(); |
5045 } | 5045 } |
5046 // Avoid redefining foreign callback as data property, just use the stored | 5046 // Avoid redefining foreign callback as data property, just use the stored |
5047 // setter to update the value instead. | 5047 // setter to update the value instead. |
5048 // TODO(mstarzinger): So far this only works if property attributes don't | 5048 // TODO(mstarzinger): So far this only works if property attributes don't |
5049 // change, this should be fixed once we cleanup the underlying code. | 5049 // change, this should be fixed once we cleanup the underlying code. |
5050 if (callback->IsForeign() && result.GetAttributes() == attr) { | 5050 if (callback->IsForeign() && lookup.GetAttributes() == attr) { |
5051 Handle<Object> result_object = | 5051 Handle<Object> result_object = |
5052 JSObject::SetPropertyWithCallback(js_object, | 5052 JSObject::SetPropertyWithCallback(js_object, |
5053 handle(callback, isolate), | 5053 callback, |
5054 name, | 5054 name, |
5055 obj_value, | 5055 obj_value, |
5056 handle(result.holder()), | 5056 handle(lookup.holder()), |
5057 kStrictMode); | 5057 kStrictMode); |
5058 RETURN_IF_EMPTY_HANDLE(isolate, result_object); | 5058 RETURN_IF_EMPTY_HANDLE(isolate, result_object); |
5059 return *result_object; | 5059 return *result_object; |
5060 } | 5060 } |
5061 } | 5061 } |
5062 | 5062 |
5063 // Take special care when attributes are different and there is already | 5063 // Take special care when attributes are different and there is already |
5064 // a property. For simplicity we normalize the property which enables us | 5064 // a property. For simplicity we normalize the property which enables us |
5065 // to not worry about changing the instance_descriptor and creating a new | 5065 // to not worry about changing the instance_descriptor and creating a new |
5066 // map. The current version of SetObjectProperty does not handle attributes | 5066 // map. The current version of SetObjectProperty does not handle attributes |
5067 // correctly in the case where a property is a field and is reset with | 5067 // correctly in the case where a property is a field and is reset with |
5068 // new attributes. | 5068 // new attributes. |
5069 if (result.IsFound() && | 5069 if (lookup.IsFound() && |
5070 (attr != result.GetAttributes() || result.IsPropertyCallbacks())) { | 5070 (attr != lookup.GetAttributes() || lookup.IsPropertyCallbacks())) { |
5071 // New attributes - normalize to avoid writing to instance descriptor | 5071 // New attributes - normalize to avoid writing to instance descriptor |
5072 if (js_object->IsJSGlobalProxy()) { | 5072 if (js_object->IsJSGlobalProxy()) { |
5073 // Since the result is a property, the prototype will exist so | 5073 // Since the result is a property, the prototype will exist so |
5074 // we don't have to check for null. | 5074 // we don't have to check for null. |
5075 js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype())); | 5075 js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype())); |
5076 } | 5076 } |
5077 JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); | 5077 JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); |
5078 // Use IgnoreAttributes version since a readonly property may be | 5078 // Use IgnoreAttributes version since a readonly property may be |
5079 // overridden and SetProperty does not allow this. | 5079 // overridden and SetProperty does not allow this. |
5080 Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( | 5080 Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( |
5081 js_object, name, obj_value, attr); | 5081 js_object, name, obj_value, attr); |
5082 RETURN_IF_EMPTY_HANDLE(isolate, result); | 5082 RETURN_IF_EMPTY_HANDLE(isolate, result); |
5083 return *result; | 5083 return *result; |
5084 } | 5084 } |
5085 | 5085 |
5086 return Runtime::ForceSetObjectProperty(isolate, | 5086 Handle<Object> result = Runtime::ForceSetObjectProperty(isolate, js_object, |
5087 js_object, | 5087 name, |
5088 name, | 5088 obj_value, |
5089 obj_value, | 5089 attr); |
5090 attr); | 5090 RETURN_IF_EMPTY_HANDLE(isolate, result); |
| 5091 return *result; |
5091 } | 5092 } |
5092 | 5093 |
5093 | 5094 |
5094 // Return property without being observable by accessors or interceptors. | 5095 // Return property without being observable by accessors or interceptors. |
5095 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) { | 5096 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) { |
5096 SealHandleScope shs(isolate); | 5097 SealHandleScope shs(isolate); |
5097 ASSERT(args.length() == 2); | 5098 ASSERT(args.length() == 2); |
5098 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 5099 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
5099 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); | 5100 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); |
5100 LookupResult lookup(isolate); | 5101 LookupResult lookup(isolate); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5234 index, *value, attr, strict_mode, true, set_mode); | 5235 index, *value, attr, strict_mode, true, set_mode); |
5235 } else { | 5236 } else { |
5236 Handle<Object> result = | 5237 Handle<Object> result = |
5237 JSReceiver::SetProperty(js_object, name, value, attr, strict_mode); | 5238 JSReceiver::SetProperty(js_object, name, value, attr, strict_mode); |
5238 RETURN_IF_EMPTY_HANDLE(isolate, result); | 5239 RETURN_IF_EMPTY_HANDLE(isolate, result); |
5239 return *result; | 5240 return *result; |
5240 } | 5241 } |
5241 } | 5242 } |
5242 | 5243 |
5243 | 5244 |
5244 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, | 5245 Handle<Object> Runtime::ForceSetObjectProperty(Isolate* isolate, |
5245 Handle<JSObject> js_object, | 5246 Handle<JSObject> js_object, |
5246 Handle<Object> key, | 5247 Handle<Object> key, |
5247 Handle<Object> value, | 5248 Handle<Object> value, |
5248 PropertyAttributes attr) { | 5249 PropertyAttributes attr) { |
5249 HandleScope scope(isolate); | |
5250 | |
5251 // Check if the given key is an array index. | 5250 // Check if the given key is an array index. |
5252 uint32_t index; | 5251 uint32_t index; |
5253 if (key->ToArrayIndex(&index)) { | 5252 if (key->ToArrayIndex(&index)) { |
5254 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters | 5253 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters |
5255 // of a string using [] notation. We need to support this too in | 5254 // of a string using [] notation. We need to support this too in |
5256 // JavaScript. | 5255 // JavaScript. |
5257 // In the case of a String object we just need to redirect the assignment to | 5256 // In the case of a String object we just need to redirect the assignment to |
5258 // the underlying string if the index is in range. Since the underlying | 5257 // the underlying string if the index is in range. Since the underlying |
5259 // string does nothing with the assignment then we can ignore such | 5258 // string does nothing with the assignment then we can ignore such |
5260 // assignments. | 5259 // assignments. |
5261 if (js_object->IsStringObjectWithCharacterAt(index)) { | 5260 if (js_object->IsStringObjectWithCharacterAt(index)) { |
5262 return *value; | 5261 return value; |
5263 } | 5262 } |
5264 | 5263 |
5265 return js_object->SetElement( | 5264 return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode, |
5266 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); | 5265 false, |
| 5266 DEFINE_PROPERTY); |
5267 } | 5267 } |
5268 | 5268 |
5269 if (key->IsName()) { | 5269 if (key->IsName()) { |
5270 Handle<Name> name = Handle<Name>::cast(key); | 5270 Handle<Name> name = Handle<Name>::cast(key); |
5271 if (name->AsArrayIndex(&index)) { | 5271 if (name->AsArrayIndex(&index)) { |
5272 return js_object->SetElement( | 5272 return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode, |
5273 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); | 5273 false, |
| 5274 DEFINE_PROPERTY); |
5274 } else { | 5275 } else { |
5275 if (name->IsString()) Handle<String>::cast(name)->TryFlatten(); | 5276 if (name->IsString()) Handle<String>::cast(name)->TryFlatten(); |
5276 Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( | 5277 return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name, |
5277 js_object, name, value, attr); | 5278 value, attr); |
5278 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
5279 return *result; | |
5280 } | 5279 } |
5281 } | 5280 } |
5282 | 5281 |
5283 // Call-back into JavaScript to convert the key to a string. | 5282 // Call-back into JavaScript to convert the key to a string. |
5284 bool has_pending_exception = false; | 5283 bool has_pending_exception = false; |
5285 Handle<Object> converted = | 5284 Handle<Object> converted = |
5286 Execution::ToString(isolate, key, &has_pending_exception); | 5285 Execution::ToString(isolate, key, &has_pending_exception); |
5287 if (has_pending_exception) return Failure::Exception(); | 5286 if (has_pending_exception) return Handle<Object>(); // exception |
5288 Handle<String> name = Handle<String>::cast(converted); | 5287 Handle<String> name = Handle<String>::cast(converted); |
5289 | 5288 |
5290 if (name->AsArrayIndex(&index)) { | 5289 if (name->AsArrayIndex(&index)) { |
5291 return js_object->SetElement( | 5290 return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode, |
5292 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); | 5291 false, |
| 5292 DEFINE_PROPERTY); |
5293 } else { | 5293 } else { |
5294 Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( | 5294 return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name, value, |
5295 js_object, name, value, attr); | 5295 attr); |
5296 RETURN_IF_EMPTY_HANDLE(isolate, result); | |
5297 return *result; | |
5298 } | 5296 } |
5299 } | 5297 } |
5300 | 5298 |
5301 | 5299 |
5302 MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate, | 5300 MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate, |
5303 Handle<JSReceiver> receiver, | 5301 Handle<JSReceiver> receiver, |
5304 Handle<Object> key, | 5302 Handle<Object> key, |
5305 JSReceiver::DeleteMode mode) { | 5303 JSReceiver::DeleteMode mode) { |
5306 HandleScope scope(isolate); | 5304 HandleScope scope(isolate); |
5307 | 5305 |
(...skipping 9530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14838 // Handle last resort GC and make sure to allow future allocations | 14836 // Handle last resort GC and make sure to allow future allocations |
14839 // to grow the heap without causing GCs (if possible). | 14837 // to grow the heap without causing GCs (if possible). |
14840 isolate->counters()->gc_last_resort_from_js()->Increment(); | 14838 isolate->counters()->gc_last_resort_from_js()->Increment(); |
14841 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 14839 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
14842 "Runtime::PerformGC"); | 14840 "Runtime::PerformGC"); |
14843 } | 14841 } |
14844 } | 14842 } |
14845 | 14843 |
14846 | 14844 |
14847 } } // namespace v8::internal | 14845 } } // namespace v8::internal |
OLD | NEW |