Revision: 16321
Author:   [email protected]
Date:     Mon Aug 26 11:59:14 2013 UTC
Log:      js accessor creation on Template

[email protected]
BUG=

Review URL: https://codereview.chromium.org/22903012
http://code.google.com/p/v8/source/detail?r=16321

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/apinatives.js
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/objects-debug.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects-printer.cc
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h
 /branches/bleeding_edge/test/cctest/test-accessors.cc
 /branches/bleeding_edge/test/cctest/test-api.cc
 /branches/bleeding_edge/test/mjsunit/fuzz-natives-part2.js
 /branches/bleeding_edge/tools/v8heapconst.py

=======================================
--- /branches/bleeding_edge/include/v8.h        Mon Aug 26 09:41:22 2013 UTC
+++ /branches/bleeding_edge/include/v8.h        Mon Aug 26 11:59:14 2013 UTC
@@ -2982,6 +2982,14 @@
   void Set(Handle<String> name, Handle<Data> value,
            PropertyAttribute attributes = None);
   V8_INLINE(void Set(const char* name, Handle<Data> value));
+
+  void SetAccessorProperty(
+     Local<String> name,
+     Local<FunctionTemplate> getter = Local<FunctionTemplate>(),
+     Local<FunctionTemplate> setter = Local<FunctionTemplate>(),
+     PropertyAttribute attribute = None,
+     AccessControl settings = DEFAULT);
+
  private:
   Template();

=======================================
--- /branches/bleeding_edge/src/api.cc  Mon Aug 26 09:41:22 2013 UTC
+++ /branches/bleeding_edge/src/api.cc  Mon Aug 26 11:59:14 2013 UTC
@@ -935,21 +935,62 @@
 }


-void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
+static void TemplateSet(i::Isolate* isolate,
+                        v8::Template* templ,
+                        int length,
+                        v8::Handle<v8::Data>* data) {
+ i::Handle<i::Object> list(Utils::OpenHandle(templ)->property_list(), isolate);
+  if (list->IsUndefined()) {
+    list = NeanderArray().value();
+    Utils::OpenHandle(templ)->set_property_list(*list);
+  }
+  NeanderArray array(list);
+  array.add(Utils::OpenHandle(*v8::Integer::New(length)));
+  for (int i = 0; i < length; i++) {
+    i::Handle<i::Object> value = data[i].IsEmpty() ?
+        i::Handle<i::Object>(isolate->factory()->undefined_value()) :
+        Utils::OpenHandle(*data[i]);
+    array.add(value);
+  }
+}
+
+
+void Template::Set(v8::Handle<String> name,
+                   v8::Handle<Data> value,
                    v8::PropertyAttribute attribute) {
   i::Isolate* isolate = i::Isolate::Current();
   if (IsDeadCheck(isolate, "v8::Template::Set()")) return;
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
- i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list(), isolate);
-  if (list->IsUndefined()) {
-    list = NeanderArray().value();
-    Utils::OpenHandle(this)->set_property_list(*list);
-  }
-  NeanderArray array(list);
-  array.add(Utils::OpenHandle(*name));
-  array.add(Utils::OpenHandle(*value));
-  array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
+  const int kSize = 3;
+  v8::Handle<v8::Data> data[kSize] = {
+      name,
+      value,
+      v8::Integer::New(attribute)};
+  TemplateSet(isolate, this, kSize, data);
+}
+
+
+void Template::SetAccessorProperty(
+    v8::Local<v8::String> name,
+    v8::Local<FunctionTemplate> getter,
+    v8::Local<FunctionTemplate> setter,
+    v8::PropertyAttribute attribute,
+    v8::AccessControl access_control) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Template::SetAccessor()")) return;
+  ENTER_V8(isolate);
+  ASSERT(!name.IsEmpty());
+  ASSERT(!getter.IsEmpty() || !setter.IsEmpty());
+  i::HandleScope scope(isolate);
+  const int kSize = 5;
+  v8::Handle<v8::Data> data[kSize] = {
+      name,
+      getter,
+      setter,
+      v8::Integer::New(attribute),
+      v8::Integer::New(access_control)};
+  TemplateSet(isolate, this, kSize, data);
 }


