| 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();
|
| }
|
| 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);
|
|
|
|
|