Push SetAccessor to Template
authordcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 4 Sep 2013 07:45:36 +0000 (07:45 +0000)
committerdcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 4 Sep 2013 07:45:36 +0000 (07:45 +0000)
R=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/23182003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16515 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

12 files changed:
include/v8.h
src/api.cc
src/factory.cc
src/macros.py
src/objects-debug.cc
src/objects-inl.h
src/objects-printer.cc
src/objects.cc
src/objects.h
test/cctest/test-accessors.cc
test/cctest/test-declarative-accessors.cc
tools/v8heapconst.py

index 1b676de..53e5929 100644 (file)
@@ -2123,10 +2123,10 @@ class V8_EXPORT Object : public Value {
                    PropertyAttribute attribute = None);
 
   // This function is not yet stable and should not be used at this time.
-  bool SetAccessor(Handle<String> name,
-                   Handle<DeclaredAccessorDescriptor> descriptor,
-                   AccessControl settings = DEFAULT,
-                   PropertyAttribute attribute = None);
+  bool SetDeclaredAccessor(Local<String> name,
+                           Local<DeclaredAccessorDescriptor> descriptor,
+                           PropertyAttribute attribute = None,
+                           AccessControl settings = DEFAULT);
 
   /**
    * Returns an array containing the names of the enumerable properties
@@ -2981,6 +2981,51 @@ class V8_EXPORT Template : public Data {
      PropertyAttribute attribute = None,
      AccessControl settings = DEFAULT);
 
+  /**
+   * Whenever the property with the given name is accessed on objects
+   * created from this Template the getter and setter callbacks
+   * are called instead of getting and setting the property directly
+   * on the JavaScript object.
+   *
+   * \param name The name of the property for which an accessor is added.
+   * \param getter The callback to invoke when getting the property.
+   * \param setter The callback to invoke when setting the property.
+   * \param data A piece of data that will be passed to the getter and setter
+   *   callbacks whenever they are invoked.
+   * \param settings Access control settings for the accessor. This is a bit
+   *   field consisting of one of more of
+   *   DEFAULT = 0, ALL_CAN_READ = 1, or ALL_CAN_WRITE = 2.
+   *   The default is to not allow cross-context access.
+   *   ALL_CAN_READ means that all cross-context reads are allowed.
+   *   ALL_CAN_WRITE means that all cross-context writes are allowed.
+   *   The combination ALL_CAN_READ | ALL_CAN_WRITE can be used to allow all
+   *   cross-context access.
+   * \param attribute The attributes of the property for which an accessor
+   *   is added.
+   * \param signature The signature describes valid receivers for the accessor
+   *   and is used to perform implicit instance checks against them. If the
+   *   receiver is incompatible (i.e. is not an instance of the constructor as
+   *   defined by FunctionTemplate::HasInstance()), an implicit TypeError is
+   *   thrown and no callback is invoked.
+   */
+  void SetNativeDataProperty(Local<String> name,
+                             AccessorGetterCallback getter,
+                             AccessorSetterCallback setter = 0,
+                             // TODO(dcarney): gcc can't handle Local below
+                             Handle<Value> data = Handle<Value>(),
+                             PropertyAttribute attribute = None,
+                             Local<AccessorSignature> signature =
+                                 Local<AccessorSignature>(),
+                             AccessControl settings = DEFAULT);
+
+  // This function is not yet stable and should not be used at this time.
+  bool SetDeclaredAccessor(Local<String> name,
+                           Local<DeclaredAccessorDescriptor> descriptor,
+                           PropertyAttribute attribute = None,
+                           Local<AccessorSignature> signature =
+                               Local<AccessorSignature>(),
+                           AccessControl settings = DEFAULT);
+
  private:
   Template();
 
@@ -3447,14 +3492,6 @@ class V8_EXPORT ObjectTemplate : public Template {
                    Handle<AccessorSignature> signature =
                        Handle<AccessorSignature>());
 
