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 |