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

Side by Side Diff: src/objects.cc

Issue 6613005: Implementation of strict mode in SetElement. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: SetElement and strict mode. Created 9 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 1938 matching lines...) Expand 10 before | Expand all | Expand 10 after
1949 return AddProperty(name, value, attributes); 1949 return AddProperty(name, value, attributes);
1950 } 1950 }
1951 if (result->IsReadOnly() && result->IsProperty()) { 1951 if (result->IsReadOnly() && result->IsProperty()) {
1952 if (strict == kStrictMode) { 1952 if (strict == kStrictMode) {
1953 HandleScope scope; 1953 HandleScope scope;
1954 Handle<String> key(name); 1954 Handle<String> key(name);
1955 Handle<Object> holder(this); 1955 Handle<Object> holder(this);
1956 Handle<Object> args[2] = { key, holder }; 1956 Handle<Object> args[2] = { key, holder };
1957 return Top::Throw(*Factory::NewTypeError("strict_read_only_property", 1957 return Top::Throw(*Factory::NewTypeError("strict_read_only_property",
1958 HandleVector(args, 2))); 1958 HandleVector(args, 2)));
1959
1960 } else { 1959 } else {
1961 return value; 1960 return value;
1962 } 1961 }
1963 } 1962 }
1964 // This is a real property that is not read-only, or it is a 1963 // This is a real property that is not read-only, or it is a
1965 // transition or null descriptor and there are no setters in the prototypes. 1964 // transition or null descriptor and there are no setters in the prototypes.
1966 switch (result->type()) { 1965 switch (result->type()) {
1967 case NORMAL: 1966 case NORMAL:
1968 return SetNormalizedProperty(result, value); 1967 return SetNormalizedProperty(result, value);
1969 case FIELD: 1968 case FIELD:
(...skipping 4926 matching lines...) Expand 10 before | Expand all | Expand 10 after
6896 if (this->IsStringObjectWithCharacterAt(index)) return true; 6895 if (this->IsStringObjectWithCharacterAt(index)) return true;
6897 6896
6898 Object* pt = GetPrototype(); 6897 Object* pt = GetPrototype();
6899 if (pt == Heap::null_value()) return false; 6898 if (pt == Heap::null_value()) return false;
6900 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); 6899 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
6901 } 6900 }
6902 6901
6903 6902
6904 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, 6903 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
6905 Object* value, 6904 Object* value,
6905 StrictModeFlag strict_mode,
6906 bool check_prototype) { 6906 bool check_prototype) {
6907 // Make sure that the top context does not change when doing 6907 // Make sure that the top context does not change when doing
6908 // callbacks or interceptor calls. 6908 // callbacks or interceptor calls.
6909 AssertNoContextChange ncc; 6909 AssertNoContextChange ncc;
6910 HandleScope scope; 6910 HandleScope scope;
6911 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); 6911 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
6912 Handle<JSObject> this_handle(this); 6912 Handle<JSObject> this_handle(this);
6913 Handle<Object> value_handle(value); 6913 Handle<Object> value_handle(value);
6914 if (!interceptor->setter()->IsUndefined()) { 6914 if (!interceptor->setter()->IsUndefined()) {
6915 v8::IndexedPropertySetter setter = 6915 v8::IndexedPropertySetter setter =
6916 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); 6916 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
6917 LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); 6917 LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
6918 CustomArguments args(interceptor->data(), this, this); 6918 CustomArguments args(interceptor->data(), this, this);
6919 v8::AccessorInfo info(args.end()); 6919 v8::AccessorInfo info(args.end());
6920 v8::Handle<v8::Value> result; 6920 v8::Handle<v8::Value> result;
6921 { 6921 {
6922 // Leaving JavaScript. 6922 // Leaving JavaScript.
6923 VMState state(EXTERNAL); 6923 VMState state(EXTERNAL);
6924 result = setter(index, v8::Utils::ToLocal(value_handle), info); 6924 result = setter(index, v8::Utils::ToLocal(value_handle), info);
6925 } 6925 }
6926 RETURN_IF_SCHEDULED_EXCEPTION(); 6926 RETURN_IF_SCHEDULED_EXCEPTION();
6927 if (!result.IsEmpty()) return *value_handle; 6927 if (!result.IsEmpty()) return *value_handle;
6928 } 6928 }
6929 MaybeObject* raw_result = 6929 MaybeObject* raw_result =
6930 this_handle->SetElementWithoutInterceptor(index, 6930 this_handle->SetElementWithoutInterceptor(index,
6931 *value_handle, 6931 *value_handle,
6932 strict_mode,
6932 check_prototype); 6933 check_prototype);
6933 RETURN_IF_SCHEDULED_EXCEPTION(); 6934 RETURN_IF_SCHEDULED_EXCEPTION();
6934 return raw_result; 6935 return raw_result;
6935 } 6936 }
6936 6937
6937 6938
6938 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, 6939 MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
6939 Object* structure, 6940 Object* structure,
6940 uint32_t index, 6941 uint32_t index,
6941 Object* holder) { 6942 Object* holder) {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
7035 UNREACHABLE(); 7036 UNREACHABLE();
7036 return NULL; 7037 return NULL;
7037 } 7038 }
7038 7039
7039 7040
7040 // Adding n elements in fast case is O(n*n). 7041 // Adding n elements in fast case is O(n*n).
7041 // Note: revisit design to have dual undefined values to capture absent 7042 // Note: revisit design to have dual undefined values to capture absent
7042 // elements. 7043 // elements.
7043 MaybeObject* JSObject::SetFastElement(uint32_t index, 7044 MaybeObject* JSObject::SetFastElement(uint32_t index,
7044 Object* value, 7045 Object* value,
7046 StrictModeFlag strict_mode,
7045 bool check_prototype) { 7047 bool check_prototype) {
7046 ASSERT(HasFastElements()); 7048 ASSERT(HasFastElements());
7047 7049
7048 Object* elms_obj; 7050 Object* elms_obj;
7049 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); 7051 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements();
7050 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 7052 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
7051 } 7053 }
7052 FixedArray* elms = FixedArray::cast(elms_obj); 7054 FixedArray* elms = FixedArray::cast(elms_obj);
7053 uint32_t elms_length = static_cast<uint32_t>(elms->length()); 7055 uint32_t elms_length = static_cast<uint32_t>(elms->length());
7054 7056
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
7091 return value; 7093 return value;
7092 } 7094 }
7093 } 7095 }
7094 7096
7095 // Otherwise default to slow case. 7097 // Otherwise default to slow case.
7096 Object* obj; 7098 Object* obj;
7097 { MaybeObject* maybe_obj = NormalizeElements(); 7099 { MaybeObject* maybe_obj = NormalizeElements();
7098 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7100 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7099 } 7101 }
7100 ASSERT(HasDictionaryElements()); 7102 ASSERT(HasDictionaryElements());
7101 return SetElement(index, value, check_prototype); 7103 return SetElement(index, value, strict_mode, check_prototype);
7102 } 7104 }
7103 7105
7104 7106
7105 MaybeObject* JSObject::SetElement(uint32_t index, 7107 MaybeObject* JSObject::SetElement(uint32_t index,
7106 Object* value, 7108 Object* value,
7109 StrictModeFlag strict_mode,
7107 bool check_prototype) { 7110 bool check_prototype) {
7108 // Check access rights if needed. 7111 // Check access rights if needed.
7109 if (IsAccessCheckNeeded() && 7112 if (IsAccessCheckNeeded() &&
7110 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { 7113 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) {
7111 HandleScope scope; 7114 HandleScope scope;
7112 Handle<Object> value_handle(value); 7115 Handle<Object> value_handle(value);
7113 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); 7116 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
7114 return *value_handle; 7117 return *value_handle;
7115 } 7118 }
7116 7119
7117 if (IsJSGlobalProxy()) { 7120 if (IsJSGlobalProxy()) {
7118 Object* proto = GetPrototype(); 7121 Object* proto = GetPrototype();
7119 if (proto->IsNull()) return value; 7122 if (proto->IsNull()) return value;
7120 ASSERT(proto->IsJSGlobalObject()); 7123 ASSERT(proto->IsJSGlobalObject());
7121 return JSObject::cast(proto)->SetElement(index, value, check_prototype); 7124 return JSObject::cast(proto)->SetElement(index,
7125 value,
7126 strict_mode,
7127 check_prototype);
7122 } 7128 }
7123 7129
7124 // Check for lookup interceptor 7130 // Check for lookup interceptor
7125 if (HasIndexedInterceptor()) { 7131 if (HasIndexedInterceptor()) {
7126 return SetElementWithInterceptor(index, value, check_prototype); 7132 return SetElementWithInterceptor(index,
7133 value,
7134 strict_mode,
7135 check_prototype);
7127 } 7136 }
7128 7137
7129 return SetElementWithoutInterceptor(index, value, check_prototype); 7138 return SetElementWithoutInterceptor(index,
7139 value,
7140 strict_mode,
7141 check_prototype);
7130 } 7142 }
7131 7143
7132 7144
7133 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, 7145 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
7134 Object* value, 7146 Object* value,
7147 StrictModeFlag strict_mode,
7135 bool check_prototype) { 7148 bool check_prototype) {
7136 switch (GetElementsKind()) { 7149 switch (GetElementsKind()) {
7137 case FAST_ELEMENTS: 7150 case FAST_ELEMENTS:
7138 // Fast case. 7151 // Fast case.
7139 return SetFastElement(index, value, check_prototype); 7152 return SetFastElement(index, value, strict_mode, check_prototype);
7140 case PIXEL_ELEMENTS: { 7153 case PIXEL_ELEMENTS: {
7141 PixelArray* pixels = PixelArray::cast(elements()); 7154 PixelArray* pixels = PixelArray::cast(elements());
7142 return pixels->SetValue(index, value); 7155 return pixels->SetValue(index, value);
7143 } 7156 }
7144 case EXTERNAL_BYTE_ELEMENTS: { 7157 case EXTERNAL_BYTE_ELEMENTS: {
7145 ExternalByteArray* array = ExternalByteArray::cast(elements()); 7158 ExternalByteArray* array = ExternalByteArray::cast(elements());
7146 return array->SetValue(index, value); 7159 return array->SetValue(index, value);
7147 } 7160 }
7148 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { 7161 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
7149 ExternalUnsignedByteArray* array = 7162 ExternalUnsignedByteArray* array =
(...skipping 28 matching lines...) Expand all
7178 NumberDictionary* dictionary = NumberDictionary::cast(elms); 7191 NumberDictionary* dictionary = NumberDictionary::cast(elms);
7179 7192
7180 int entry = dictionary->FindEntry(index); 7193 int entry = dictionary->FindEntry(index);
7181 if (entry != NumberDictionary::kNotFound) { 7194 if (entry != NumberDictionary::kNotFound) {
7182 Object* element = dictionary->ValueAt(entry); 7195 Object* element = dictionary->ValueAt(entry);
7183 PropertyDetails details = dictionary->DetailsAt(entry); 7196 PropertyDetails details = dictionary->DetailsAt(entry);
7184 if (details.type() == CALLBACKS) { 7197 if (details.type() == CALLBACKS) {
7185 return SetElementWithCallback(element, index, value, this); 7198 return SetElementWithCallback(element, index, value, this);
7186 } else { 7199 } else {
7187 dictionary->UpdateMaxNumberKey(index); 7200 dictionary->UpdateMaxNumberKey(index);
7188 dictionary->ValueAtPut(entry, value); 7201 // If put fails instrict mode, throw exception.
7202 if (!dictionary->ValueAtPut(entry, value) &&
7203 strict_mode == kStrictMode) {
7204 Handle<Object> number(Factory::NewNumberFromUint(index));
7205 Handle<Object> holder(this);
7206 Handle<Object> args[2] = { number, holder };
7207 return Top::Throw(
7208 *Factory::NewTypeError("strict_read_only_property",
7209 HandleVector(args, 2)));
7210 }
7189 } 7211 }
7190 } else { 7212 } else {
7191 // Index not already used. Look for an accessor in the prototype chain. 7213 // Index not already used. Look for an accessor in the prototype chain.
7192 if (check_prototype) { 7214 if (check_prototype) {
7193 bool found; 7215 bool found;
7194 MaybeObject* result = 7216 MaybeObject* result =
7217 // Strict mode not needed. No-setter case already handled.
7195 SetElementWithCallbackSetterInPrototypes(index, value, &found); 7218 SetElementWithCallbackSetterInPrototypes(index, value, &found);
7196 if (found) return result; 7219 if (found) return result;
7197 } 7220 }
7198 // When we set the is_extensible flag to false we always force 7221 // When we set the is_extensible flag to false we always force
7199 // the element into dictionary mode (and force them to stay there). 7222 // the element into dictionary mode (and force them to stay there).
7200 if (!map()->is_extensible()) { 7223 if (!map()->is_extensible()) {
7201 Handle<Object> number(Factory::NewNumberFromUint(index)); 7224 Handle<Object> number(Factory::NewNumberFromUint(index));
7202 Handle<String> index_string(Factory::NumberToString(number)); 7225 Handle<String> index_string(Factory::NumberToString(number));
7203 Handle<Object> args[1] = { index_string }; 7226 Handle<Object> args[1] = { index_string };
7204 return Top::Throw(*Factory::NewTypeError("object_not_extensible", 7227 return Top::Throw(*Factory::NewTypeError("object_not_extensible",
(...skipping 2830 matching lines...) Expand 10 before | Expand all | Expand 10 after
10035 if (break_point_objects()->IsUndefined()) return 0; 10058 if (break_point_objects()->IsUndefined()) return 0;
10036 // Single beak point. 10059 // Single beak point.
10037 if (!break_point_objects()->IsFixedArray()) return 1; 10060 if (!break_point_objects()->IsFixedArray()) return 1;
10038 // Multiple break points. 10061 // Multiple break points.
10039 return FixedArray::cast(break_point_objects())->length(); 10062 return FixedArray::cast(break_point_objects())->length();
10040 } 10063 }
10041 #endif 10064 #endif
10042 10065
10043 10066
10044 } } // namespace v8::internal 10067 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698