=======================================
--- /branches/bleeding_edge/src/apinatives.js   Mon Jul 15 11:41:41 2013 UTC
+++ /branches/bleeding_edge/src/apinatives.js   Mon Aug 26 11:59:14 2013 UTC
@@ -104,19 +104,32 @@

 function ConfigureTemplateInstance(obj, data) {
   var properties = %GetTemplateField(data, kApiPropertyListOffset);
-  if (properties) {
-    // Disable access checks while instantiating the object.
-    var requires_access_checks = %DisableAccessChecks(obj);
-    try {
-      for (var i = 0; i < properties[0]; i += 3) {
+  if (!properties) return;
+  // Disable access checks while instantiating the object.
+  var requires_access_checks = %DisableAccessChecks(obj);
+  try {
+    for (var i = 1; i < properties[0];) {
+      var length = properties[i];
+      if (length == 3) {
         var name = properties[i + 1];
         var prop_data = properties[i + 2];
         var attributes = properties[i + 3];
         var value = Instantiate(prop_data, name);
         %SetProperty(obj, name, value, attributes);
+      } else if (length == 5) {
+        var name = properties[i + 1];
+        var getter = properties[i + 2];
+        var setter = properties[i + 3];
+        var attribute = properties[i + 4];
+        var access_control = properties[i + 5];
+        %SetAccessorProperty(
+            obj, name, getter, setter, attribute, access_control);
+      } else {
+        throw "Bad properties array";
       }
-    } finally {
-      if (requires_access_checks) %EnableAccessChecks(obj);
+      i += length + 1;
     }
+  } finally {
+    if (requires_access_checks) %EnableAccessChecks(obj);
   }
 }
=======================================
--- /branches/bleeding_edge/src/heap.cc Thu Aug 22 16:14:37 2013 UTC
+++ /branches/bleeding_edge/src/heap.cc Mon Aug 26 11:59:14 2013 UTC
@@ -2429,6 +2429,7 @@
   }
   accessors->set_getter(the_hole_value(), SKIP_WRITE_BARRIER);
   accessors->set_setter(the_hole_value(), SKIP_WRITE_BARRIER);
+  accessors->set_access_flags(Smi::FromInt(0), SKIP_WRITE_BARRIER);
   return accessors;
 }

=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Mon Aug 5 13:45:16 2013 UTC +++ /branches/bleeding_edge/src/objects-debug.cc Mon Aug 26 11:59:14 2013 UTC
@@ -856,6 +856,7 @@
   CHECK(IsAccessorPair());
   VerifyPointer(getter());
   VerifyPointer(setter());
+  VerifySmiField(kAccessFlagsOffset);
 }


=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Fri Aug 23 13:21:01 2013 UTC
+++ /branches/bleeding_edge/src/objects-inl.h   Mon Aug 26 11:59:14 2013 UTC
@@ -4454,6 +4454,7 @@

 ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
 ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
+ACCESSORS_TO_SMI(AccessorPair, access_flags, kAccessFlagsOffset)

 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
@@ -5848,6 +5849,36 @@
   if (!function_template->IsFunctionTemplateInfo()) return true;
return receiver->IsInstanceOf(FunctionTemplateInfo::cast(function_template));
 }
