| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 277d320588d04ccbdb92a715e6bdc147333beb85..45ad471c2de09d3871b6da2209b948d795d16185 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -361,10 +361,24 @@ Handle<FixedArray> JSObject::EnsureWritableFastElements(
|
| }
|
|
|
|
|
| -MaybeHandle<Object> JSObject::GetPropertyWithCallback(Handle<JSObject> object,
|
| - Handle<Object> receiver,
|
| - Handle<Object> structure,
|
| - Handle<Name> name) {
|
| +MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
|
| + Handle<Object> receiver,
|
| + Handle<Name> name) {
|
| + Isolate* isolate = proxy->GetIsolate();
|
| +
|
| + // TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
| + if (name->IsSymbol()) return isolate->factory()->undefined_value();
|
| +
|
| + Handle<Object> args[] = { receiver, name };
|
| + return CallTrap(
|
| + proxy, "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
|
| +}
|
| +
|
| +
|
| +MaybeHandle<Object> Object::GetPropertyWithCallback(Handle<Object> receiver,
|
| + Handle<Name> name,
|
| + Handle<JSObject> holder,
|
| + Handle<Object> structure) {
|
| Isolate* isolate = name->GetIsolate();
|
| ASSERT(!structure->IsForeign());
|
| // api style callbacks.
|
| @@ -395,8 +409,8 @@ MaybeHandle<Object> JSObject::GetPropertyWithCallback(Handle<JSObject> object,
|
| if (call_fun == NULL) return isolate->factory()->undefined_value();
|
|
|
| Handle<String> key = Handle<String>::cast(name);
|
| - LOG(isolate, ApiNamedPropertyAccess("load", *object, *name));
|
| - PropertyCallbackArguments args(isolate, data->data(), *receiver, *object);
|
| + LOG(isolate, ApiNamedPropertyAccess("load", *holder, *name));
|
| + PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder);
|
| v8::Handle<v8::Value> result =
|
| args.Call(call_fun, v8::Utils::ToLocal(key));
|
| RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| @@ -415,29 +429,79 @@ MaybeHandle<Object> JSObject::GetPropertyWithCallback(Handle<JSObject> object,
|
| if (getter->IsSpecFunction()) {
|
| // TODO(rossberg): nicer would be to cast to some JSCallable here...
|
| return Object::GetPropertyWithDefinedGetter(
|
| - object, receiver, Handle<JSReceiver>::cast(getter));
|
| + receiver, Handle<JSReceiver>::cast(getter));
|
| }
|
| // Getter is not a function.
|
| return isolate->factory()->undefined_value();
|
| }
|
|
|
|
|
| -MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
|
| - Handle<Object> receiver,
|
| - Handle<Name> name) {
|
| - Isolate* isolate = proxy->GetIsolate();
|
| +MaybeHandle<Object> Object::SetPropertyWithCallback(Handle<Object> receiver,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + Handle<JSObject> holder,
|
| + Handle<Object> structure,
|
| + StrictMode strict_mode) {
|
| + Isolate* isolate = name->GetIsolate();
|
|
|
| - // TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
| - if (name->IsSymbol()) return isolate->factory()->undefined_value();
|
| + // We should never get here to initialize a const with the hole
|
| + // value since a const declaration would conflict with the setter.
|
| + ASSERT(!value->IsTheHole());
|
| + ASSERT(!structure->IsForeign());
|
| + if (structure->IsExecutableAccessorInfo()) {
|
| + // api style callbacks
|
| + ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure);
|
| + if (!data->IsCompatibleReceiver(*receiver)) {
|
| + Handle<Object> args[2] = { name, receiver };
|
| + Handle<Object> error =
|
| + isolate->factory()->NewTypeError("incompatible_method_receiver",
|
| + HandleVector(args,
|
| + ARRAY_SIZE(args)));
|
| + return isolate->Throw<Object>(error);
|
| + }
|
| + // TODO(rossberg): Support symbols in the API.
|
| + if (name->IsSymbol()) return value;
|
| + Object* call_obj = data->setter();
|
| + v8::AccessorSetterCallback call_fun =
|
| + v8::ToCData<v8::AccessorSetterCallback>(call_obj);
|
| + if (call_fun == NULL) return value;
|
| + Handle<String> key = Handle<String>::cast(name);
|
| + LOG(isolate, ApiNamedPropertyAccess("store", *holder, *name));
|
| + PropertyCallbackArguments args(isolate, data->data(), *receiver, *holder);
|
| + args.Call(call_fun,
|
| + v8::Utils::ToLocal(key),
|
| + v8::Utils::ToLocal(value));
|
| + RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| + return value;
|
| + }
|
|
|
| - Handle<Object> args[] = { receiver, name };
|
| - return CallTrap(
|
| - proxy, "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
|
| + if (structure->IsAccessorPair()) {
|
| + Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
|
| + if (setter->IsSpecFunction()) {
|
| + // TODO(rossberg): nicer would be to cast to some JSCallable here...
|
| + return SetPropertyWithDefinedSetter(
|
| + receiver, Handle<JSReceiver>::cast(setter), value);
|
| + } else {
|
| + if (strict_mode == SLOPPY) return value;
|
| + Handle<Object> args[2] = { name, holder };
|
| + Handle<Object> error =
|
| + isolate->factory()->NewTypeError("no_setter_in_callback",
|
| + HandleVector(args, 2));
|
| + return isolate->Throw<Object>(error);
|
| + }
|
| + }
|
| +
|
| + // TODO(dcarney): Handle correctly.
|
| + if (structure->IsDeclaredAccessorInfo()) {
|
| + return value;
|
| + }
|
| +
|
| + UNREACHABLE();
|
| + return MaybeHandle<Object>();
|
| }
|
|
|
|
|
| MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
|
| - Handle<Object> object,
|
| Handle<Object> receiver,
|
| Handle<JSReceiver> getter) {
|
| Isolate* isolate = getter->GetIsolate();
|
| @@ -453,6 +517,29 @@ MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
|
| }
|
|
|
|
|
| +MaybeHandle<Object> Object::SetPropertyWithDefinedSetter(
|
| + Handle<Object> receiver,
|
| + Handle<JSReceiver> setter,
|
| + Handle<Object> value) {
|
| + Isolate* isolate = setter->GetIsolate();
|
| +
|
| + Debug* debug = isolate->debug();
|
| + // Handle stepping into a setter if step into is active.
|
| + // TODO(rossberg): should this apply to getters that are function proxies?
|
| + if (debug->StepInActive() && setter->IsJSFunction()) {
|
| + debug->HandleStepIn(
|
| + Handle<JSFunction>::cast(setter), Handle<Object>::null(), 0, false);
|
| + }
|
| +
|
| + Handle<Object> argv[] = { value };
|
| + RETURN_ON_EXCEPTION(
|
| + isolate,
|
| + Execution::Call(isolate, setter, receiver, ARRAY_SIZE(argv), argv),
|
| + Object);
|
| + return value;
|
| +}
|
| +
|
| +
|
| // Only deal with CALLBACKS and INTERCEPTOR
|
| MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
|
| Handle<JSObject> object,
|
| @@ -477,7 +564,7 @@ MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
|
| break;
|
| }
|
| Handle<JSObject> holder(result->holder(), isolate);
|
| - return GetPropertyWithCallback(holder, receiver, callback_obj, name);
|
| + return GetPropertyWithCallback(receiver, name, holder, callback_obj);
|
| }
|
| case NORMAL:
|
| case FIELD:
|
| @@ -791,11 +878,9 @@ MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
|
| case CONSTANT:
|
| return handle(result->GetConstant(), isolate);
|
| case CALLBACKS:
|
| - return JSObject::GetPropertyWithCallback(
|
| - handle(result->holder(), isolate),
|
| - receiver,
|
| - handle(result->GetCallbackObject(), isolate),
|
| - name);
|
| + return GetPropertyWithCallback(
|
| + receiver, name, handle(result->holder(), isolate),
|
| + handle(result->GetCallbackObject(), isolate));
|
| case HANDLER:
|
| return JSProxy::GetPropertyWithHandler(
|
| handle(result->proxy(), isolate), receiver, name);
|
| @@ -3005,94 +3090,6 @@ MaybeHandle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
|
| }
|
|
|
|
|
| -MaybeHandle<Object> JSObject::SetPropertyWithCallback(Handle<JSObject> object,
|
| - Handle<Object> structure,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - Handle<JSObject> holder,
|
| - StrictMode strict_mode) {
|
| - Isolate* isolate = object->GetIsolate();
|
| -
|
| - // We should never get here to initialize a const with the hole
|
| - // value since a const declaration would conflict with the setter.
|
| - ASSERT(!value->IsTheHole());
|
| - ASSERT(!structure->IsForeign());
|
| - if (structure->IsExecutableAccessorInfo()) {
|
| - // api style callbacks
|
| - ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(*structure);
|
| - if (!data->IsCompatibleReceiver(*object)) {
|
| - Handle<Object> args[2] = { name, object };
|
| - Handle<Object> error =
|
| - isolate->factory()->NewTypeError("incompatible_method_receiver",
|
| - HandleVector(args,
|
| - ARRAY_SIZE(args)));
|
| - return isolate->Throw<Object>(error);
|
| - }
|
| - // TODO(rossberg): Support symbols in the API.
|
| - if (name->IsSymbol()) return value;
|
| - Object* call_obj = data->setter();
|
| - v8::AccessorSetterCallback call_fun =
|
| - v8::ToCData<v8::AccessorSetterCallback>(call_obj);
|
| - if (call_fun == NULL) return value;
|
| - Handle<String> key = Handle<String>::cast(name);
|
| - LOG(isolate, ApiNamedPropertyAccess("store", *object, *name));
|
| - PropertyCallbackArguments args(isolate, data->data(), *object, *holder);
|
| - args.Call(call_fun,
|
| - v8::Utils::ToLocal(key),
|
| - v8::Utils::ToLocal(value));
|
| - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| - return value;
|
| - }
|
| -
|
| - if (structure->IsAccessorPair()) {
|
| - Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
|
| - if (setter->IsSpecFunction()) {
|
| - // TODO(rossberg): nicer would be to cast to some JSCallable here...
|
| - return SetPropertyWithDefinedSetter(
|
| - object, Handle<JSReceiver>::cast(setter), value);
|
| - } else {
|
| - if (strict_mode == SLOPPY) return value;
|
| - Handle<Object> args[2] = { name, holder };
|
| - Handle<Object> error =
|
| - isolate->factory()->NewTypeError("no_setter_in_callback",
|
| - HandleVector(args, 2));
|
| - return isolate->Throw<Object>(error);
|
| - }
|
| - }
|
| -
|
| - // TODO(dcarney): Handle correctly.
|
| - if (structure->IsDeclaredAccessorInfo()) {
|
| - return value;
|
| - }
|
| -
|
| - UNREACHABLE();
|
| - return MaybeHandle<Object>();
|
| -}
|
| -
|
| -
|
| -MaybeHandle<Object> JSReceiver::SetPropertyWithDefinedSetter(
|
| - Handle<JSReceiver> object,
|
| - Handle<JSReceiver> setter,
|
| - Handle<Object> value) {
|
| - Isolate* isolate = object->GetIsolate();
|
| -
|
| - Debug* debug = isolate->debug();
|
| - // Handle stepping into a setter if step into is active.
|
| - // TODO(rossberg): should this apply to getters that are function proxies?
|
| - if (debug->StepInActive() && setter->IsJSFunction()) {
|
| - debug->HandleStepIn(
|
| - Handle<JSFunction>::cast(setter), Handle<Object>::null(), 0, false);
|
| - }
|
| -
|
| - Handle<Object> argv[] = { value };
|
| - RETURN_ON_EXCEPTION(
|
| - isolate,
|
| - Execution::Call(isolate, setter, object, ARRAY_SIZE(argv), argv),
|
| - Object);
|
| - return value;
|
| -}
|
| -
|
| -
|
| MaybeHandle<Object> JSObject::SetElementWithCallbackSetterInPrototypes(
|
| Handle<JSObject> object,
|
| uint32_t index,
|
| @@ -3166,8 +3163,9 @@ MaybeHandle<Object> JSObject::SetPropertyViaPrototypes(
|
| *done = true;
|
| if (!result.IsReadOnly()) {
|
| Handle<Object> callback_object(result.GetCallbackObject(), isolate);
|
| - return SetPropertyWithCallback(object, callback_object, name, value,
|
| - handle(result.holder()), strict_mode);
|
| + return SetPropertyWithCallback(object, name, value,
|
| + handle(result.holder()),
|
| + callback_object, strict_mode);
|
| }
|
| break;
|
| }
|
| @@ -3625,22 +3623,16 @@ MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck(
|
| if (obj->IsAccessorInfo()) {
|
| Handle<AccessorInfo> info(AccessorInfo::cast(obj));
|
| if (info->all_can_write()) {
|
| - return SetPropertyWithCallback(object,
|
| - info,
|
| - name,
|
| - value,
|
| + return SetPropertyWithCallback(object, name, value,
|
| handle(result->holder()),
|
| - strict_mode);
|
| + info, strict_mode);
|
| }
|
| } else if (obj->IsAccessorPair()) {
|
| Handle<AccessorPair> pair(AccessorPair::cast(obj));
|
| if (pair->all_can_read()) {
|
| - return SetPropertyWithCallback(object,
|
| - pair,
|
| - name,
|
| - value,
|
| + return SetPropertyWithCallback(object, name, value,
|
| handle(result->holder()),
|
| - strict_mode);
|
| + pair, strict_mode);
|
| }
|
| }
|
| break;
|
| @@ -4300,8 +4292,9 @@ MaybeHandle<Object> JSObject::SetPropertyForResult(
|
| break;
|
| case CALLBACKS: {
|
| Handle<Object> callback_object(lookup->GetCallbackObject(), isolate);
|
| - return SetPropertyWithCallback(object, callback_object, name, value,
|
| - handle(lookup->holder()), strict_mode);
|
| + return SetPropertyWithCallback(object, name, value,
|
| + handle(lookup->holder()),
|
| + callback_object, strict_mode);
|
| }
|
| case INTERCEPTOR:
|
| maybe_result = SetPropertyWithInterceptor(
|
| @@ -12588,7 +12581,7 @@ MaybeHandle<Object> JSObject::GetElementWithCallback(
|
| if (getter->IsSpecFunction()) {
|
| // TODO(rossberg): nicer would be to cast to some JSCallable here...
|
| return GetPropertyWithDefinedGetter(
|
| - object, receiver, Handle<JSReceiver>::cast(getter));
|
| + receiver, Handle<JSReceiver>::cast(getter));
|
| }
|
| // Getter is not a function.
|
| return isolate->factory()->undefined_value();
|
|
|