| 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 | |
| 108 // Check if the given key is an array index. | 95 // Check if the given key is an array index. |
| 109 uint32_t index = 0; | 96 uint32_t index = 0; |
| 110 if (key->ToArrayIndex(&index)) { | 97 if (key->ToArrayIndex(&index)) { |
| 111 // TODO(verwaest): Support non-JSObject receivers. | 98 // TODO(verwaest): Support other objects as well. |
| 112 if (!object->IsJSObject()) return value; | 99 if (!object->IsJSReceiver()) return value; |
| 113 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | 100 return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index, |
| 114 | 101 value, language_mode); |
| 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( | |
| 178 Handle<JSObject> js_object, Handle<Object> key, Handle<Object> value, | |
| 179 PropertyAttributes attrs, | |
| 180 JSObject::ExecutableAccessorInfoHandling handling) { | |
| 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, handling); | |
| 187 } | 102 } |
| 188 | 103 |
| 189 Handle<Name> name; | 104 Handle<Name> name; |
| 190 if (key->IsName()) { | 105 if (key->IsName()) { |
| 191 name = Handle<Name>::cast(key); | 106 name = Handle<Name>::cast(key); |
| 192 } else { | 107 } else { |
| 193 // Call-back into JavaScript to convert the key to a string. | 108 // Call-back into JavaScript to convert the key to a string. |
| 194 Handle<Object> converted; | 109 Handle<Object> converted; |
| 195 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, | 110 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, |
| 196 Execution::ToString(isolate, key), Object); | 111 Execution::ToString(isolate, key), Object); |
| 197 name = Handle<String>::cast(converted); | 112 name = Handle<String>::cast(converted); |
| 198 } | 113 } |
| 199 | 114 |
| 200 if (name->AsArrayIndex(&index)) { | 115 if (name->AsArrayIndex(&index)) { |
| 201 return JSObject::SetOwnElementIgnoreAttributes(js_object, index, value, | 116 // TODO(verwaest): Support other objects as well. |
| 202 attrs, handling); | 117 if (!object->IsJSReceiver()) return value; |
| 203 } else { | 118 return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index, |
| 204 if (name->IsString()) name = String::Flatten(Handle<String>::cast(name)); | 119 value, language_mode); |
| 205 return JSObject::SetOwnPropertyIgnoreAttributes(js_object, name, value, | |
| 206 attrs, handling); | |
| 207 } | 120 } |
| 121 return Object::SetProperty(object, name, value, language_mode); |
| 208 } | 122 } |
| 209 | 123 |
| 210 | 124 |
| 211 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate, | 125 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate, |
| 212 Handle<Object> obj) { | 126 Handle<Object> obj) { |
| 213 // We don't expect access checks to be needed on JSProxy objects. | 127 // We don't expect access checks to be needed on JSProxy objects. |
| 214 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); | 128 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); |
| 215 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); | 129 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); |
| 216 do { | 130 do { |
| 217 if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() && | 131 if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() && |
| (...skipping 1130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1348 | 1262 |
| 1349 // Implements part of 8.12.9 DefineOwnProperty. | 1263 // Implements part of 8.12.9 DefineOwnProperty. |
| 1350 // There are 3 cases that lead here: | 1264 // There are 3 cases that lead here: |
| 1351 // Step 4a - define a new data property. | 1265 // Step 4a - define a new data property. |
| 1352 // Steps 9b & 12 - replace an existing accessor property with a data property. | 1266 // Steps 9b & 12 - replace an existing accessor property with a data property. |
| 1353 // Step 12 - update an existing data property with a data or generic | 1267 // Step 12 - update an existing data property with a data or generic |
| 1354 // descriptor. | 1268 // descriptor. |
| 1355 RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) { | 1269 RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) { |
| 1356 HandleScope scope(isolate); | 1270 HandleScope scope(isolate); |
| 1357 DCHECK(args.length() == 4); | 1271 DCHECK(args.length() == 4); |
| 1358 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0); | 1272 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
| 1359 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | 1273 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
| 1360 CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2); | 1274 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); |
| 1361 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | 1275 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); |
| 1362 | 1276 |
| 1363 LookupIterator it(js_object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); | 1277 uint32_t index = 0; |
| 1364 if (it.IsFound() && it.state() == LookupIterator::ACCESS_CHECK) { | 1278 LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR; |
| 1365 if (!isolate->MayAccess(js_object)) { | 1279 LookupIterator it = name->AsArrayIndex(&index) |
| 1366 return isolate->heap()->undefined_value(); | 1280 ? LookupIterator(isolate, object, index, c) |
| 1367 } | 1281 : LookupIterator(object, name, c); |
| 1368 it.Next(); | 1282 if (it.state() == LookupIterator::ACCESS_CHECK && !it.HasAccess()) { |
| 1283 return isolate->heap()->undefined_value(); |
| 1369 } | 1284 } |
| 1370 | 1285 |
| 1371 Handle<Object> result; | 1286 Handle<Object> result; |
| 1372 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1287 MaybeHandle<Object> maybe_result = |
| 1373 isolate, result, | 1288 it.IsElement() |
| 1374 Runtime::DefineObjectProperty(js_object, name, obj_value, attrs, | 1289 ? JSObject::SetOwnElementIgnoreAttributes(object, index, value, attrs, |
| 1375 JSObject::DONT_FORCE_FIELD)); | 1290 JSObject::DONT_FORCE_FIELD) |
| 1291 : JSObject::SetOwnPropertyIgnoreAttributes( |
| 1292 object, name, value, attrs, JSObject::DONT_FORCE_FIELD); |
| 1293 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result); |
| 1376 return *result; | 1294 return *result; |
| 1377 } | 1295 } |
| 1378 | 1296 |
| 1379 | 1297 |
| 1380 // Return property without being observable by accessors or interceptors. | 1298 // Return property without being observable by accessors or interceptors. |
| 1381 RUNTIME_FUNCTION(Runtime_GetDataProperty) { | 1299 RUNTIME_FUNCTION(Runtime_GetDataProperty) { |
| 1382 HandleScope scope(isolate); | 1300 HandleScope scope(isolate); |
| 1383 DCHECK(args.length() == 2); | 1301 DCHECK(args.length() == 2); |
| 1384 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); | 1302 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); |
| 1385 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); | 1303 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
| 1386 return *JSReceiver::GetDataProperty(object, key); | 1304 return *JSReceiver::GetDataProperty(object, name); |
| 1387 } | 1305 } |
| 1388 | 1306 |
| 1389 | 1307 |
| 1390 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) { | 1308 RUNTIME_FUNCTION(Runtime_HasFastPackedElements) { |
| 1391 SealHandleScope shs(isolate); | 1309 SealHandleScope shs(isolate); |
| 1392 DCHECK(args.length() == 1); | 1310 DCHECK(args.length() == 1); |
| 1393 CONVERT_ARG_CHECKED(HeapObject, obj, 0); | 1311 CONVERT_ARG_CHECKED(HeapObject, obj, 0); |
| 1394 return isolate->heap()->ToBoolean( | 1312 return isolate->heap()->ToBoolean( |
| 1395 IsFastPackedElementsKind(obj->map()->elements_kind())); | 1313 IsFastPackedElementsKind(obj->map()->elements_kind())); |
| 1396 } | 1314 } |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); | 1441 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); |
| 1524 | 1442 |
| 1525 RETURN_FAILURE_ON_EXCEPTION( | 1443 RETURN_FAILURE_ON_EXCEPTION( |
| 1526 isolate, | 1444 isolate, |
| 1527 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), | 1445 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), |
| 1528 setter, attrs)); | 1446 setter, attrs)); |
| 1529 return isolate->heap()->undefined_value(); | 1447 return isolate->heap()->undefined_value(); |
| 1530 } | 1448 } |
| 1531 } // namespace internal | 1449 } // namespace internal |
| 1532 } // namespace v8 | 1450 } // namespace v8 |
| OLD | NEW |