+
+
+void AccessorPair::set_access_flags(v8::AccessControl access_control) {
+  int current = access_flags()->value();
+  current = BooleanBit::set(current,
+                            kProhibitsOverwritingBit,
+                            access_control & PROHIBITS_OVERWRITING);
+  current = BooleanBit::set(current,
+                            kAllCanReadBit,
+                            access_control & ALL_CAN_READ);
+  current = BooleanBit::set(current,
+                            kAllCanWriteBit,
+                            access_control & ALL_CAN_WRITE);
+  set_access_flags(Smi::FromInt(current));
+}
+
+
+bool AccessorPair::all_can_read() {
+  return BooleanBit::get(access_flags(), kAllCanReadBit);
+}
+
+
+bool AccessorPair::all_can_write() {
+  return BooleanBit::get(access_flags(), kAllCanWriteBit);
+}
+
+
+bool AccessorPair::prohibits_overwriting() {
+  return BooleanBit::get(access_flags(), kProhibitsOverwritingBit);
+}


 template<typename Shape, typename Key>
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Fri Aug 9 08:22:46 2013 UTC +++ /branches/bleeding_edge/src/objects-printer.cc Mon Aug 26 11:59:14 2013 UTC
@@ -985,6 +985,8 @@
   getter()->ShortPrint(out);
   PrintF(out, "\n - setter: ");
   setter()->ShortPrint(out);
+  PrintF(out, "\n - flag: ");
+  access_flags()->ShortPrint(out);
 }


=======================================
--- /branches/bleeding_edge/src/objects.cc      Fri Aug 23 13:30:02 2013 UTC
+++ /branches/bleeding_edge/src/objects.cc      Mon Aug 26 11:59:14 2013 UTC
@@ -513,6 +513,12 @@
             return result->holder()->GetPropertyWithCallback(
                 receiver, result->GetCallbackObject(), name);
           }
+        } else if (obj->IsAccessorPair()) {
+          AccessorPair* pair = AccessorPair::cast(obj);
+          if (pair->all_can_read()) {
+            return result->holder()->GetPropertyWithCallback(
+                receiver, result->GetCallbackObject(), name);
+          }
         }
         break;
       }
@@ -573,6 +579,11 @@
           if (info->all_can_read()) {
             return result->GetAttributes();
           }
+        } else if (obj->IsAccessorPair()) {
+          AccessorPair* pair = AccessorPair::cast(obj);
+          if (pair->all_can_read()) {
+            return result->GetAttributes();
+          }
         }
         break;
       }
@@ -3395,6 +3406,15 @@
                                              result->holder(),
                                              strict_mode);
             }
+          } else if (obj->IsAccessorPair()) {
+            AccessorPair* pair = AccessorPair::cast(obj);
+            if (pair->all_can_read()) {
+              return SetPropertyWithCallback(result->GetCallbackObject(),
+                                             name,
+                                             value,
+                                             result->holder(),
+                                             strict_mode);
+            }
           }
           break;
         }
@@ -5892,7 +5912,8 @@
                                      uint32_t index,
                                      Handle<Object> getter,
                                      Handle<Object> setter,
