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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 Handle<Object> key, | 85 Handle<Object> key, |
86 Handle<Object> value, | 86 Handle<Object> value, |
87 LanguageMode language_mode) { | 87 LanguageMode language_mode) { |
88 if (object->IsUndefined() || object->IsNull()) { | 88 if (object->IsUndefined() || object->IsNull()) { |
89 THROW_NEW_ERROR( | 89 THROW_NEW_ERROR( |
90 isolate, | 90 isolate, |
91 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object), | 91 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object), |
92 Object); | 92 Object); |
93 } | 93 } |
94 | 94 |
| 95 if (object->IsJSProxy()) { |
| 96 Handle<Object> name_object; |
| 97 if (key->IsSymbol()) { |
| 98 name_object = key; |
| 99 } else { |
| 100 ASSIGN_RETURN_ON_EXCEPTION(isolate, name_object, |
| 101 Execution::ToString(isolate, key), Object); |
| 102 } |
| 103 Handle<Name> name = Handle<Name>::cast(name_object); |
| 104 return Object::SetProperty(Handle<JSProxy>::cast(object), name, value, |
| 105 language_mode); |
| 106 } |
| 107 |
95 // Check if the given key is an array index. | 108 // Check if the given key is an array index. |
96 uint32_t index = 0; | 109 uint32_t index = 0; |
97 if (key->ToArrayIndex(&index)) { | 110 if (key->ToArrayIndex(&index)) { |
98 // TODO(verwaest): Support other objects as well. | 111 // TODO(verwaest): Support non-JSObject receivers. |
99 if (!object->IsJSReceiver()) return value; | 112 if (!object->IsJSObject()) return value; |
100 return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index, | 113 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
101 value, language_mode); | 114 |
| 115 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters |
| 116 // of a string using [] notation. We need to support this too in |
| 117 // JavaScript. |
| 118 // In the case of a String object we just need to redirect the assignment to |
| 119 // the underlying string if the index is in range. Since the underlying |
| 120 // string does nothing with the assignment then we can ignore such |
| 121 // assignments. |
| 122 if (js_object->IsStringObjectWithCharacterAt(index)) { |
| 123 return value; |
| 124 } |
| 125 |
| 126 JSObject::ValidateElements(js_object); |
| 127 if (js_object->HasExternalArrayElements() || |
| 128 js_object->HasFixedTypedArrayElements()) { |
| 129 if (!value->IsNumber() && !value->IsUndefined()) { |
| 130 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, |
| 131 Execution::ToNumber(isolate, value), Object); |
| 132 } |
| 133 } |
| 134 |
| 135 MaybeHandle<Object> result = |
| 136 JSObject::SetElement(js_object, index, value, language_mode); |
| 137 JSObject::ValidateElements(js_object); |
| 138 |
| 139 return result.is_null() ? result : value; |
| 140 } |
| 141 |
| 142 if (key->IsName()) { |
| 143 Handle<Name> name = Handle<Name>::cast(key); |
| 144 if (name->AsArrayIndex(&index)) { |
| 145 // TODO(verwaest): Support non-JSObject receivers. |
| 146 if (!object->IsJSObject()) return value; |
| 147 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
| 148 if (js_object->HasExternalArrayElements()) { |
| 149 if (!value->IsNumber() && !value->IsUndefined()) { |
| 150 ASSIGN_RETURN_ON_EXCEPTION( |
| 151 isolate, value, Execution::ToNumber(isolate, value), Object); |
| 152 } |
| 153 } |
| 154 return JSObject::SetElement(js_object, index, value, language_mode); |
| 155 } else { |
| 156 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); |
| 157 return Object::SetProperty(object, name, value, language_mode); |
| 158 } |
| 159 } |
| 160 |
| 161 // Call-back into JavaScript to convert the key to a string. |
| 162 Handle<Object> converted; |
| 163 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, |
| 164 Execution::ToString(isolate, key), Object); |
| 165 Handle<String> name = Handle<String>::cast(converted); |
| 166 |
| 167 if (name->AsArrayIndex(&index)) { |
| 168 // TODO(verwaest): Support non-JSObject receivers. |
| 169 if (!object->IsJSObject()) return value; |
| 170 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
| 171 return JSObject::SetElement(js_object, index, value, language_mode); |
| 172 } |
| 173 return Object::SetProperty(object, name, value, language_mode); |
| 174 } |
| 175 |
| 176 |
| 177 MaybeHandle<Object> Runtime::DefineObjectProperty(Handle<JSObject> js_object, |
| 178 Handle<Object> key, |
| 179 Handle<Object> value, |
| 180 PropertyAttributes attrs) { |
| 181 Isolate* isolate = js_object->GetIsolate(); |
| 182 // Check if the given key is an array index. |
| 183 uint32_t index = 0; |
| 184 if (key->ToArrayIndex(&index)) { |
| 185 return JSObject::SetOwnElementIgnoreAttributes(js_object, index, value, |
| 186 attrs); |
102 } | 187 } |
103 | 188 |
104 Handle<Name> name; | 189 Handle<Name> name; |
105 if (key->IsName()) { | 190 if (key->IsName()) { |
106 name = Handle<Name>::cast(key); | 191 name = Handle<Name>::cast(key); |
107 } else { | 192 } else { |
108 // Call-back into JavaScript to convert the key to a string. | 193 // Call-back into JavaScript to convert the key to a string. |
109 Handle<Object> converted; | 194 Handle<Object> converted; |
110 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, | 195 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, |
111 Execution::ToString(isolate, key), Object); | 196 Execution::ToString(isolate, key), Object); |
112 name = Handle<String>::cast(converted); | 197 name = Handle<String>::cast(converted); |
113 } | 198 } |
114 | 199 |
115 if (name->AsArrayIndex(&index)) { | 200 if (name->AsArrayIndex(&index)) { |
116 // TODO(verwaest): Support other objects as well. | 201 return JSObject::SetOwnElementIgnoreAttributes(js_object, index, value, |
117 if (!object->IsJSReceiver()) return value; | 202 attrs); |
118 return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index, | 203 } else { |
119 value, language_mode); | 204 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); |
| 205 return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value, |
| 206 attrs); |
120 } | 207 } |
121 return Object::SetProperty(object, name, value, language_mode); | |
122 } | 208 } |
123 | 209 |
124 | 210 |
125 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate, | 211 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate, |
126 Handle<Object> obj) { | 212 Handle<Object> obj) { |
127 // 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. |
128 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); | 214 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); |
129 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); | 215 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); |
130 do { | 216 do { |
131 if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() && | 217 if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() && |
(...skipping 1130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1262 | 1348 |
1263 // Implements part of 8.12.9 DefineOwnProperty. | 1349 // Implements part of 8.12.9 DefineOwnProperty. |
1264 // There are 3 cases that lead here: | 1350 // There are 3 cases that lead here: |
1265 // Step 4a - define a new data property. | 1351 // Step 4a - define a new data property. |
1266 // Steps 9b & 12 - replace an existing accessor property with a data property. | 1352 // Steps 9b & 12 - replace an existing accessor property with a data property. |
1267 // Step 12 - update an existing data property with a data or generic | 1353 // Step 12 - update an existing data property with a data or generic |
1268 // descriptor. | 1354 // descriptor. |
1269 RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) { | 1355 RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) { |
1270 HandleScope scope(isolate); | 1356 HandleScope scope(isolate); |
1271 DCHECK(args.length() == 4); | 1357 DCHECK(args.length() == 4); |
1272 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 1358 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0); |
1273 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | 1359 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
1274 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); | 1360 CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2); |
1275 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | 1361 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); |
1276 | 1362 |
1277 uint32_t index = 0; | 1363 LookupIterator it(js_object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); |
1278 LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR; | 1364 if (it.IsFound() && it.state() == LookupIterator::ACCESS_CHECK) { |
1279 LookupIterator it = name->AsArrayIndex(&index) | 1365 if (!isolate->MayAccess(js_object)) { |
1280 ? LookupIterator(isolate, object, index, c) | 1366 return isolate->heap()->undefined_value(); |
1281 : LookupIterator(object, name, c); | 1367 } |
1282 if (it.state() == LookupIterator::ACCESS_CHECK && !it.HasAccess()) { | 1368 it.Next(); |
1283 return isolate->heap()->undefined_value(); | |
1284 } | 1369 } |
1285 | 1370 |
1286 Handle<Object> result; | 1371 Handle<Object> result; |
1287 MaybeHandle<Object> maybe_result = | 1372 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
1288 it.IsElement() | 1373 isolate, result, |
1289 ? JSObject::SetOwnElementIgnoreAttributes(object, index, value, attrs) | 1374 Runtime::DefineObjectProperty(js_object, name, obj_value, attrs)); |
1290 : JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, | |
1291 attrs); | |
1292 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result); | |
1293 return *result; | 1375 return *result; |
1294 } | 1376 } |
1295 | 1377 |
1296 | 1378 |
1297 // Return property without being observable by accessors or interceptors. | 1379 // Return property without being observable by accessors or interceptors. |
1298 RUNTIME_FUNCTION(Runtime_GetDataProperty) { | 1380 RUNTIME_FUNCTION(Runtime_GetDataProperty) { |
1299 HandleScope scope(isolate); | 1381 HandleScope scope(isolate); |
1300 DCHECK(args.length() == 2); | 1382 DCHECK(args.length() == 2); |
1301 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); | 1383 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); |
1302 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | 1384 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); |
1303 return *JSReceiver::GetDataProperty(object, name); | 1385 return *JSReceiver::GetDataProperty(object, key); |
1304 } | 1386 } |
1305 | 1387 |
1306 | 1388 |
1307 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) { | 1389 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) { |
1308 SealHandleScope shs(isolate); | 1390 SealHandleScope shs(isolate); |
1309 DCHECK(args.length() == 1); | 1391 DCHECK(args.length() == 1); |
1310 CONVERT_ARG_CHECKED(HeapObject, obj, 0); | 1392 CONVERT_ARG_CHECKED(HeapObject, obj, 0); |
1311 return isolate->heap()->ToBoolean( | 1393 return isolate->heap()->ToBoolean( |
1312 IsFastPackedElementsKind(obj->map()->elements_kind())); | 1394 IsFastPackedElementsKind(obj->map()->elements_kind())); |
1313 } | 1395 } |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1440 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | 1522 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); |
1441 | 1523 |
1442 RETURN_FAILURE_ON_EXCEPTION( | 1524 RETURN_FAILURE_ON_EXCEPTION( |
1443 isolate, | 1525 isolate, |
1444 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), | 1526 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), |
1445 setter, attrs)); | 1527 setter, attrs)); |
1446 return isolate->heap()->undefined_value(); | 1528 return isolate->heap()->undefined_value(); |
1447 } | 1529 } |
1448 } // namespace internal | 1530 } // namespace internal |
1449 } // namespace v8 | 1531 } // namespace v8 |
OLD | NEW |