-  // This function is not yet stable and should not be used at this time.
-  bool SetAccessor(Handle<String> name,
-                   Handle<DeclaredAccessorDescriptor> descriptor,
-                   AccessControl settings = DEFAULT,
-                   PropertyAttribute attribute = None,
-                   Handle<AccessorSignature> signature =
-                       Handle<AccessorSignature>());
-
   /**
    * Sets a named property handler on the object template.
    *
index e2f3fcd..1a422fb 100644 (file)
@@ -1438,55 +1438,95 @@ Local<ObjectTemplate> ObjectTemplate::New(
 
 // Ensure that the object template has a constructor.  If no
 // constructor is available we create one.
-static void EnsureConstructor(ObjectTemplate* object_template) {
-  if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
-    Local<FunctionTemplate> templ = FunctionTemplate::New();
-    i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
-    constructor->set_instance_template(*Utils::OpenHandle(object_template));
-    Utils::OpenHandle(object_template)->set_constructor(*constructor);
+static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
+    ObjectTemplate* object_template) {
+  i::Object* obj = Utils::OpenHandle(object_template)->constructor();
+  if (!obj ->IsUndefined()) {
+    i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj);
+    return i::Handle<i::FunctionTemplateInfo>(info, info->GetIsolate());
   }
+  Local<FunctionTemplate> templ = FunctionTemplate::New();
+  i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
+  constructor->set_instance_template(*Utils::OpenHandle(object_template));
+  Utils::OpenHandle(object_template)->set_constructor(*constructor);
+  return constructor;
 }
 
 
-static inline void AddPropertyToFunctionTemplate(
-    i::Handle<i::FunctionTemplateInfo> cons,
+static inline void AddPropertyToTemplate(
+    i::Handle<i::TemplateInfo> info,
     i::Handle<i::AccessorInfo> obj) {
-  i::Handle<i::Object> list(cons->property_accessors(), cons->GetIsolate());
+  i::Handle<i::Object> list(info->property_accessors(), info->GetIsolate());
   if (list->IsUndefined()) {
     list = NeanderArray().value();
-    cons->set_property_accessors(*list);
+    info->set_property_accessors(*list);
   }
   NeanderArray array(list);
   array.add(obj);
 }
 
 
-template<typename Setter, typename Getter, typename Data>
-static bool ObjectTemplateSetAccessor(
-    ObjectTemplate* object_template,
-    v8::Handle<String> name,
+static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
+    Template* template_obj) {
+  return Utils::OpenHandle(template_obj);
+}
+
+
+// TODO(dcarney): remove this with ObjectTemplate::SetAccessor
+static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
+    ObjectTemplate* object_template) {
+  EnsureConstructor(object_template);
+  return Utils::OpenHandle(object_template);
+}
+
+
+template<typename Setter, typename Getter, typename Data, typename Template>
+static bool TemplateSetAccessor(
+    Template* template_obj,
+    v8::Local<String> name,
     Getter getter,
     Setter setter,
     Data data,
     AccessControl settings,
     PropertyAttribute attribute,
-    v8::Handle<AccessorSignature> signature) {
-  i::Isolate* isolate = Utils::OpenHandle(object_template)->GetIsolate();
+    v8::Local<AccessorSignature> signature) {
+  i::Isolate* isolate = Utils::OpenHandle(template_obj)->GetIsolate();
   if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetAccessor()")) return false;
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  EnsureConstructor(object_template);
-  i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
-      Utils::OpenHandle(object_template)->constructor());
-  i::Handle<i::FunctionTemplateInfo> cons(constructor);
   i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(
       name, getter, setter, data, settings, attribute, signature);
   if (obj.is_null()) return false;
-  AddPropertyToFunctionTemplate(cons, obj);
+  i::Handle<i::TemplateInfo> info = GetTemplateInfo(template_obj);
+  AddPropertyToTemplate(info, obj);
   return true;
 }
 
 
+bool Template::SetDeclaredAccessor(
+    Local<String> name,
+    Local<DeclaredAccessorDescriptor> descriptor,
+    PropertyAttribute attribute,
+    Local<AccessorSignature> signature,
+    AccessControl settings) {
+  void* null = NULL;
+  return TemplateSetAccessor(
+      this, name, descriptor, null, null, settings, attribute, signature);
+}
+
+
+void Template::SetNativeDataProperty(v8::Local<String> name,
+                                     AccessorGetterCallback getter,
+                                     AccessorSetterCallback setter,
+                                     v8::Handle<Value> data,
+                                     PropertyAttribute attribute,
+                                     v8::Local<AccessorSignature> signature,
+                                     AccessControl settings) {
+  TemplateSetAccessor(
+      this, name, getter, setter, data, settings, attribute, signature);
+}
+
+
 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
                                  AccessorGetterCallback getter,
                                  AccessorSetterCallback setter,
@@ -1494,22 +1534,11 @@ void ObjectTemplate::SetAccessor(v8::Handle<String> name,
                                  AccessControl settings,
                                  PropertyAttribute attribute,
                                  v8::Handle<AccessorSignature> signature) {
-  ObjectTemplateSetAccessor(
+  TemplateSetAccessor(
       this, name, getter, setter, data, settings, attribute, signature);
 }
 
 
-bool ObjectTemplate::SetAccessor(Handle<String> name,
-                                 Handle<DeclaredAccessorDescriptor> descriptor,
-                                 AccessControl settings,
-                                 PropertyAttribute attribute,
-                                 Handle<AccessorSignature> signature) {
-  void* null = NULL;
-  return ObjectTemplateSetAccessor(
-      this, name, descriptor, null, null, settings, attribute, signature);
-}
-
-
 void ObjectTemplate::SetNamedPropertyHandler(
     NamedPropertyGetterCallback getter,
     NamedPropertySetterCallback setter,
@@ -3638,10 +3667,10 @@ bool Object::SetAccessor(Handle<String> name,
 }
 
 
-bool Object::SetAccessor(Handle<String> name,
-                         Handle<DeclaredAccessorDescriptor> descriptor,
-                         AccessControl settings,
-                         PropertyAttribute attributes) {
+bool Object::SetDeclaredAccessor(Local<String> name,
+                                 Local<DeclaredAccessorDescriptor> descriptor,
+                                 PropertyAttribute attributes,
+                                 AccessControl settings) {
   void* null = NULL;
   return ObjectSetAccessor(
       this, name, descriptor, null, null, settings, attributes);
@@ -5314,18 +5343,6 @@ const char* v8::V8::GetVersion() {
 }
 
 
-static i::Handle<i::FunctionTemplateInfo>
-    EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
-  if (templ->constructor()->IsUndefined()) {
-    Local<FunctionTemplate> constructor = FunctionTemplate::New();
-    Utils::OpenHandle(*constructor)->set_instance_template(*templ);
-    templ->set_constructor(*Utils::OpenHandle(*constructor));
-  }
-  return i::Handle<i::FunctionTemplateInfo>(
-    i::FunctionTemplateInfo::cast(templ->constructor()));
-}
-
-
 static i::Handle<i::Context> CreateEnvironment(
     i::Isolate* isolate,
     v8::ExtensionConfiguration* extensions,
@@ -5342,13 +5359,11 @@ static i::Handle<i::Context> CreateEnvironment(
 
     if (!global_template.IsEmpty()) {
       // Make sure that the global_template has a constructor.
-      global_constructor =
-          EnsureConstructor(Utils::OpenHandle(*global_template));
+      global_constructor = EnsureConstructor(*global_template);
 
       // Create a fresh template for the global proxy object.
       proxy_template = ObjectTemplate::New();
-      proxy_constructor =
-          EnsureConstructor(Utils::OpenHandle(*proxy_template));
+      proxy_constructor = EnsureConstructor(*proxy_template);
 
       // Set the global template to be the prototype template of
       // global proxy template.
index 7dde2a7..3d94921 100644 (file)
@@ -1460,15 +1460,29 @@ Handle<JSFunction> Factory::CreateApiFunction(
   result->shared()->set_construct_stub(*construct_stub);
   result->shared()->DontAdaptArguments();
 
-  // Recursively copy parent templates' accessors, 'data' may be modified.
+  // Recursively copy parent instance templates' accessors,
+  // 'data' may be modified.
   int max_number_of_additional_properties = 0;
+  int max_number_of_static_properties = 0;
   FunctionTemplateInfo* info = *obj;
   while (true) {
-    Object* props = info->property_accessors();
-    if (!props->IsUndefined()) {
-      Handle<Object> props_handle(props, isolate());
-      NeanderArray props_array(props_handle);
-      max_number_of_additional_properties += props_array.length();
+    if (!info->instance_template()->IsUndefined()) {
+      Object* props =
+          ObjectTemplateInfo::cast(
+              info->instance_template())->property_accessors();
+      if (!props->IsUndefined()) {
+        Handle<Object> props_handle(props, isolate());
+        NeanderArray props_array(props_handle);
+        max_number_of_additional_properties += props_array.length();
+      }
+    }
+    if (!info->property_accessors()->IsUndefined()) {
+      Object* props = info->property_accessors();
+      if (!props->IsUndefined()) {
+        Handle<Object> props_handle(props, isolate());
+        NeanderArray props_array(props_handle);
+        max_number_of_static_properties += props_array.length();
+      }
     }
     Object* parent = info->parent_template();
     if (parent->IsUndefined()) break;
@@ -1477,17 +1491,44 @@ Handle<JSFunction> Factory::CreateApiFunction(
 
   Map::EnsureDescriptorSlack(map, max_number_of_additional_properties);
 
+  // Use a temporary FixedArray to acculumate static accessors
+  int valid_descriptors = 0;
+  Handle<FixedArray> array;
+  if (max_number_of_static_properties > 0) {
+    array = NewFixedArray(max_number_of_static_properties);
+  }
+
   while (true) {
-    Handle<Object> props = Handle<Object>(obj->property_accessors(),
-                                          isolate());
-    if (!props->IsUndefined()) {
-      Map::AppendCallbackDescriptors(map, props);
+    // Install instance descriptors
+    if (!obj->instance_template()->IsUndefined()) {
+      Handle<ObjectTemplateInfo> instance =
+          Handle<ObjectTemplateInfo>(
+              ObjectTemplateInfo::cast(obj->instance_template()), isolate());
+      Handle<Object> props = Handle<Object>(instance->property_accessors(),
+                                            isolate());
+      if (!props->IsUndefined()) {
+        Map::AppendCallbackDescriptors(map, props);
+      }
+    }
+    // Accumulate static accessors
+    if (!obj->property_accessors()->IsUndefined()) {
+      Handle<Object> props = Handle<Object>(obj->property_accessors(),
+                                            isolate());
+      valid_descriptors =
+          AccessorInfo::AppendUnique(props, array, valid_descriptors);
     }
+    // Climb parent chain
     Handle<Object> parent = Handle<Object>(obj->parent_template(), isolate());
     if (parent->IsUndefined()) break;
     obj = Handle<FunctionTemplateInfo>::cast(parent);
   }
 
+  // Install accumulated static accessors
+  for (int i = 0; i < valid_descriptors; i++) {
+    Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
+    JSObject::SetAccessor(result, accessor);
+  }
+
   ASSERT(result->shared()->IsApiFunction());
   return result;
 }
index f1a2130..38b9a08 100644 (file)
@@ -42,8 +42,8 @@ const SETTER = 1;
 # These definitions must match the index of the properties in objects.h.
 const kApiTagOffset                 = 0;
 const kApiPropertyListOffset        = 1;
-const kApiSerialNumberOffset        = 2;
-const kApiConstructorOffset         = 2;
+const kApiSerialNumberOffset        = 3;
+const kApiConstructorOffset         = 3;
 const kApiPrototypeTemplateOffset   = 5;
 const kApiParentTemplateOffset      = 6;
 const kApiFlagOffset                = 14;
index 8ab793e..3eb7817 100644 (file)
@@ -889,6 +889,7 @@ void CallHandlerInfo::CallHandlerInfoVerify() {
 void TemplateInfo::TemplateInfoVerify() {
   VerifyPointer(tag());
   VerifyPointer(property_list());
+  VerifyPointer(property_accessors());
 }
 
 
@@ -897,7 +898,6 @@ void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
   TemplateInfoVerify();
   VerifyPointer(serial_number());
   VerifyPointer(call_code());
-  VerifyPointer(property_accessors());
   VerifyPointer(prototype_template());
   VerifyPointer(parent_template());
   VerifyPointer(named_property_handler());
index 90bd2ec..8353695 100644 (file)
@@ -4466,11 +4466,10 @@ ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
 
 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
+ACCESSORS(TemplateInfo, property_accessors, Object, kPropertyAccessorsOffset)
 
 ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
 ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
-ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
-          kPropertyAccessorsOffset)
 ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
           kPrototypeTemplateOffset)
 ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
index 9ea060f..0b8fdfd 100644 (file)
@@ -1070,6 +1070,8 @@ void ObjectTemplateInfo::ObjectTemplateInfoPrint(FILE* out) {
   tag()->ShortPrint(out);
   PrintF(out, "\n - property_list: ");
   property_list()->ShortPrint(out);
+  PrintF(out, "\n - property_accessors: ");
+  property_accessors()->ShortPrint(out);
   PrintF(out, "\n - constructor: ");
   constructor()->ShortPrint(out);
   PrintF(out, "\n - internal_field_count: ");
index 7490927..bed3834 100644 (file)
@@ -3001,48 +3001,101 @@ void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
 }
 
 
-void Map::AppendCallbackDescriptors(Handle<Map> map,
-                                    Handle<Object> descriptors) {
-  Isolate* isolate = map->GetIsolate();
-  Handle<DescriptorArray> array(map->instance_descriptors());
-  NeanderArray callbacks(descriptors);
-  int nof_callbacks = callbacks.length();
-
-  ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
+template<class T>
+static int AppendUniqueCallbacks(NeanderArray* callbacks,
+                                 Handle<typename T::Array> array,
+                                 int valid_descriptors) {
+  int nof_callbacks = callbacks->length();
 
+  Isolate* isolate = array->GetIsolate();
   // Ensure the keys are unique names before writing them into the
   // instance descriptor. Since it may cause a GC, it has to be done before we
   // temporarily put the heap in an invalid state while appending descriptors.
   for (int i = 0; i < nof_callbacks; ++i) {
-    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
-    if (!entry->name()->IsUniqueName()) {
-      Handle<String> key =
-          isolate->factory()->InternalizedStringFromString(
-              Handle<String>(String::cast(entry->name())));
-      entry->set_name(*key);
-    }
+    Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
+    if (entry->name()->IsUniqueName()) continue;
+    Handle<String> key =
+        isolate->factory()->InternalizedStringFromString(
+            Handle<String>(String::cast(entry->name())));
+    entry->set_name(*key);
   }
 
-  int nof = map->NumberOfOwnDescriptors();
-
   // Fill in new callback descriptors.  Process the callbacks from
   // back to front so that the last callback with a given name takes
   // precedence over previously added callbacks with that name.
   for (int i = nof_callbacks - 1; i >= 0; i--) {
-    AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
+    AccessorInfo* entry = AccessorInfo::cast(callbacks->get(i));
     Name* key = Name::cast(entry->name());
     // Check if a descriptor with this name already exists before writing.
-    if (array->Search(key, nof) == DescriptorArray::kNotFound) {
-      CallbacksDescriptor desc(key, entry, entry->property_attributes());
-      array->Append(&desc);
-      nof += 1;
+    if (!T::Contains(key, entry, valid_descriptors, array)) {
+      T::Insert(key, entry, valid_descriptors, array);
+      valid_descriptors++;
+    }
+  }
+
+  return valid_descriptors;
+}
+
+struct DescriptorArrayAppender {
+  typedef DescriptorArray Array;
+  static bool Contains(Name* key,
+                       AccessorInfo* entry,
+                       int valid_descriptors,
+                       Handle<DescriptorArray> array) {
+    return array->Search(key, valid_descriptors) != DescriptorArray::kNotFound;
+  }
+  static void Insert(Name* key,
+                     AccessorInfo* entry,
+                     int valid_descriptors,
+                     Handle<DescriptorArray> array) {
+    CallbacksDescriptor desc(key, entry, entry->property_attributes());
+    array->Append(&desc);
+  }
+};
+
+
+struct FixedArrayAppender {
+  typedef FixedArray Array;
+  static bool Contains(Name* key,
+                       AccessorInfo* entry,
+                       int valid_descriptors,
+                       Handle<FixedArray> array) {
+    for (int i = 0; i < valid_descriptors; i++) {
+      if (key == AccessorInfo::cast(array->get(i))->name()) return true;
     }
+    return false;
   }
+  static void Insert(Name* key,
+                     AccessorInfo* entry,
+                     int valid_descriptors,
+                     Handle<FixedArray> array) {
+    array->set(valid_descriptors, entry);
+  }
+};
 
+
+void Map::AppendCallbackDescriptors(Handle<Map> map,
+                                    Handle<Object> descriptors) {
+  int nof = map->NumberOfOwnDescriptors();
+  Handle<DescriptorArray> array(map->instance_descriptors());
+  NeanderArray callbacks(descriptors);
+  ASSERT(array->NumberOfSlackDescriptors() >= callbacks.length());
+  nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
   map->SetNumberOfOwnDescriptors(nof);
 }
 
 
+int AccessorInfo::AppendUnique(Handle<Object> descriptors,
+                               Handle<FixedArray> array,
+                               int valid_descriptors) {
+  NeanderArray callbacks(descriptors);
+  ASSERT(array->length() >= callbacks.length() + valid_descriptors);
+  return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
+                                                   array,
+                                                   valid_descriptors);
+}
+
+
 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
   ASSERT(!map.is_null());
   for (int i = 0; i < maps->length(); ++i) {
index 4e0f53e..d7339d6 100644 (file)
@@ -9489,6 +9489,11 @@ class AccessorInfo: public Struct {
   // Dispatched behavior.
   DECLARE_VERIFIER(AccessorInfo)
 
+  // Append all descriptors to the array that are not already there.
+  // Return number added.
+  static int AppendUnique(Handle<Object> descriptors,
+                          Handle<FixedArray> array,
+                          int valid_descriptors);
 
   static const int kNameOffset = HeapObject::kHeaderSize;
   static const int kFlagOffset = kNameOffset + kPointerSize;
@@ -9795,12 +9800,15 @@ class TemplateInfo: public Struct {
  public:
   DECL_ACCESSORS(tag, Object)
   DECL_ACCESSORS(property_list, Object)
+  DECL_ACCESSORS(property_accessors, Object)
 
   DECLARE_VERIFIER(TemplateInfo)
 
-  static const int kTagOffset          = HeapObject::kHeaderSize;
+  static const int kTagOffset = HeapObject::kHeaderSize;
   static const int kPropertyListOffset = kTagOffset + kPointerSize;
-  static const int kHeaderSize         = kPropertyListOffset + kPointerSize;
+  static const int kPropertyAccessorsOffset =
+      kPropertyListOffset + kPointerSize;
+  static const int kHeaderSize = kPropertyAccessorsOffset + kPointerSize;
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
@@ -9811,7 +9819,6 @@ class FunctionTemplateInfo: public TemplateInfo {
  public:
   DECL_ACCESSORS(serial_number, Object)
   DECL_ACCESSORS(call_code, Object)
-  DECL_ACCESSORS(property_accessors, Object)
   DECL_ACCESSORS(prototype_template, Object)
   DECL_ACCESSORS(parent_template, Object)
   DECL_ACCESSORS(named_property_handler, Object)
@@ -9843,9 +9850,8 @@ class FunctionTemplateInfo: public TemplateInfo {
 
   static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
   static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
-  static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
   static const int kPrototypeTemplateOffset =
-      kPropertyAccessorsOffset + kPointerSize;
+      kCallCodeOffset + kPointerSize;
   static const int kParentTemplateOffset =
       kPrototypeTemplateOffset + kPointerSize;
   static const int kNamedPropertyHandlerOffset =
index 2f7e7f4..b68b0b0 100644 (file)
@@ -49,6 +49,12 @@ static void handle_property(Local<String> name,
   info.GetReturnValue().Set(v8_num(900));
 }
 
+static void handle_property_2(Local<String> name,
+                              const v8::PropertyCallbackInfo<v8::Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  info.GetReturnValue().Set(v8_num(902));
+}
+
 
 static void handle_property(const v8::FunctionCallbackInfo<v8::Value>& info) {
   ApiTestFuzzer::Fuzz();
@@ -67,16 +73,27 @@ THREADED_TEST(PropertyHandler) {
   getter_templ->SetLength(0);
   fun_templ->
       InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ);
+  fun_templ->InstanceTemplate()->
+      SetNativeDataProperty(v8_str("instance_foo"), handle_property);
+  fun_templ->SetNativeDataProperty(v8_str("object_foo"), handle_property_2);
   Local<Function> fun = fun_templ->GetFunction();
   env->Global()->Set(v8_str("Fun"), fun);
-  Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
+  Local<Script> getter;
+  Local<Script> setter;
+  // check function instance accessors
+  getter = v8_compile("var obj = new Fun(); obj.instance_foo;");
   CHECK_EQ(900, getter->Run()->Int32Value());
-  Local<Script> setter = v8_compile("obj.foo = 901;");
+  setter = v8_compile("obj.instance_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());
+  // check function static accessors
+  getter = v8_compile("Fun.object_foo;");
+  CHECK_EQ(902, getter->Run()->Int32Value());
+  setter = v8_compile("Fun.object_foo = 903;");
+  CHECK_EQ(903, setter->Run()->Int32Value());
 }
 
 
index e3c7fa5..fa5a045 100644 (file)
@@ -101,7 +101,7 @@ static v8::Local<v8::ObjectTemplate> CreateConstructor(
   // Setup object template.
   if (descriptor_name != NULL && !descriptor.IsEmpty()) {
     bool added_accessor =
-        obj_template->SetAccessor(v8_str(descriptor_name), descriptor);
+        obj_template->SetDeclaredAccessor(v8_str(descriptor_name), descriptor);
     CHECK(added_accessor);
   }
   obj_template->SetInternalFieldCount((internal_field+1)*2 + 7);
@@ -124,9 +124,9 @@ static void VerifyRead(v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
       context->Global()->Get(v8_str("accessible")));
   obj->SetAlignedPointerInInternalField(internal_field, internal_object);
   bool added_accessor;
-  added_accessor = obj->SetAccessor(v8_str("y"), descriptor);
+  added_accessor = obj->SetDeclaredAccessor(v8_str("y"), descriptor);
   CHECK(added_accessor);
-  added_accessor = obj->SetAccessor(v8_str("13"), descriptor);
+  added_accessor = obj->SetDeclaredAccessor(v8_str("13"), descriptor);
   CHECK(added_accessor);
   // Test access from template getter.
   v8::Local<v8::Value> value;
index 18bd3fb..a4335a0 100644 (file)
@@ -250,6 +250,6 @@ KNOWN_OBJECTS = {
   ("OLD_DATA_SPACE", 0x082c9): "EmptyExternalPixelArray",
   ("OLD_DATA_SPACE", 0x082d5): "InfinityValue",
   ("OLD_DATA_SPACE", 0x082e1): "MinusZeroValue",
-  ("CODE_SPACE", 0x114e1): "JsConstructEntryCode",
-  ("CODE_SPACE", 0x18ca1): "JsEntryCode",
+  ("CODE_SPACE", 0x11ce1): "JsConstructEntryCode",
+  ("CODE_SPACE", 0x193e1): "JsEntryCode",
 }