-                                     PropertyAttributes attributes) {
+                                     PropertyAttributes attributes,
+                                     v8::AccessControl access_control) {
   switch (object->GetElementsKind()) {
     case FAST_SMI_ELEMENTS:
     case FAST_ELEMENTS:
@@ -5950,6 +5971,7 @@
   Isolate* isolate = object->GetIsolate();
   Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair();
   accessors->SetComponents(*getter, *setter);
+  accessors->set_access_flags(access_control);

   CALL_HEAP_FUNCTION_VOID(
       isolate, object->SetElementCallback(index, *accessors, attributes));
@@ -5981,11 +6003,13 @@
                                       Handle<Name> name,
                                       Handle<Object> getter,
                                       Handle<Object> setter,
-                                      PropertyAttributes attributes) {
+                                      PropertyAttributes attributes,
+                                      v8::AccessControl access_control) {
// We could assert that the property is configurable here, but we would need
   // to do a lookup, which seems to be a bit of overkill.
   bool only_attribute_changes = getter->IsNull() && setter->IsNull();
   if (object->HasFastProperties() && !only_attribute_changes &&
+      access_control == v8::DEFAULT &&
       (object->map()->NumberOfOwnDescriptors() <
        DescriptorArray::kMaxNumberOfDescriptors)) {
     bool getterOk = getter->IsNull() ||
@@ -5997,6 +6021,7 @@

   Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name);
   accessors->SetComponents(*getter, *setter);
+  accessors->set_access_flags(access_control);

   CALL_HEAP_FUNCTION_VOID(
       object->GetIsolate(),
@@ -6018,12 +6043,13 @@
   LookupCallbackProperty(name, &callback_result);
   if (callback_result.IsFound()) {
     Object* obj = callback_result.GetCallbackObject();
-    if (obj->IsAccessorInfo() &&
-        AccessorInfo::cast(obj)->prohibits_overwriting()) {
-      return false;
+    if (obj->IsAccessorInfo()) {
+      return !AccessorInfo::cast(obj)->prohibits_overwriting();
+    }
+    if (obj->IsAccessorPair()) {
+      return !AccessorPair::cast(obj)->prohibits_overwriting();
     }
   }
-
   return true;
 }

@@ -6101,7 +6127,8 @@
                               Handle<Name> name,
                               Handle<Object> getter,
                               Handle<Object> setter,
-                              PropertyAttributes attributes) {
+                              PropertyAttributes attributes,
+                              v8::AccessControl access_control) {
   Isolate* isolate = object->GetIsolate();
   // Check access rights if needed.
   if (object->IsAccessCheckNeeded() &&
@@ -6114,8 +6141,12 @@
     Handle<Object> proto(object->GetPrototype(), isolate);
     if (proto->IsNull()) return;
     ASSERT(proto->IsJSGlobalObject());
-    DefineAccessor(
-        Handle<JSObject>::cast(proto), name, getter, setter, attributes);
+    DefineAccessor(Handle<JSObject>::cast(proto),
+                   name,
+                   getter,
+                   setter,
+                   attributes,
+                   access_control);
     return;
   }

@@ -6151,9 +6182,11 @@
   }

   if (is_element) {
-    DefineElementAccessor(object, index, getter, setter, attributes);
+    DefineElementAccessor(
+        object, index, getter, setter, attributes, access_control);
   } else {
-    DefinePropertyAccessor(object, name, getter, setter, attributes);
+    DefinePropertyAccessor(
+        object, name, getter, setter, attributes, access_control);
   }

   if (is_observed) {
=======================================
--- /branches/bleeding_edge/src/objects.h       Fri Aug 23 13:30:02 2013 UTC
+++ /branches/bleeding_edge/src/objects.h       Mon Aug 26 11:59:14 2013 UTC
@@ -2252,7 +2252,8 @@
                              Handle<Name> name,
                              Handle<Object> getter,
                              Handle<Object> setter,
-                             PropertyAttributes attributes);
+                             PropertyAttributes attributes,
+ v8::AccessControl access_control = v8::DEFAULT);

   MaybeObject* LookupAccessor(Name* name, AccessorComponent component);

@@ -2836,14 +2837,16 @@
                                     uint32_t index,
                                     Handle<Object> getter,
                                     Handle<Object> setter,
-                                    PropertyAttributes attributes);
+                                    PropertyAttributes attributes,
+                                    v8::AccessControl access_control);
static Handle<AccessorPair> CreateAccessorPairFor(Handle<JSObject> object,
                                                     Handle<Name> name);
   static void DefinePropertyAccessor(Handle<JSObject> object,
                                      Handle<Name> name,
                                      Handle<Object> getter,
                                      Handle<Object> setter,
-                                     PropertyAttributes attributes);
+                                     PropertyAttributes attributes,
+                                     v8::AccessControl access_control);

   // Try to define a single accessor paying attention to map transitions.
// Returns false if this was not possible and we have to use the slow case.
@@ -9689,10 +9692,18 @@
 //   * undefined: considered an accessor by the spec, too, strangely enough
 //   * the hole: an accessor which has not been set
 //   * a pointer to a map: a transition used to ensure map sharing
