OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 <stdlib.h> | 5 #include <stdlib.h> |
6 #include <limits> | 6 #include <limits> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 1928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1939 Factory* factory = isolate->factory(); | 1939 Factory* factory = isolate->factory(); |
1940 | 1940 |
1941 PropertyAttributes attrs; | 1941 PropertyAttributes attrs; |
1942 uint32_t index = 0; | 1942 uint32_t index = 0; |
1943 Handle<Object> value; | 1943 Handle<Object> value; |
1944 MaybeHandle<AccessorPair> maybe_accessors; | 1944 MaybeHandle<AccessorPair> maybe_accessors; |
1945 // TODO(verwaest): Unify once indexed properties can be handled by the | 1945 // TODO(verwaest): Unify once indexed properties can be handled by the |
1946 // LookupIterator. | 1946 // LookupIterator. |
1947 if (name->AsArrayIndex(&index)) { | 1947 if (name->AsArrayIndex(&index)) { |
1948 // Get attributes. | 1948 // Get attributes. |
1949 attrs = JSReceiver::GetOwnElementAttribute(obj, index); | 1949 Maybe<PropertyAttributes> maybe = |
1950 if (attrs == ABSENT) { | 1950 JSReceiver::GetOwnElementAttribute(obj, index); |
1951 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 1951 if (!maybe.has_value) return MaybeHandle<Object>(); |
1952 return factory->undefined_value(); | 1952 attrs = maybe.value; |
1953 } | 1953 if (attrs == ABSENT) return factory->undefined_value(); |
1954 | 1954 |
1955 // Get AccessorPair if present. | 1955 // Get AccessorPair if present. |
1956 maybe_accessors = JSObject::GetOwnElementAccessorPair(obj, index); | 1956 maybe_accessors = JSObject::GetOwnElementAccessorPair(obj, index); |
1957 | 1957 |
1958 // Get value if not an AccessorPair. | 1958 // Get value if not an AccessorPair. |
1959 if (maybe_accessors.is_null()) { | 1959 if (maybe_accessors.is_null()) { |
1960 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, | 1960 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, |
1961 Runtime::GetElementOrCharAt(isolate, obj, index), Object); | 1961 Runtime::GetElementOrCharAt(isolate, obj, index), Object); |
1962 } | 1962 } |
1963 } else { | 1963 } else { |
1964 // Get attributes. | 1964 // Get attributes. |
1965 LookupIterator it(obj, name, LookupIterator::CHECK_OWN); | 1965 LookupIterator it(obj, name, LookupIterator::CHECK_OWN); |
1966 attrs = JSObject::GetPropertyAttributes(&it); | 1966 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it); |
1967 if (attrs == ABSENT) { | 1967 if (!maybe.has_value) return MaybeHandle<Object>(); |
1968 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 1968 attrs = maybe.value; |
1969 return factory->undefined_value(); | 1969 if (attrs == ABSENT) return factory->undefined_value(); |
1970 } | |
1971 | 1970 |
1972 // Get AccessorPair if present. | 1971 // Get AccessorPair if present. |
1973 if (it.state() == LookupIterator::PROPERTY && | 1972 if (it.state() == LookupIterator::PROPERTY && |
1974 it.property_kind() == LookupIterator::ACCESSOR && | 1973 it.property_kind() == LookupIterator::ACCESSOR && |
1975 it.GetAccessors()->IsAccessorPair()) { | 1974 it.GetAccessors()->IsAccessorPair()) { |
1976 maybe_accessors = Handle<AccessorPair>::cast(it.GetAccessors()); | 1975 maybe_accessors = Handle<AccessorPair>::cast(it.GetAccessors()); |
1977 } | 1976 } |
1978 | 1977 |
1979 // Get value if not an AccessorPair. | 1978 // Get value if not an AccessorPair. |
1980 if (maybe_accessors.is_null()) { | 1979 if (maybe_accessors.is_null()) { |
1981 ASSIGN_RETURN_ON_EXCEPTION( | 1980 ASSIGN_RETURN_ON_EXCEPTION( |
1982 isolate, value, Object::GetProperty(&it), Object); | 1981 isolate, value, Object::GetProperty(&it), Object); |
1983 } | 1982 } |
1984 } | 1983 } |
1985 ASSERT(!isolate->has_scheduled_exception()); | 1984 ASSERT(!isolate->has_pending_exception()); |
1986 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE); | 1985 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE); |
1987 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); | 1986 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); |
1988 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); | 1987 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); |
1989 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(!maybe_accessors.is_null())); | 1988 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(!maybe_accessors.is_null())); |
1990 | 1989 |
1991 Handle<AccessorPair> accessors; | 1990 Handle<AccessorPair> accessors; |
1992 if (maybe_accessors.ToHandle(&accessors)) { | 1991 if (maybe_accessors.ToHandle(&accessors)) { |
1993 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate); | 1992 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate); |
1994 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate); | 1993 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate); |
1995 elms->set(GETTER_INDEX, *getter); | 1994 elms->set(GETTER_INDEX, *getter); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2136 } | 2135 } |
2137 | 2136 |
2138 | 2137 |
2139 // May throw a RedeclarationError. | 2138 // May throw a RedeclarationError. |
2140 static Object* DeclareGlobals(Isolate* isolate, Handle<GlobalObject> global, | 2139 static Object* DeclareGlobals(Isolate* isolate, Handle<GlobalObject> global, |
2141 Handle<String> name, Handle<Object> value, | 2140 Handle<String> name, Handle<Object> value, |
2142 PropertyAttributes attr, bool is_var, | 2141 PropertyAttributes attr, bool is_var, |
2143 bool is_const, bool is_function) { | 2142 bool is_const, bool is_function) { |
2144 // Do the lookup own properties only, see ES5 erratum. | 2143 // Do the lookup own properties only, see ES5 erratum. |
2145 LookupIterator it(global, name, LookupIterator::CHECK_HIDDEN); | 2144 LookupIterator it(global, name, LookupIterator::CHECK_HIDDEN); |
2146 PropertyAttributes old_attributes = JSReceiver::GetPropertyAttributes(&it); | 2145 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 2146 ASSERT(maybe.has_value); |
| 2147 PropertyAttributes old_attributes = maybe.value; |
2147 | 2148 |
2148 if (old_attributes != ABSENT) { | 2149 if (old_attributes != ABSENT) { |
2149 // The name was declared before; check for conflicting re-declarations. | 2150 // The name was declared before; check for conflicting re-declarations. |
2150 if (is_const) return ThrowRedeclarationError(isolate, name); | 2151 if (is_const) return ThrowRedeclarationError(isolate, name); |
2151 | 2152 |
2152 // Skip var re-declarations. | 2153 // Skip var re-declarations. |
2153 if (is_var) return isolate->heap()->undefined_value(); | 2154 if (is_var) return isolate->heap()->undefined_value(); |
2154 | 2155 |
2155 ASSERT(is_function); | 2156 ASSERT(is_function); |
2156 if ((old_attributes & DONT_DELETE) != 0) { | 2157 if ((old_attributes & DONT_DELETE) != 0) { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2264 // of the constant is the first argument and the initial value | 2265 // of the constant is the first argument and the initial value |
2265 // is the second. | 2266 // is the second. |
2266 RUNTIME_ASSERT(args.length() == 2); | 2267 RUNTIME_ASSERT(args.length() == 2); |
2267 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); | 2268 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); |
2268 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); | 2269 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); |
2269 | 2270 |
2270 Handle<GlobalObject> global = isolate->global_object(); | 2271 Handle<GlobalObject> global = isolate->global_object(); |
2271 | 2272 |
2272 // Lookup the property as own on the global object. | 2273 // Lookup the property as own on the global object. |
2273 LookupIterator it(global, name, LookupIterator::CHECK_HIDDEN); | 2274 LookupIterator it(global, name, LookupIterator::CHECK_HIDDEN); |
2274 PropertyAttributes old_attributes = JSReceiver::GetPropertyAttributes(&it); | 2275 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 2276 ASSERT(maybe.has_value); |
| 2277 PropertyAttributes old_attributes = maybe.value; |
2275 | 2278 |
2276 PropertyAttributes attr = | 2279 PropertyAttributes attr = |
2277 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | 2280 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); |
2278 // Set the value if the property is either missing, or the property attributes | 2281 // Set the value if the property is either missing, or the property attributes |
2279 // allow setting the value without invoking an accessor. | 2282 // allow setting the value without invoking an accessor. |
2280 if (it.IsFound()) { | 2283 if (it.IsFound()) { |
2281 // Ignore if we can't reconfigure the value. | 2284 // Ignore if we can't reconfigure the value. |
2282 if ((old_attributes & DONT_DELETE) != 0) { | 2285 if ((old_attributes & DONT_DELETE) != 0) { |
2283 if ((old_attributes & READ_ONLY) != 0 || | 2286 if ((old_attributes & READ_ONLY) != 0 || |
2284 it.property_kind() == LookupIterator::ACCESSOR) { | 2287 it.property_kind() == LookupIterator::ACCESSOR) { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2412 if (attributes == ABSENT) { | 2415 if (attributes == ABSENT) { |
2413 holder = handle(context_arg->extension(), isolate); | 2416 holder = handle(context_arg->extension(), isolate); |
2414 } else { | 2417 } else { |
2415 // For JSContextExtensionObjects, the initializer can be run multiple times | 2418 // For JSContextExtensionObjects, the initializer can be run multiple times |
2416 // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the | 2419 // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the |
2417 // first assignment should go through. For JSGlobalObjects, additionally any | 2420 // first assignment should go through. For JSGlobalObjects, additionally any |
2418 // code can run in between that modifies the declared property. | 2421 // code can run in between that modifies the declared property. |
2419 ASSERT(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject()); | 2422 ASSERT(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject()); |
2420 | 2423 |
2421 LookupIterator it(holder, name, LookupIterator::CHECK_HIDDEN); | 2424 LookupIterator it(holder, name, LookupIterator::CHECK_HIDDEN); |
2422 PropertyAttributes old_attributes = JSReceiver::GetPropertyAttributes(&it); | 2425 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); |
| 2426 if (!maybe.has_value) return isolate->heap()->exception(); |
| 2427 PropertyAttributes old_attributes = maybe.value; |
2423 | 2428 |
2424 // Ignore if we can't reconfigure the value. | 2429 // Ignore if we can't reconfigure the value. |
2425 if ((old_attributes & DONT_DELETE) != 0) { | 2430 if ((old_attributes & DONT_DELETE) != 0) { |
2426 if ((old_attributes & READ_ONLY) != 0 || | 2431 if ((old_attributes & READ_ONLY) != 0 || |
2427 it.property_kind() == LookupIterator::ACCESSOR) { | 2432 it.property_kind() == LookupIterator::ACCESSOR) { |
2428 return *value; | 2433 return *value; |
2429 } | 2434 } |
2430 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY); | 2435 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY); |
2431 } | 2436 } |
2432 } | 2437 } |
(...skipping 2307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4740 ASSIGN_RETURN_ON_EXCEPTION( | 4745 ASSIGN_RETURN_ON_EXCEPTION( |
4741 isolate, converted, Execution::ToString(isolate, key), Name); | 4746 isolate, converted, Execution::ToString(isolate, key), Name); |
4742 return Handle<Name>::cast(converted); | 4747 return Handle<Name>::cast(converted); |
4743 } | 4748 } |
4744 } | 4749 } |
4745 | 4750 |
4746 | 4751 |
4747 MaybeHandle<Object> Runtime::HasObjectProperty(Isolate* isolate, | 4752 MaybeHandle<Object> Runtime::HasObjectProperty(Isolate* isolate, |
4748 Handle<JSReceiver> object, | 4753 Handle<JSReceiver> object, |
4749 Handle<Object> key) { | 4754 Handle<Object> key) { |
| 4755 Maybe<bool> maybe; |
4750 // Check if the given key is an array index. | 4756 // Check if the given key is an array index. |
4751 uint32_t index; | 4757 uint32_t index; |
4752 if (key->ToArrayIndex(&index)) { | 4758 if (key->ToArrayIndex(&index)) { |
4753 return isolate->factory()->ToBoolean(JSReceiver::HasElement(object, index)); | 4759 maybe = JSReceiver::HasElement(object, index); |
| 4760 } else { |
| 4761 // Convert the key to a name - possibly by calling back into JavaScript. |
| 4762 Handle<Name> name; |
| 4763 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object); |
| 4764 |
| 4765 maybe = JSReceiver::HasProperty(object, name); |
4754 } | 4766 } |
4755 | 4767 |
4756 // Convert the key to a name - possibly by calling back into JavaScript. | 4768 if (!maybe.has_value) return MaybeHandle<Object>(); |
4757 Handle<Name> name; | 4769 return isolate->factory()->ToBoolean(maybe.value); |
4758 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object); | |
4759 | |
4760 return isolate->factory()->ToBoolean(JSReceiver::HasProperty(object, name)); | |
4761 } | 4770 } |
4762 | 4771 |
4763 | 4772 |
4764 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, | 4773 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, |
4765 Handle<Object> object, | 4774 Handle<Object> object, |
4766 Handle<Object> key) { | 4775 Handle<Object> key) { |
4767 if (object->IsUndefined() || object->IsNull()) { | 4776 if (object->IsUndefined() || object->IsNull()) { |
4768 Handle<Object> args[2] = { key, object }; | 4777 Handle<Object> args[2] = { key, object }; |
4769 return isolate->Throw<Object>( | 4778 return isolate->Throw<Object>( |
4770 isolate->factory()->NewTypeError("non_object_property_load", | 4779 isolate->factory()->NewTypeError("non_object_property_load", |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4932 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); | 4941 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); |
4933 CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2); | 4942 CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2); |
4934 RUNTIME_ASSERT(IsValidAccessor(getter)); | 4943 RUNTIME_ASSERT(IsValidAccessor(getter)); |
4935 CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3); | 4944 CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3); |
4936 RUNTIME_ASSERT(IsValidAccessor(setter)); | 4945 RUNTIME_ASSERT(IsValidAccessor(setter)); |
4937 CONVERT_SMI_ARG_CHECKED(unchecked, 4); | 4946 CONVERT_SMI_ARG_CHECKED(unchecked, 4); |
4938 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 4947 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
4939 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); | 4948 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); |
4940 | 4949 |
4941 bool fast = obj->HasFastProperties(); | 4950 bool fast = obj->HasFastProperties(); |
4942 // DefineAccessor checks access rights. | 4951 RETURN_FAILURE_ON_EXCEPTION( |
4943 JSObject::DefineAccessor(obj, name, getter, setter, attr); | 4952 isolate, JSObject::DefineAccessor(obj, name, getter, setter, attr)); |
4944 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | |
4945 if (fast) JSObject::MigrateSlowToFast(obj, 0); | 4953 if (fast) JSObject::MigrateSlowToFast(obj, 0); |
4946 return isolate->heap()->undefined_value(); | 4954 return isolate->heap()->undefined_value(); |
4947 } | 4955 } |
4948 | 4956 |
4949 | 4957 |
4950 // Implements part of 8.12.9 DefineOwnProperty. | 4958 // Implements part of 8.12.9 DefineOwnProperty. |
4951 // There are 3 cases that lead here: | 4959 // There are 3 cases that lead here: |
4952 // Step 4a - define a new data property. | 4960 // Step 4a - define a new data property. |
4953 // Steps 9b & 12 - replace an existing accessor property with a data property. | 4961 // Steps 9b & 12 - replace an existing accessor property with a data property. |
4954 // Step 12 - update an existing data property with a data or generic | 4962 // Step 12 - update an existing data property with a data or generic |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5272 #ifdef DEBUG | 5280 #ifdef DEBUG |
5273 bool duplicate; | 5281 bool duplicate; |
5274 if (key->IsName()) { | 5282 if (key->IsName()) { |
5275 LookupIterator it(object, Handle<Name>::cast(key), | 5283 LookupIterator it(object, Handle<Name>::cast(key), |
5276 LookupIterator::CHECK_OWN_REAL); | 5284 LookupIterator::CHECK_OWN_REAL); |
5277 JSReceiver::GetPropertyAttributes(&it); | 5285 JSReceiver::GetPropertyAttributes(&it); |
5278 duplicate = it.IsFound(); | 5286 duplicate = it.IsFound(); |
5279 } else { | 5287 } else { |
5280 uint32_t index = 0; | 5288 uint32_t index = 0; |
5281 RUNTIME_ASSERT(key->ToArrayIndex(&index)); | 5289 RUNTIME_ASSERT(key->ToArrayIndex(&index)); |
5282 duplicate = JSReceiver::HasOwnElement(object, index); | 5290 Maybe<bool> maybe = JSReceiver::HasOwnElement(object, index); |
| 5291 if (!maybe.has_value) return isolate->heap()->exception(); |
| 5292 duplicate = maybe.value; |
5283 } | 5293 } |
5284 if (duplicate) { | 5294 if (duplicate) { |
5285 Handle<Object> args[1] = { key }; | 5295 Handle<Object> args[1] = { key }; |
5286 Handle<Object> error = isolate->factory()->NewTypeError( | 5296 Handle<Object> error = isolate->factory()->NewTypeError( |
5287 "duplicate_template_property", HandleVector(args, 1)); | 5297 "duplicate_template_property", HandleVector(args, 1)); |
5288 return isolate->Throw(*error); | 5298 return isolate->Throw(*error); |
5289 } | 5299 } |
5290 #endif | 5300 #endif |
5291 | 5301 |
5292 Handle<Object> result; | 5302 Handle<Object> result; |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5494 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 5504 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
5495 isolate, result, | 5505 isolate, result, |
5496 JSReceiver::DeleteProperty(object, key, delete_mode)); | 5506 JSReceiver::DeleteProperty(object, key, delete_mode)); |
5497 return *result; | 5507 return *result; |
5498 } | 5508 } |
5499 | 5509 |
5500 | 5510 |
5501 static Object* HasOwnPropertyImplementation(Isolate* isolate, | 5511 static Object* HasOwnPropertyImplementation(Isolate* isolate, |
5502 Handle<JSObject> object, | 5512 Handle<JSObject> object, |
5503 Handle<Name> key) { | 5513 Handle<Name> key) { |
5504 if (JSReceiver::HasOwnProperty(object, key)) { | 5514 Maybe<bool> maybe = JSReceiver::HasOwnProperty(object, key); |
5505 return isolate->heap()->true_value(); | 5515 if (!maybe.has_value) return isolate->heap()->exception(); |
5506 } | 5516 if (maybe.value) return isolate->heap()->true_value(); |
5507 // Handle hidden prototypes. If there's a hidden prototype above this thing | 5517 // Handle hidden prototypes. If there's a hidden prototype above this thing |
5508 // then we have to check it for properties, because they are supposed to | 5518 // then we have to check it for properties, because they are supposed to |
5509 // look like they are on this object. | 5519 // look like they are on this object. |
5510 PrototypeIterator iter(isolate, object); | 5520 PrototypeIterator iter(isolate, object); |
5511 if (!iter.IsAtEnd() && | 5521 if (!iter.IsAtEnd() && |
5512 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)) | 5522 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)) |
5513 ->map() | 5523 ->map() |
5514 ->is_hidden_prototype()) { | 5524 ->is_hidden_prototype()) { |
5515 // TODO(verwaest): The recursion is not necessary for keys that are array | 5525 // TODO(verwaest): The recursion is not necessary for keys that are array |
5516 // indicies. Removing this. | 5526 // indicies. Removing this. |
(...skipping 14 matching lines...) Expand all Loading... |
5531 | 5541 |
5532 uint32_t index; | 5542 uint32_t index; |
5533 const bool key_is_array_index = key->AsArrayIndex(&index); | 5543 const bool key_is_array_index = key->AsArrayIndex(&index); |
5534 | 5544 |
5535 // Only JS objects can have properties. | 5545 // Only JS objects can have properties. |
5536 if (object->IsJSObject()) { | 5546 if (object->IsJSObject()) { |
5537 Handle<JSObject> js_obj = Handle<JSObject>::cast(object); | 5547 Handle<JSObject> js_obj = Handle<JSObject>::cast(object); |
5538 // Fast case: either the key is a real named property or it is not | 5548 // Fast case: either the key is a real named property or it is not |
5539 // an array index and there are no interceptors or hidden | 5549 // an array index and there are no interceptors or hidden |
5540 // prototypes. | 5550 // prototypes. |
5541 if (JSObject::HasRealNamedProperty(js_obj, key)) { | 5551 Maybe<bool> maybe = JSObject::HasRealNamedProperty(js_obj, key); |
5542 ASSERT(!isolate->has_scheduled_exception()); | 5552 if (!maybe.has_value) return isolate->heap()->exception(); |
| 5553 ASSERT(!isolate->has_pending_exception()); |
| 5554 if (maybe.value) { |
5543 return isolate->heap()->true_value(); | 5555 return isolate->heap()->true_value(); |
5544 } else { | |
5545 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | |
5546 } | 5556 } |
5547 Map* map = js_obj->map(); | 5557 Map* map = js_obj->map(); |
5548 if (!key_is_array_index && | 5558 if (!key_is_array_index && |
5549 !map->has_named_interceptor() && | 5559 !map->has_named_interceptor() && |
5550 !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) { | 5560 !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) { |
5551 return isolate->heap()->false_value(); | 5561 return isolate->heap()->false_value(); |
5552 } | 5562 } |
5553 // Slow case. | 5563 // Slow case. |
5554 return HasOwnPropertyImplementation(isolate, | 5564 return HasOwnPropertyImplementation(isolate, |
5555 Handle<JSObject>(js_obj), | 5565 Handle<JSObject>(js_obj), |
5556 Handle<Name>(key)); | 5566 Handle<Name>(key)); |
5557 } else if (object->IsString() && key_is_array_index) { | 5567 } else if (object->IsString() && key_is_array_index) { |
5558 // Well, there is one exception: Handle [] on strings. | 5568 // Well, there is one exception: Handle [] on strings. |
5559 Handle<String> string = Handle<String>::cast(object); | 5569 Handle<String> string = Handle<String>::cast(object); |
5560 if (index < static_cast<uint32_t>(string->length())) { | 5570 if (index < static_cast<uint32_t>(string->length())) { |
5561 return isolate->heap()->true_value(); | 5571 return isolate->heap()->true_value(); |
5562 } | 5572 } |
5563 } | 5573 } |
5564 return isolate->heap()->false_value(); | 5574 return isolate->heap()->false_value(); |
5565 } | 5575 } |
5566 | 5576 |
5567 | 5577 |
5568 RUNTIME_FUNCTION(Runtime_HasProperty) { | 5578 RUNTIME_FUNCTION(Runtime_HasProperty) { |
5569 HandleScope scope(isolate); | 5579 HandleScope scope(isolate); |
5570 ASSERT(args.length() == 2); | 5580 ASSERT(args.length() == 2); |
5571 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); | 5581 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); |
5572 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); | 5582 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); |
5573 | 5583 |
5574 bool result = JSReceiver::HasProperty(receiver, key); | 5584 Maybe<bool> maybe = JSReceiver::HasProperty(receiver, key); |
5575 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | 5585 if (!maybe.has_value) return isolate->heap()->exception(); |
5576 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 5586 return isolate->heap()->ToBoolean(maybe.value); |
5577 return isolate->heap()->ToBoolean(result); | |
5578 } | 5587 } |
5579 | 5588 |
5580 | 5589 |
5581 RUNTIME_FUNCTION(Runtime_HasElement) { | 5590 RUNTIME_FUNCTION(Runtime_HasElement) { |
5582 HandleScope scope(isolate); | 5591 HandleScope scope(isolate); |
5583 ASSERT(args.length() == 2); | 5592 ASSERT(args.length() == 2); |
5584 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); | 5593 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0); |
5585 CONVERT_SMI_ARG_CHECKED(index, 1); | 5594 CONVERT_SMI_ARG_CHECKED(index, 1); |
5586 | 5595 |
5587 bool result = JSReceiver::HasElement(receiver, index); | 5596 Maybe<bool> maybe = JSReceiver::HasElement(receiver, index); |
5588 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | 5597 if (!maybe.has_value) return isolate->heap()->exception(); |
5589 return isolate->heap()->ToBoolean(result); | 5598 return isolate->heap()->ToBoolean(maybe.value); |
5590 } | 5599 } |
5591 | 5600 |
5592 | 5601 |
5593 RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) { | 5602 RUNTIME_FUNCTION(Runtime_IsPropertyEnumerable) { |
5594 HandleScope scope(isolate); | 5603 HandleScope scope(isolate); |
5595 ASSERT(args.length() == 2); | 5604 ASSERT(args.length() == 2); |
5596 | 5605 |
5597 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); | 5606 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); |
5598 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); | 5607 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); |
5599 | 5608 |
5600 PropertyAttributes att = JSReceiver::GetOwnPropertyAttributes(object, key); | 5609 Maybe<PropertyAttributes> maybe = |
5601 if (att == ABSENT || (att & DONT_ENUM) != 0) { | 5610 JSReceiver::GetOwnPropertyAttributes(object, key); |
5602 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | 5611 if (!maybe.has_value) return isolate->heap()->exception(); |
5603 return isolate->heap()->false_value(); | 5612 if (maybe.value == ABSENT) maybe.value = DONT_ENUM; |
5604 } | 5613 return isolate->heap()->ToBoolean((maybe.value & DONT_ENUM) == 0); |
5605 ASSERT(!isolate->has_scheduled_exception()); | |
5606 return isolate->heap()->true_value(); | |
5607 } | 5614 } |
5608 | 5615 |
5609 | 5616 |
5610 RUNTIME_FUNCTION(Runtime_GetPropertyNames) { | 5617 RUNTIME_FUNCTION(Runtime_GetPropertyNames) { |
5611 HandleScope scope(isolate); | 5618 HandleScope scope(isolate); |
5612 ASSERT(args.length() == 1); | 5619 ASSERT(args.length() == 1); |
5613 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); | 5620 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); |
5614 Handle<JSArray> result; | 5621 Handle<JSArray> result; |
5615 | 5622 |
5616 isolate->counters()->for_in()->Increment(); | 5623 isolate->counters()->for_in()->Increment(); |
(...skipping 3572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9189 UNREACHABLE(); | 9196 UNREACHABLE(); |
9190 return MakePair(NULL, NULL); | 9197 return MakePair(NULL, NULL); |
9191 } | 9198 } |
9192 } | 9199 } |
9193 | 9200 |
9194 // Otherwise, if the slot was found the holder is a context extension | 9201 // Otherwise, if the slot was found the holder is a context extension |
9195 // object, subject of a with, or a global object. We read the named | 9202 // object, subject of a with, or a global object. We read the named |
9196 // property from it. | 9203 // property from it. |
9197 if (!holder.is_null()) { | 9204 if (!holder.is_null()) { |
9198 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder); | 9205 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder); |
9199 ASSERT(object->IsJSProxy() || JSReceiver::HasProperty(object, name)); | 9206 #ifdef DEBUG |
| 9207 if (!object->IsJSProxy()) { |
| 9208 Maybe<bool> maybe = JSReceiver::HasProperty(object, name); |
| 9209 ASSERT(maybe.has_value); |
| 9210 ASSERT(maybe.value); |
| 9211 } |
| 9212 #endif |
9200 // GetProperty below can cause GC. | 9213 // GetProperty below can cause GC. |
9201 Handle<Object> receiver_handle( | 9214 Handle<Object> receiver_handle( |
9202 object->IsGlobalObject() | 9215 object->IsGlobalObject() |
9203 ? Object::cast(isolate->heap()->undefined_value()) | 9216 ? Object::cast(isolate->heap()->undefined_value()) |
9204 : object->IsJSProxy() ? static_cast<Object*>(*object) | 9217 : object->IsJSProxy() ? static_cast<Object*>(*object) |
9205 : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)), | 9218 : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)), |
9206 isolate); | 9219 isolate); |
9207 | 9220 |
9208 // No need to unhole the value here. This is taken care of by the | 9221 // No need to unhole the value here. This is taken care of by the |
9209 // GetProperty function. | 9222 // GetProperty function. |
(...skipping 966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10176 // Run through the elements FixedArray and use HasElement and GetElement | 10189 // Run through the elements FixedArray and use HasElement and GetElement |
10177 // to check the prototype for missing elements. | 10190 // to check the prototype for missing elements. |
10178 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); | 10191 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); |
10179 int fast_length = static_cast<int>(length); | 10192 int fast_length = static_cast<int>(length); |
10180 ASSERT(fast_length <= elements->length()); | 10193 ASSERT(fast_length <= elements->length()); |
10181 for (int j = 0; j < fast_length; j++) { | 10194 for (int j = 0; j < fast_length; j++) { |
10182 HandleScope loop_scope(isolate); | 10195 HandleScope loop_scope(isolate); |
10183 Handle<Object> element_value(elements->get(j), isolate); | 10196 Handle<Object> element_value(elements->get(j), isolate); |
10184 if (!element_value->IsTheHole()) { | 10197 if (!element_value->IsTheHole()) { |
10185 visitor->visit(j, element_value); | 10198 visitor->visit(j, element_value); |
10186 } else if (JSReceiver::HasElement(receiver, j)) { | 10199 } else { |
10187 // Call GetElement on receiver, not its prototype, or getters won't | 10200 Maybe<bool> maybe = JSReceiver::HasElement(receiver, j); |
10188 // have the correct receiver. | 10201 if (!maybe.has_value) return false; |
10189 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 10202 if (maybe.value) { |
10190 isolate, element_value, | 10203 // Call GetElement on receiver, not its prototype, or getters won't |
10191 Object::GetElement(isolate, receiver, j), | 10204 // have the correct receiver. |
10192 false); | 10205 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
10193 visitor->visit(j, element_value); | 10206 isolate, element_value, |
| 10207 Object::GetElement(isolate, receiver, j), false); |
| 10208 visitor->visit(j, element_value); |
| 10209 } |
10194 } | 10210 } |
10195 } | 10211 } |
10196 break; | 10212 break; |
10197 } | 10213 } |
10198 case FAST_HOLEY_DOUBLE_ELEMENTS: | 10214 case FAST_HOLEY_DOUBLE_ELEMENTS: |
10199 case FAST_DOUBLE_ELEMENTS: { | 10215 case FAST_DOUBLE_ELEMENTS: { |
10200 // Empty array is FixedArray but not FixedDoubleArray. | 10216 // Empty array is FixedArray but not FixedDoubleArray. |
10201 if (length == 0) break; | 10217 if (length == 0) break; |
10202 // Run through the elements FixedArray and use HasElement and GetElement | 10218 // Run through the elements FixedArray and use HasElement and GetElement |
10203 // to check the prototype for missing elements. | 10219 // to check the prototype for missing elements. |
10204 if (receiver->elements()->IsFixedArray()) { | 10220 if (receiver->elements()->IsFixedArray()) { |
10205 ASSERT(receiver->elements()->length() == 0); | 10221 ASSERT(receiver->elements()->length() == 0); |
10206 break; | 10222 break; |
10207 } | 10223 } |
10208 Handle<FixedDoubleArray> elements( | 10224 Handle<FixedDoubleArray> elements( |
10209 FixedDoubleArray::cast(receiver->elements())); | 10225 FixedDoubleArray::cast(receiver->elements())); |
10210 int fast_length = static_cast<int>(length); | 10226 int fast_length = static_cast<int>(length); |
10211 ASSERT(fast_length <= elements->length()); | 10227 ASSERT(fast_length <= elements->length()); |
10212 for (int j = 0; j < fast_length; j++) { | 10228 for (int j = 0; j < fast_length; j++) { |
10213 HandleScope loop_scope(isolate); | 10229 HandleScope loop_scope(isolate); |
10214 if (!elements->is_the_hole(j)) { | 10230 if (!elements->is_the_hole(j)) { |
10215 double double_value = elements->get_scalar(j); | 10231 double double_value = elements->get_scalar(j); |
10216 Handle<Object> element_value = | 10232 Handle<Object> element_value = |
10217 isolate->factory()->NewNumber(double_value); | 10233 isolate->factory()->NewNumber(double_value); |
10218 visitor->visit(j, element_value); | 10234 visitor->visit(j, element_value); |
10219 } else if (JSReceiver::HasElement(receiver, j)) { | 10235 } else { |
10220 // Call GetElement on receiver, not its prototype, or getters won't | 10236 Maybe<bool> maybe = JSReceiver::HasElement(receiver, j); |
10221 // have the correct receiver. | 10237 if (!maybe.has_value) return false; |
10222 Handle<Object> element_value; | 10238 if (maybe.value) { |
10223 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 10239 // Call GetElement on receiver, not its prototype, or getters won't |
10224 isolate, element_value, | 10240 // have the correct receiver. |
10225 Object::GetElement(isolate, receiver, j), | 10241 Handle<Object> element_value; |
10226 false); | 10242 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
10227 visitor->visit(j, element_value); | 10243 isolate, element_value, |
| 10244 Object::GetElement(isolate, receiver, j), false); |
| 10245 visitor->visit(j, element_value); |
| 10246 } |
10228 } | 10247 } |
10229 } | 10248 } |
10230 break; | 10249 break; |
10231 } | 10250 } |
10232 case DICTIONARY_ELEMENTS: { | 10251 case DICTIONARY_ELEMENTS: { |
10233 Handle<SeededNumberDictionary> dict(receiver->element_dictionary()); | 10252 Handle<SeededNumberDictionary> dict(receiver->element_dictionary()); |
10234 List<uint32_t> indices(dict->Capacity() / 2); | 10253 List<uint32_t> indices(dict->Capacity() / 2); |
10235 // Collect all indices in the object and the prototypes less | 10254 // Collect all indices in the object and the prototypes less |
10236 // than length. This might introduce duplicates in the indices list. | 10255 // than length. This might introduce duplicates in the indices list. |
10237 CollectElementIndices(receiver, length, &indices); | 10256 CollectElementIndices(receiver, length, &indices); |
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11532 isolate, scope_info, function_context, variable_name, new_value)) { | 11551 isolate, scope_info, function_context, variable_name, new_value)) { |
11533 return true; | 11552 return true; |
11534 } | 11553 } |
11535 | 11554 |
11536 // Function context extension. These are variables introduced by eval. | 11555 // Function context extension. These are variables introduced by eval. |
11537 if (function_context->closure() == *function) { | 11556 if (function_context->closure() == *function) { |
11538 if (function_context->has_extension() && | 11557 if (function_context->has_extension() && |
11539 !function_context->IsNativeContext()) { | 11558 !function_context->IsNativeContext()) { |
11540 Handle<JSObject> ext(JSObject::cast(function_context->extension())); | 11559 Handle<JSObject> ext(JSObject::cast(function_context->extension())); |
11541 | 11560 |
11542 if (JSReceiver::HasProperty(ext, variable_name)) { | 11561 Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name); |
| 11562 ASSERT(maybe.has_value); |
| 11563 if (maybe.value) { |
11543 // We don't expect this to do anything except replacing | 11564 // We don't expect this to do anything except replacing |
11544 // property value. | 11565 // property value. |
11545 Runtime::SetObjectProperty(isolate, ext, variable_name, new_value, | 11566 Runtime::SetObjectProperty(isolate, ext, variable_name, new_value, |
11546 SLOPPY).Assert(); | 11567 SLOPPY).Assert(); |
11547 return true; | 11568 return true; |
11548 } | 11569 } |
11549 } | 11570 } |
11550 } | 11571 } |
11551 } | 11572 } |
11552 | 11573 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11616 // Context locals to the context extension. | 11637 // Context locals to the context extension. |
11617 if (SetContextLocalValue( | 11638 if (SetContextLocalValue( |
11618 isolate, scope_info, context, variable_name, new_value)) { | 11639 isolate, scope_info, context, variable_name, new_value)) { |
11619 return true; | 11640 return true; |
11620 } | 11641 } |
11621 | 11642 |
11622 // Properties from the function context extension. This will | 11643 // Properties from the function context extension. This will |
11623 // be variables introduced by eval. | 11644 // be variables introduced by eval. |
11624 if (context->has_extension()) { | 11645 if (context->has_extension()) { |
11625 Handle<JSObject> ext(JSObject::cast(context->extension())); | 11646 Handle<JSObject> ext(JSObject::cast(context->extension())); |
11626 if (JSReceiver::HasProperty(ext, variable_name)) { | 11647 Maybe<bool> maybe = JSReceiver::HasProperty(ext, variable_name); |
| 11648 ASSERT(maybe.has_value); |
| 11649 if (maybe.value) { |
11627 // We don't expect this to do anything except replacing property value. | 11650 // We don't expect this to do anything except replacing property value. |
11628 Runtime::DefineObjectProperty( | 11651 Runtime::DefineObjectProperty( |
11629 ext, variable_name, new_value, NONE).Assert(); | 11652 ext, variable_name, new_value, NONE).Assert(); |
11630 return true; | 11653 return true; |
11631 } | 11654 } |
11632 } | 11655 } |
11633 | 11656 |
11634 return false; | 11657 return false; |
11635 } | 11658 } |
11636 | 11659 |
(...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12693 | 12716 |
12694 | 12717 |
12695 // Helper function to find or create the arguments object for | 12718 // Helper function to find or create the arguments object for |
12696 // Runtime_DebugEvaluate. | 12719 // Runtime_DebugEvaluate. |
12697 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeArgumentsObject( | 12720 MUST_USE_RESULT static MaybeHandle<JSObject> MaterializeArgumentsObject( |
12698 Isolate* isolate, | 12721 Isolate* isolate, |
12699 Handle<JSObject> target, | 12722 Handle<JSObject> target, |
12700 Handle<JSFunction> function) { | 12723 Handle<JSFunction> function) { |
12701 // Do not materialize the arguments object for eval or top-level code. | 12724 // Do not materialize the arguments object for eval or top-level code. |
12702 // Skip if "arguments" is already taken. | 12725 // Skip if "arguments" is already taken. |
12703 if (!function->shared()->is_function() || | 12726 if (!function->shared()->is_function()) return target; |
12704 JSReceiver::HasOwnProperty( | 12727 Maybe<bool> maybe = JSReceiver::HasOwnProperty( |
12705 target, isolate->factory()->arguments_string())) { | 12728 target, isolate->factory()->arguments_string()); |
12706 return target; | 12729 if (!maybe.has_value) return MaybeHandle<JSObject>(); |
12707 } | 12730 if (maybe.value) return target; |
12708 | 12731 |
12709 // FunctionGetArguments can't throw an exception. | 12732 // FunctionGetArguments can't throw an exception. |
12710 Handle<JSObject> arguments = Handle<JSObject>::cast( | 12733 Handle<JSObject> arguments = Handle<JSObject>::cast( |
12711 Accessors::FunctionGetArguments(function)); | 12734 Accessors::FunctionGetArguments(function)); |
12712 Handle<String> arguments_str = isolate->factory()->arguments_string(); | 12735 Handle<String> arguments_str = isolate->factory()->arguments_string(); |
12713 RETURN_ON_EXCEPTION( | 12736 RETURN_ON_EXCEPTION( |
12714 isolate, | 12737 isolate, |
12715 Runtime::DefineObjectProperty(target, arguments_str, arguments, NONE), | 12738 Runtime::DefineObjectProperty(target, arguments_str, arguments, NONE), |
12716 JSObject); | 12739 JSObject); |
12717 return target; | 12740 return target; |
(...skipping 2277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14995 } | 15018 } |
14996 return NULL; | 15019 return NULL; |
14997 } | 15020 } |
14998 | 15021 |
14999 | 15022 |
15000 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 15023 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
15001 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 15024 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
15002 } | 15025 } |
15003 | 15026 |
15004 } } // namespace v8::internal | 15027 } } // namespace v8::internal |
OLD | NEW |