Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index d81e1980c6a9fb9c46d00f62b262a7ff8a42cfd3..2f5a7b43337e5ba7b197d88f99b91494656ac376 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -140,6 +140,8 @@ void Object::Lookup(String* name, LookupResult* result) { |
| HeapObject* heap_object = HeapObject::cast(this); |
| if (heap_object->IsJSObject()) { |
| return JSObject::cast(this)->Lookup(name, result); |
| + } else if (heap_object->IsJSProxy()) { |
| + return result->HandlerResult(); |
|
Kevin Millikin (Chromium)
2011/05/30 16:32:29
Indentation looks off.
rossberg
2011/05/31 14:50:24
Done.
|
| } |
| Context* global_context = Isolate::Current()->context()->global_context(); |
| if (heap_object->IsString()) { |
| @@ -148,8 +150,6 @@ void Object::Lookup(String* name, LookupResult* result) { |
| holder = global_context->number_function()->instance_prototype(); |
| } else if (heap_object->IsBoolean()) { |
| holder = global_context->boolean_function()->instance_prototype(); |
| - } else if (heap_object->IsJSProxy()) { |
| - return result->HandlerResult(); |
| } |
| } |
| ASSERT(holder != NULL); // Cannot handle null or undefined. |
| @@ -236,9 +236,9 @@ MaybeObject* Object::GetPropertyWithHandler(Object* receiver_raw, |
| Handle<Object> handler(handler_raw); |
| // Extract trap function. |
| - LookupResult lookup; |
| - Handle<Object> trap(v8::internal::GetProperty(handler, "get", &lookup)); |
| - if (!lookup.IsFound()) { |
| + Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("get"); |
| + Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); |
| + if (trap->IsUndefined()) { |
| // Get the derived `get' property. |
| trap = isolate->derived_get_trap(); |
| } |
| @@ -1281,8 +1281,8 @@ void HeapNumber::HeapNumberPrint(StringStream* accumulator) { |
| } |
| -String* JSObject::class_name() { |
| - if (IsJSFunction()) { |
| +String* JSReceiver::class_name() { |
| + if (IsJSFunction() && IsJSFunctionProxy()) { |
| return GetHeap()->function_class_symbol(); |
| } |
| if (map()->constructor()->IsJSFunction()) { |
| @@ -1294,7 +1294,7 @@ String* JSObject::class_name() { |
| } |
| -String* JSObject::constructor_name() { |
| +String* JSReceiver::constructor_name() { |
| if (map()->constructor()->IsJSFunction()) { |
| JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| String* name = String::cast(constructor->shared()->name()); |
| @@ -1304,6 +1304,7 @@ String* JSObject::constructor_name() { |
| Object* proto = GetPrototype(); |
| if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name(); |
| } |
| + // TODO(rossberg): what about proxies? |
| // If the constructor is not present, return "Object". |
| return GetHeap()->Object_symbol(); |
| } |
| @@ -1758,10 +1759,10 @@ MaybeObject* JSObject::SetPropertyWithInterceptor( |
| } |
| -MaybeObject* JSObject::SetProperty(String* name, |
| - Object* value, |
| - PropertyAttributes attributes, |
| - StrictModeFlag strict_mode) { |
| +MaybeObject* JSReceiver::SetProperty(String* name, |
| + Object* value, |
| + PropertyAttributes attributes, |
| + StrictModeFlag strict_mode) { |
| LookupResult result; |
| LocalLookup(name, &result); |
| return SetProperty(&result, name, value, attributes, strict_mode); |
| @@ -2124,7 +2125,89 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, |
| } |
| -MaybeObject* JSObject::SetProperty(LookupResult* result, |
| +MaybeObject* JSReceiver::SetProperty(LookupResult* result, |
| + String* key, |
| + Object* value, |
| + PropertyAttributes attributes, |
| + StrictModeFlag strict_mode) { |
| + if (result->IsFound() && result->type() == HANDLER) { |
| + return JSProxy::cast(this)->SetPropertyWithHandler( |
| + key, value, attributes, strict_mode); |
| + } else { |
| + return JSObject::cast(this)->SetPropertyForResult( |
| + result, key, value, attributes, strict_mode); |
| + } |
| +} |
| + |
| + |
| +MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( |
| + String* name_raw, |
| + Object* value_raw, |
| + PropertyAttributes attributes, |
| + StrictModeFlag strict_mode) { |
| + Isolate* isolate = GetIsolate(); |
| + HandleScope scope; |
| + Handle<Object> receiver(this); |
| + Handle<Object> name(name_raw); |
| + Handle<Object> value(value_raw); |
| + Handle<Object> handler(this->handler()); |
| + |
| + // Extract trap function. |
| + Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("set"); |
| + Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); |
| + if (trap->IsUndefined()) { |
| + trap = isolate->derived_set_trap(); |
| + } |
| + |
| + // Call trap function. |
| + Object** args[] = { |
| + receiver.location(), name.location(), value.location() |
| + }; |
| + bool has_exception; |
| + Handle<Object> result = |
| + Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception); |
| + if (has_exception) return Failure::Exception(); |
| + |
| + return *result; |
| +} |
| + |
| + |
| +MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( |
| + JSReceiver* receiver_raw, |
| + String* name_raw, |
| + bool* has_exception) { |
| + Isolate* isolate = GetIsolate(); |
| + HandleScope scope; |
| + Handle<JSReceiver> receiver(receiver_raw); |
| + Handle<Object> name(name_raw); |
| + Handle<Object> handler(this->handler()); |
| + |
| + // Extract trap function. |
| + Handle<String> trap_name = |
| + isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor"); |
| + Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); |
| + if (trap->IsUndefined()) { |
| + Handle<Object> args[] = { handler, trap_name }; |
| + Handle<Object> error = isolate->factory()->NewTypeError( |
| + "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args))); |
| + isolate->Throw(*error); |
| + *has_exception = true; |
| + return NONE; |
| + } |
| + |
| + // Call trap function. |
| + Object** args[] = { name.location() }; |
| + Handle<Object> result = |
| + Execution::Call(trap, handler, ARRAY_SIZE(args), args, has_exception); |
| + if (has_exception) return NONE; |
| + |
| + // TODO(rossberg): convert result to PropertyAttributes |
| + USE(result); |
| + return NONE; |
| +} |
| + |
| + |
| +MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, |
| String* name, |
| Object* value, |
| PropertyAttributes attributes, |
| @@ -2399,12 +2482,13 @@ PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( |
| } |
| -PropertyAttributes JSObject::GetPropertyAttributeWithReceiver( |
| - JSObject* receiver, |
| +PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( |
| + JSReceiver* receiver, |
| String* key) { |
| uint32_t index = 0; |
| - if (key->AsArrayIndex(&index)) { |
| - if (HasElementWithReceiver(receiver, index)) return NONE; |
| + if (IsJSObject() && key->AsArrayIndex(&index)) { |
| + if (JSObject::cast(this)->HasElementWithReceiver(receiver, index)) |
| + return NONE; |
| return ABSENT; |
| } |
| // Named property. |
| @@ -2414,18 +2498,17 @@ PropertyAttributes JSObject::GetPropertyAttributeWithReceiver( |
| } |
| -PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver, |
| - LookupResult* result, |
| - String* name, |
| - bool continue_search) { |
| +PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver, |
| + LookupResult* result, |
| + String* name, |
| + bool continue_search) { |
| // Check access rights if needed. |
| if (IsAccessCheckNeeded()) { |
| + JSObject* this_obj = JSObject::cast(this); |
| Heap* heap = GetHeap(); |
| - if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) { |
| - return GetPropertyAttributeWithFailedAccessCheck(receiver, |
| - result, |
| - name, |
| - continue_search); |
| + if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) { |
| + return this_obj->GetPropertyAttributeWithFailedAccessCheck( |
| + receiver, result, name, continue_search); |
| } |
| } |
| if (result->IsProperty()) { |
| @@ -2435,9 +2518,15 @@ PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver, |
| case CONSTANT_FUNCTION: |
| case CALLBACKS: |
| return result->GetAttributes(); |
| + case HANDLER: { |
| + // TODO(rossberg): propagate exceptions properly. |
| + bool has_exception = false; |
| + return JSProxy::cast(this)->GetPropertyAttributeWithHandler( |
| + receiver, name, &has_exception); |
| + } |
| case INTERCEPTOR: |
| - return result->holder()-> |
| - GetPropertyAttributeWithInterceptor(receiver, name, continue_search); |
| + return result->holder()->GetPropertyAttributeWithInterceptor( |
| + JSObject::cast(receiver), name, continue_search); |
| default: |
| UNREACHABLE(); |
| } |
| @@ -2446,11 +2535,11 @@ PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver, |
| } |
| -PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) { |
| +PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) { |
| // Check whether the name is an array index. |
| uint32_t index = 0; |
| - if (name->AsArrayIndex(&index)) { |
| - if (HasLocalElement(index)) return NONE; |
| + if (IsJSObject() && name->AsArrayIndex(&index)) { |
| + if (JSObject::cast(this)->HasLocalElement(index)) return NONE; |
| return ABSENT; |
| } |
| // Named property. |
| @@ -3202,6 +3291,15 @@ AccessorDescriptor* Map::FindAccessor(String* name) { |
| } |
| +void JSReceiver::LocalLookup(String* name, LookupResult* result) { |
| + if (IsJSProxy()) { |
| + result->HandlerResult(); |
| + } else { |
| + JSObject::cast(this)->LocalLookup(name, result); |
| + } |
| +} |
| + |
| + |
| void JSObject::LocalLookup(String* name, LookupResult* result) { |
| ASSERT(name->IsString()); |
| @@ -3237,7 +3335,7 @@ void JSObject::LocalLookup(String* name, LookupResult* result) { |
| } |
| -void JSObject::Lookup(String* name, LookupResult* result) { |
| +void JSReceiver::Lookup(String* name, LookupResult* result) { |
| // Ecma-262 3rd 8.6.2.4 |
| Heap* heap = GetHeap(); |
| for (Object* current = this; |
| @@ -6992,12 +7090,12 @@ MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) { |
| } |
| -MaybeObject* JSObject::SetPrototype(Object* value, |
| - bool skip_hidden_prototypes) { |
| +MaybeObject* JSReceiver::SetPrototype(Object* value, |
| + bool skip_hidden_prototypes) { |
| Heap* heap = GetHeap(); |
| // Silently ignore the change if value is not a JSObject or null. |
| // SpiderMonkey behaves this way. |
| - if (!value->IsJSObject() && !value->IsNull()) return value; |
| + if (!value->IsJSReceiver() && !value->IsNull()) return value; |
| // From 8.6.2 Object Internal Methods |
| // ... |
| @@ -7028,7 +7126,7 @@ MaybeObject* JSObject::SetPrototype(Object* value, |
| } |
| } |
| - JSObject* real_receiver = this; |
| + JSReceiver* real_receiver = this; |
| if (skip_hidden_prototypes) { |
| // Find the first object in the chain whose prototype object is not |
| @@ -7069,7 +7167,7 @@ MaybeObject* JSObject::SetPrototype(Object* value, |
| } |
| -bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { |
| +bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { |
| switch (GetElementsKind()) { |
| case FAST_ELEMENTS: { |
| uint32_t length = IsJSArray() ? |
| @@ -7124,14 +7222,14 @@ bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { |
| } |
| -bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) { |
| +bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) { |
| Isolate* isolate = GetIsolate(); |
| // Make sure that the top context does not change when doing |
| // callbacks or interceptor calls. |
| AssertNoContextChange ncc; |
| HandleScope scope(isolate); |
| Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| - Handle<JSObject> receiver_handle(receiver); |
| + Handle<JSReceiver> receiver_handle(receiver); |
| Handle<JSObject> holder_handle(this); |
| CustomArguments args(isolate, interceptor->data(), receiver, this); |
| v8::AccessorInfo info(args.end()); |
| @@ -7240,7 +7338,7 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { |
| } |
| -bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
| +bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) { |
| // Check access rights if needed. |
| if (IsAccessCheckNeeded()) { |
| Heap* heap = GetHeap(); |
| @@ -8110,7 +8208,7 @@ InterceptorInfo* JSObject::GetIndexedInterceptor() { |
| MaybeObject* JSObject::GetPropertyPostInterceptor( |
| - JSObject* receiver, |
| + JSReceiver* receiver, |
| String* name, |
| PropertyAttributes* attributes) { |
| // Check local property in holder, ignore interceptor. |
| @@ -8128,7 +8226,7 @@ MaybeObject* JSObject::GetPropertyPostInterceptor( |
| MaybeObject* JSObject::GetLocalPropertyPostInterceptor( |
| - JSObject* receiver, |
| + JSReceiver* receiver, |
| String* name, |
| PropertyAttributes* attributes) { |
| // Check local property in holder, ignore interceptor. |
| @@ -8142,13 +8240,13 @@ MaybeObject* JSObject::GetLocalPropertyPostInterceptor( |
| MaybeObject* JSObject::GetPropertyWithInterceptor( |
| - JSObject* receiver, |
| + JSReceiver* receiver, |
| String* name, |
| PropertyAttributes* attributes) { |
| Isolate* isolate = GetIsolate(); |
| InterceptorInfo* interceptor = GetNamedInterceptor(); |
| HandleScope scope(isolate); |
| - Handle<JSObject> receiver_handle(receiver); |
| + Handle<JSReceiver> receiver_handle(receiver); |
| Handle<JSObject> holder_handle(this); |
| Handle<String> name_handle(name); |