+// access_flags provides the ability to override access checks on access check
+// failure.
 class AccessorPair: public Struct {
  public:
   DECL_ACCESSORS(getter, Object)
   DECL_ACCESSORS(setter, Object)
+  DECL_ACCESSORS(access_flags, Smi)
+
+  inline void set_access_flags(v8::AccessControl access_control);
+  inline bool all_can_read();
+  inline bool all_can_write();
+  inline bool prohibits_overwriting();

   static inline AccessorPair* cast(Object* obj);

@@ -9729,9 +9740,14 @@

   static const int kGetterOffset = HeapObject::kHeaderSize;
   static const int kSetterOffset = kGetterOffset + kPointerSize;
-  static const int kSize = kSetterOffset + kPointerSize;
+  static const int kAccessFlagsOffset = kSetterOffset + kPointerSize;
+  static const int kSize = kAccessFlagsOffset + kPointerSize;

  private:
+  static const int kAllCanReadBit = 0;
+  static const int kAllCanWriteBit = 1;
+  static const int kProhibitsOverwritingBit = 2;
+
// Strangely enough, in addition to functions and harmony proxies, the spec
   // requires us to consider undefined as a kind of accessor, too:
   //    var obj = {};
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Fri Aug 23 11:43:30 2013 UTC
+++ /branches/bleeding_edge/src/runtime.cc      Mon Aug 26 11:59:14 2013 UTC
@@ -1662,6 +1662,14 @@
         (access_type == v8::ACCESS_GET && info->all_can_read()) ||
         (access_type == v8::ACCESS_SET && info->all_can_write());
   }
+  if (callback->IsAccessorPair()) {
+    AccessorPair* info = AccessorPair::cast(callback);
+    return
+        (access_type == v8::ACCESS_HAS &&
+           (info->all_can_read() || info->all_can_write())) ||
+        (access_type == v8::ACCESS_GET && info->all_can_read()) ||
+        (access_type == v8::ACCESS_SET && info->all_can_write());
+  }
   return false;
 }

@@ -1941,6 +1949,35 @@
   }
   return isolate->heap()->undefined_value();
 }
+
+
+// Transform getter or setter into something DefineAccessor can handle.
+static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
+ Handle<Object> component) {
+  if (component->IsUndefined()) return isolate->factory()->null_value();
+  Handle<FunctionTemplateInfo> info =
+      Handle<FunctionTemplateInfo>::cast(component);
+  return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction());
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 6);
+  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
+  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
+  CONVERT_SMI_ARG_CHECKED(attribute, 4);
+  CONVERT_SMI_ARG_CHECKED(access_control, 5);
+  JSObject::DefineAccessor(object,
+                           name,
+                           InstantiateAccessorComponent(isolate, getter),
+                           InstantiateAccessorComponent(isolate, setter),
+                           static_cast<PropertyAttributes>(attribute),
+                           static_cast<v8::AccessControl>(access_control));
+  return isolate->heap()->undefined_value();
+}


 static Failure* ThrowRedeclarationError(Isolate* isolate,
=======================================
--- /branches/bleeding_edge/src/runtime.h       Thu Aug 22 16:14:37 2013 UTC
+++ /branches/bleeding_edge/src/runtime.h       Mon Aug 26 11:59:14 2013 UTC
@@ -258,6 +258,7 @@
   F(GetTemplateField, 2, 1) \
   F(DisableAccessChecks, 1, 1) \
   F(EnableAccessChecks, 1, 1) \
+  F(SetAccessorProperty, 6, 1) \
   \
   /* Dates */ \
   F(DateCurrentTime, 0, 1) \
=======================================
--- /branches/bleeding_edge/test/cctest/test-accessors.cc Fri Jul 5 09:52:11 2013 UTC +++ /branches/bleeding_edge/test/cctest/test-accessors.cc Mon Aug 26 11:59:14 2013 UTC
@@ -49,6 +49,13 @@
   ApiTestFuzzer::Fuzz();
   info.GetReturnValue().Set(v8_num(900));
 }
+
+
+static void handle_property(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(0, info.Length());
+  info.GetReturnValue().Set(v8_num(907));
+}


 THREADED_TEST(PropertyHandler) {
@@ -56,12 +63,21 @@
   v8::HandleScope scope(env->GetIsolate());
   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
+  Local<v8::FunctionTemplate> getter_templ =
+      v8::FunctionTemplate::New(handle_property);
+  getter_templ->SetLength(0);
+  fun_templ->
+      InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ);
   Local<Function> fun = fun_templ->GetFunction();
   env->Global()->Set(v8_str("Fun"), fun);
   Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
   CHECK_EQ(900, getter->Run()->Int32Value());
   Local<Script> setter = v8_compile("obj.foo = 901;");
   CHECK_EQ(901, setter->Run()->Int32Value());
+  getter = v8_compile("obj.bar;");
+  CHECK_EQ(907, getter->Run()->Int32Value());
+  setter = v8_compile("obj.bar = 908;");
+  CHECK_EQ(908, setter->Run()->Int32Value());
 }


@@ -109,30 +125,52 @@
 }


-static int x_register = 0;
+static int x_register[2] = {0, 0};
 static v8::Handle<v8::Object> x_receiver;
 static v8::Handle<v8::Object> x_holder;

+template<class Info>
+static void XGetter(const Info& info, int offset) {
+  ApiTestFuzzer::Fuzz();
+  v8::Isolate* isolate = v8::Isolate::GetCurrent();
+  CHECK_EQ(isolate, info.GetIsolate());
+  CHECK_EQ(x_receiver, info.This());
+  info.GetReturnValue().Set(v8_num(x_register[offset]));
+}
+

 static void XGetter(Local<String> name,
                     const v8::PropertyCallbackInfo<v8::Value>& info) {
-  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(x_holder, info.Holder());
+  XGetter(info, 0);
+}
+
+
+static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  XGetter(info, 1);
+}
+
+
+template<class Info>
+static void XSetter(Local<Value> value, const Info& info, int offset) {
   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   CHECK_EQ(isolate, info.GetIsolate());
-  CHECK_EQ(x_receiver, info.This());
-  CHECK_EQ(x_holder, info.Holder());
-  info.GetReturnValue().Set(v8_num(x_register));
+  CHECK_EQ(x_holder, info.This());
+  x_register[offset] = value->Int32Value();
 }


 static void XSetter(Local<String> name,
                     Local<Value> value,
                     const v8::PropertyCallbackInfo<void>& info) {
-  v8::Isolate* isolate = v8::Isolate::GetCurrent();
-  CHECK_EQ(isolate, info.GetIsolate());
-  CHECK_EQ(x_holder, info.This());
   CHECK_EQ(x_holder, info.Holder());
-  x_register = value->Int32Value();
+  XSetter(value, info, 0);
+}
+
+
+static void XSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  CHECK_EQ(1, info.Length());
+  XSetter(info[0], info, 1);
 }


@@ -140,7 +178,10 @@
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-  obj->SetAccessor(v8_str("x"), XGetter, XSetter);
+  obj->SetAccessor(v8_str("x0"), XGetter, XSetter);
+  obj->SetAccessorProperty(v8_str("x1"),
+                           v8::FunctionTemplate::New(XGetter),
+                           v8::FunctionTemplate::New(XSetter));
   x_holder = obj->NewInstance();
   context->Global()->Set(v8_str("holder"), x_holder);
   x_receiver = v8::Object::New();
@@ -149,14 +190,16 @@
     "obj.__proto__ = holder;"
     "var result = [];"
     "for (var i = 0; i < 10; i++) {"
-    "  holder.x = i;"
-    "  result.push(obj.x);"
+    "  holder.x0 = i;"
+    "  holder.x1 = i;"
+    "  result.push(obj.x0);"
+    "  result.push(obj.x1);"
     "}"
     "result"));
-  CHECK_EQ(10, array->Length());
-  for (int i = 0; i < 10; i++) {
+  CHECK_EQ(20, array->Length());
+  for (int i = 0; i < 20; i++) {
     v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
-    CHECK_EQ(v8::Integer::New(i), entry);
+    CHECK_EQ(v8::Integer::New(i/2), entry);
   }
 }

=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Fri Aug 23 11:10:03 2013 UTC +++ /branches/bleeding_edge/test/cctest/test-api.cc Mon Aug 26 11:59:14 2013 UTC
@@ -8257,11 +8257,19 @@
 }


-static int g_echo_value = -1;
+static int g_echo_value_1 = -1;
+static int g_echo_value_2 = -1;
+
+
 static void EchoGetter(
     Local<String> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(v8_num(g_echo_value));
+  info.GetReturnValue().Set(v8_num(g_echo_value_1));
+}
+
+
+static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(v8_num(g_echo_value_2));
 }


@@ -8269,7 +8277,14 @@
                        Local<Value> value,
                        const v8::PropertyCallbackInfo<void>&) {
   if (value->IsNumber())
-    g_echo_value = value->Int32Value();
+    g_echo_value_1 = value->Int32Value();
+}
+
+
+static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  v8::Handle<v8::Value> value = info[0];
+  if (value->IsNumber())
+    g_echo_value_2 = value->Int32Value();
 }


@@ -8285,6 +8300,12 @@
                               const v8::PropertyCallbackInfo<void>&) {
   CHECK(false);  // This function should nto be called.
 }
+
+
+static void UnreachableFunction(
+    const v8::FunctionCallbackInfo<v8::Value>& info) {
+  CHECK(false);  // This function should not be called..
+}


 TEST(AccessControl) {
@@ -8302,12 +8323,27 @@
       v8::Handle<Value>(),
       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));

+
+  global_template->SetAccessorProperty(
+      v8_str("accessible_js_prop"),
+      v8::FunctionTemplate::New(EchoGetter),
+      v8::FunctionTemplate::New(EchoSetter),
+      v8::None,
+      v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
+
   // Add an accessor that is not accessible by cross-domain JS code.
   global_template->SetAccessor(v8_str("blocked_prop"),
                                UnreachableGetter, UnreachableSetter,
                                v8::Handle<Value>(),
                                v8::DEFAULT);

+  global_template->SetAccessorProperty(
+      v8_str("blocked_js_prop"),
+      v8::FunctionTemplate::New(UnreachableFunction),
+      v8::FunctionTemplate::New(UnreachableFunction),
+      v8::None,
+      v8::DEFAULT);
+
   // Create an environment
v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   context0->Enter();
@@ -8499,27 +8535,48 @@
   // Access accessible property
   value = CompileRun("other.accessible_prop = 3");
   CHECK(value->IsNumber());
+  CHECK_EQ(3, value->Int32Value());
+  CHECK_EQ(3, g_echo_value_1);
+
+  // Access accessible js property
+  value = CompileRun("other.accessible_js_prop = 3");
+  CHECK(value->IsNumber());
   CHECK_EQ(3, value->Int32Value());
-  CHECK_EQ(3, g_echo_value);
+  CHECK_EQ(3, g_echo_value_2);

   value = CompileRun("other.accessible_prop");
   CHECK(value->IsNumber());
   CHECK_EQ(3, value->Int32Value());

+  value = CompileRun("other.accessible_js_prop");
+  CHECK(value->IsNumber());
+  CHECK_EQ(3, value->Int32Value());
+
   value = CompileRun(
       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   CHECK(value->IsNumber());
   CHECK_EQ(3, value->Int32Value());

+  value = CompileRun(
+      "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
+  CHECK(value->IsNumber());
+  CHECK_EQ(3, value->Int32Value());
+
value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   CHECK(value->IsTrue());

+ value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
+  CHECK(value->IsTrue());
+
   // Enumeration doesn't enumerate accessors from inaccessible objects in
// the prototype chain even if the accessors are in themselves accessible.
   value =
       CompileRun("(function(){var obj = {'__proto__':other};"
                  "for (var p in obj)"
-                 "   if (p == 'accessible_prop' || p == 'blocked_prop') {"
+                 "   if (p == 'accessible_prop' ||"
+                 "       p == 'accessible_js_prop' ||"
+                 "       p == 'blocked_js_prop' ||"
+                 "       p == 'blocked_js_prop') {"
                  "     return false;"
                  "   }"
                  "return true;})()");
@@ -8591,7 +8648,7 @@
   // Make sure that we can set the accessible accessors value using normal
   // assignment.
   CompileRun("other.accessible_prop = 42");
-  CHECK_EQ(42, g_echo_value);
+  CHECK_EQ(42, g_echo_value_1);

   v8::Handle<Value> value;
   // We follow Safari in ignoring assignments to host object accessors.
=======================================
--- /branches/bleeding_edge/test/mjsunit/fuzz-natives-part2.js Thu Aug 22 16:14:37 2013 UTC +++ /branches/bleeding_edge/test/mjsunit/fuzz-natives-part2.js Mon Aug 26 11:59:14 2013 UTC
@@ -165,6 +165,7 @@
   "DeclareGlobals": true,
   "ArrayConstructor": true,
   "InternalArrayConstructor": true,
+  "SetAccessorProperty": true,

   "PromoteScheduledException": true,
   "DeleteHandleScopeExtensions": true,
=======================================
--- /branches/bleeding_edge/tools/v8heapconst.py Fri Aug 9 08:22:46 2013 UTC +++ /branches/bleeding_edge/tools/v8heapconst.py Mon Aug 26 11:59:14 2013 UTC
@@ -227,14 +227,14 @@
   ("OLD_POINTER_SPACE", 0x0a9d9): "NonMonomorphicCache",
   ("OLD_POINTER_SPACE", 0x0afed): "PolymorphicCodeCache",
   ("OLD_POINTER_SPACE", 0x0aff5): "NativesSourceCache",
-  ("OLD_POINTER_SPACE", 0x0b035): "EmptyScript",
-  ("OLD_POINTER_SPACE", 0x0b06d): "IntrinsicFunctionNames",
-  ("OLD_POINTER_SPACE", 0x0e089): "ObservationState",
-  ("OLD_POINTER_SPACE", 0x0e095): "FrozenSymbol",
-  ("OLD_POINTER_SPACE", 0x0e0a1): "ElementsTransitionSymbol",
-  ("OLD_POINTER_SPACE", 0x0e0ad): "EmptySlowElementDictionary",
-  ("OLD_POINTER_SPACE", 0x0e249): "ObservedSymbol",
-  ("OLD_POINTER_SPACE", 0x274e9): "StringTable",
+  ("OLD_POINTER_SPACE", 0x0b03d): "EmptyScript",
+  ("OLD_POINTER_SPACE", 0x0b075): "IntrinsicFunctionNames",
+  ("OLD_POINTER_SPACE", 0x0e091): "ObservationState",
+  ("OLD_POINTER_SPACE", 0x0e09d): "FrozenSymbol",
+  ("OLD_POINTER_SPACE", 0x0e0a9): "ElementsTransitionSymbol",
+  ("OLD_POINTER_SPACE", 0x0e0b5): "EmptySlowElementDictionary",
+  ("OLD_POINTER_SPACE", 0x0e251): "ObservedSymbol",
+  ("OLD_POINTER_SPACE", 0x29861): "StringTable",
   ("OLD_DATA_SPACE", 0x08099): "EmptyDescriptorArray",
   ("OLD_DATA_SPACE", 0x080a1): "EmptyFixedArray",
   ("OLD_DATA_SPACE", 0x080a9): "NanValue",
@@ -250,6 +250,6 @@
   ("OLD_DATA_SPACE", 0x082c9): "EmptyExternalPixelArray",
   ("OLD_DATA_SPACE", 0x082d5): "InfinityValue",
   ("OLD_DATA_SPACE", 0x082e1): "MinusZeroValue",
-  ("CODE_SPACE", 0x10d01): "JsConstructEntryCode",
-  ("CODE_SPACE", 0x183c1): "JsEntryCode",
+  ("CODE_SPACE", 0x114e1): "JsConstructEntryCode",
+  ("CODE_SPACE", 0x18ca1): "JsEntryCode",
 }

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to