Browse Source

fix: add property query interceptors

VerteDinde 10 months ago
parent
commit
ac0a67beea
2 changed files with 575 additions and 0 deletions
  1. 1 0
      patches/node/.patches
  2. 574 0
      patches/node/fix_add_property_query_interceptors.patch

+ 1 - 0
patches/node/.patches

@@ -52,3 +52,4 @@ src_remove_dependency_on_wrapper-descriptor-based_cppheap.patch
 test_update_v8-stats_test_for_v8_12_6.patch
 chore_remove_calls_to_v8_functioncallbackinfo_holder.patch
 src_do_not_use_soon-to-be-deprecated_v8_api.patch
+fix_add_property_query_interceptors.patch

+ 574 - 0
patches/node/fix_add_property_query_interceptors.patch

@@ -0,0 +1,574 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: VerteDinde <[email protected]>
+Date: Mon, 24 Jun 2024 21:48:40 -0700
+Subject: fix: add property query interceptors
+
+This commit cherry-picks an upstream interceptor API change
+from node-v8/canary to accomodate V8's upstream changes to old
+interceptor APIs.
+
+Node PR: https://github.com/nodejs/node-v8/commit/d1f18b0bf16efbc1e54ba04a54735ce4683cb936
+CL: https://chromium-review.googlesource.com/c/v8/v8/+/5630388
+
+This patch can be removed when the node change is incorporated into main.
+
+diff --git a/src/node_contextify.cc b/src/node_contextify.cc
+index f6969e635f692b17b4efca1dfbee086a0199db6e..6ace71b04e9da761c77838dde2abd8088abcb6c4 100644
+--- a/src/node_contextify.cc
++++ b/src/node_contextify.cc
+@@ -49,6 +49,7 @@ using v8::FunctionTemplate;
+ using v8::HandleScope;
+ using v8::IndexedPropertyHandlerConfiguration;
+ using v8::Int32;
++using v8::Intercepted;
+ using v8::Isolate;
+ using v8::Just;
+ using v8::Local;
+@@ -457,14 +458,15 @@ bool ContextifyContext::IsStillInitializing(const ContextifyContext* ctx) {
+ }
+ 
+ // static
+-void ContextifyContext::PropertyGetterCallback(
+-    Local<Name> property,
+-    const PropertyCallbackInfo<Value>& args) {
++Intercepted ContextifyContext::PropertyGetterCallback(
++    Local<Name> property, const PropertyCallbackInfo<Value>& args) {
+   Environment* env = Environment::GetCurrent(args);
+   ContextifyContext* ctx = ContextifyContext::Get(args);
+ 
+   // Still initializing
+-  if (IsStillInitializing(ctx)) return;
++  if (IsStillInitializing(ctx)) {
++    return Intercepted::kNo;
++  }
+ 
+   Local<Context> context = ctx->context();
+   Local<Object> sandbox = ctx->sandbox();
+@@ -488,18 +490,22 @@ void ContextifyContext::PropertyGetterCallback(
+       rv = ctx->global_proxy();
+ 
+     args.GetReturnValue().Set(rv);
++    return Intercepted::kYes;
+   }
++  return Intercepted::kNo;
+ }
+ 
+ // static
+-void ContextifyContext::PropertySetterCallback(
++Intercepted ContextifyContext::PropertySetterCallback(
+     Local<Name> property,
+     Local<Value> value,
+-    const PropertyCallbackInfo<Value>& args) {
++    const PropertyCallbackInfo<void>& args) {
+   ContextifyContext* ctx = ContextifyContext::Get(args);
+ 
+   // Still initializing
+-  if (IsStillInitializing(ctx)) return;
++  if (IsStillInitializing(ctx)) {
++    return Intercepted::kNo;
++  }
+ 
+   Local<Context> context = ctx->context();
+   PropertyAttribute attributes = PropertyAttribute::None;
+@@ -517,8 +523,9 @@ void ContextifyContext::PropertySetterCallback(
+       (static_cast<int>(attributes) &
+       static_cast<int>(PropertyAttribute::ReadOnly));
+ 
+-  if (read_only)
+-    return;
++  if (read_only) {
++    return Intercepted::kNo;
++  }
+ 
+   // true for x = 5
+   // false for this.x = 5
+@@ -537,11 +544,16 @@ void ContextifyContext::PropertySetterCallback(
+ 
+   bool is_declared = is_declared_on_global_proxy || is_declared_on_sandbox;
+   if (!is_declared && args.ShouldThrowOnError() && is_contextual_store &&
+-      !is_function)
+-    return;
++      !is_function) {
++    return Intercepted::kNo;
++  }
+ 
+-  if (!is_declared && property->IsSymbol()) return;
+-  if (ctx->sandbox()->Set(context, property, value).IsNothing()) return;
++  if (!is_declared && property->IsSymbol()) {
++    return Intercepted::kNo;
++  }
++  if (ctx->sandbox()->Set(context, property, value).IsNothing()) {
++    return Intercepted::kNo;
++  }
+ 
+   Local<Value> desc;
+   if (is_declared_on_sandbox &&
+@@ -555,19 +567,23 @@ void ContextifyContext::PropertySetterCallback(
+     // We have to specify the return value for any contextual or get/set
+     // property
+     if (desc_obj->HasOwnProperty(context, env->get_string()).FromMaybe(false) ||
+-        desc_obj->HasOwnProperty(context, env->set_string()).FromMaybe(false))
++        desc_obj->HasOwnProperty(context, env->set_string()).FromMaybe(false)) {
+       args.GetReturnValue().Set(value);
++      return Intercepted::kYes;
++    }
+   }
++  return Intercepted::kNo;
+ }
+ 
+ // static
+-void ContextifyContext::PropertyDescriptorCallback(
+-    Local<Name> property,
+-    const PropertyCallbackInfo<Value>& args) {
++Intercepted ContextifyContext::PropertyDescriptorCallback(
++    Local<Name> property, const PropertyCallbackInfo<Value>& args) {
+   ContextifyContext* ctx = ContextifyContext::Get(args);
+ 
+   // Still initializing
+-  if (IsStillInitializing(ctx)) return;
++  if (IsStillInitializing(ctx)) {
++    return Intercepted::kNo;
++  }
+ 
+   Local<Context> context = ctx->context();
+ 
+@@ -577,19 +593,23 @@ void ContextifyContext::PropertyDescriptorCallback(
+     Local<Value> desc;
+     if (sandbox->GetOwnPropertyDescriptor(context, property).ToLocal(&desc)) {
+       args.GetReturnValue().Set(desc);
++      return Intercepted::kYes;
+     }
+   }
++  return Intercepted::kNo;
+ }
+ 
+ // static
+-void ContextifyContext::PropertyDefinerCallback(
++Intercepted ContextifyContext::PropertyDefinerCallback(
+     Local<Name> property,
+     const PropertyDescriptor& desc,
+-    const PropertyCallbackInfo<Value>& args) {
++    const PropertyCallbackInfo<void>& args) {
+   ContextifyContext* ctx = ContextifyContext::Get(args);
+ 
+   // Still initializing
+-  if (IsStillInitializing(ctx)) return;
++  if (IsStillInitializing(ctx)) {
++    return Intercepted::kNo;
++  }
+ 
+   Local<Context> context = ctx->context();
+   Isolate* isolate = context->GetIsolate();
+@@ -608,7 +628,7 @@ void ContextifyContext::PropertyDefinerCallback(
+   // If the property is set on the global as neither writable nor
+   // configurable, don't change it on the global or sandbox.
+   if (is_declared && read_only && dont_delete) {
+-    return;
++    return Intercepted::kNo;
+   }
+ 
+   Local<Object> sandbox = ctx->sandbox();
+@@ -631,6 +651,9 @@ void ContextifyContext::PropertyDefinerCallback(
+         desc.has_set() ? desc.set() : Undefined(isolate).As<Value>());
+ 
+     define_prop_on_sandbox(&desc_for_sandbox);
++    // TODO(https://github.com/nodejs/node/issues/52634): this should return
++    // kYes to behave according to the expected semantics.
++    return Intercepted::kNo;
+   } else {
+     Local<Value> value =
+         desc.has_value() ? desc.value() : Undefined(isolate).As<Value>();
+@@ -642,26 +665,32 @@ void ContextifyContext::PropertyDefinerCallback(
+       PropertyDescriptor desc_for_sandbox(value);
+       define_prop_on_sandbox(&desc_for_sandbox);
+     }
++    // TODO(https://github.com/nodejs/node/issues/52634): this should return
++    // kYes to behave according to the expected semantics.
++    return Intercepted::kNo;
+   }
+ }
+ 
+ // static
+-void ContextifyContext::PropertyDeleterCallback(
+-    Local<Name> property,
+-    const PropertyCallbackInfo<Boolean>& args) {
++Intercepted ContextifyContext::PropertyDeleterCallback(
++    Local<Name> property, const PropertyCallbackInfo<Boolean>& args) {
+   ContextifyContext* ctx = ContextifyContext::Get(args);
+ 
+   // Still initializing
+-  if (IsStillInitializing(ctx)) return;
++  if (IsStillInitializing(ctx)) {
++    return Intercepted::kNo;
++  }
+ 
+   Maybe<bool> success = ctx->sandbox()->Delete(ctx->context(), property);
+ 
+-  if (success.FromMaybe(false))
+-    return;
++  if (success.FromMaybe(false)) {
++    return Intercepted::kNo;
++  }
+ 
+   // Delete failed on the sandbox, intercept and do not delete on
+   // the global object.
+   args.GetReturnValue().Set(false);
++  return Intercepted::kYes;
+ }
+ 
+ // static
+@@ -681,76 +710,84 @@ void ContextifyContext::PropertyEnumeratorCallback(
+ }
+ 
+ // static
+-void ContextifyContext::IndexedPropertyGetterCallback(
+-    uint32_t index,
+-    const PropertyCallbackInfo<Value>& args) {
++Intercepted ContextifyContext::IndexedPropertyGetterCallback(
++    uint32_t index, const PropertyCallbackInfo<Value>& args) {
+   ContextifyContext* ctx = ContextifyContext::Get(args);
+ 
+   // Still initializing
+-  if (IsStillInitializing(ctx)) return;
++  if (IsStillInitializing(ctx)) {
++    return Intercepted::kNo;
++  }
+ 
+-  ContextifyContext::PropertyGetterCallback(
++  return ContextifyContext::PropertyGetterCallback(
+       Uint32ToName(ctx->context(), index), args);
+ }
+ 
+-
+-void ContextifyContext::IndexedPropertySetterCallback(
++Intercepted ContextifyContext::IndexedPropertySetterCallback(
+     uint32_t index,
+     Local<Value> value,
+-    const PropertyCallbackInfo<Value>& args) {
++    const PropertyCallbackInfo<void>& args) {
+   ContextifyContext* ctx = ContextifyContext::Get(args);
+ 
+   // Still initializing
+-  if (IsStillInitializing(ctx)) return;
++  if (IsStillInitializing(ctx)) {
++    return Intercepted::kNo;
++  }
+ 
+-  ContextifyContext::PropertySetterCallback(
++  return ContextifyContext::PropertySetterCallback(
+       Uint32ToName(ctx->context(), index), value, args);
+ }
+ 
+ // static
+-void ContextifyContext::IndexedPropertyDescriptorCallback(
+-    uint32_t index,
+-    const PropertyCallbackInfo<Value>& args) {
++Intercepted ContextifyContext::IndexedPropertyDescriptorCallback(
++    uint32_t index, const PropertyCallbackInfo<Value>& args) {
+   ContextifyContext* ctx = ContextifyContext::Get(args);
+ 
+   // Still initializing
+-  if (IsStillInitializing(ctx)) return;
++  if (IsStillInitializing(ctx)) {
++    return Intercepted::kNo;
++  }
+ 
+-  ContextifyContext::PropertyDescriptorCallback(
++  return ContextifyContext::PropertyDescriptorCallback(
+       Uint32ToName(ctx->context(), index), args);
+ }
+ 
+ 
+-void ContextifyContext::IndexedPropertyDefinerCallback(
++Intercepted ContextifyContext::IndexedPropertyDefinerCallback(
+     uint32_t index,
+     const PropertyDescriptor& desc,
+-    const PropertyCallbackInfo<Value>& args) {
++    const PropertyCallbackInfo<void>& args) {
+   ContextifyContext* ctx = ContextifyContext::Get(args);
+ 
+   // Still initializing
+-  if (IsStillInitializing(ctx)) return;
++  if (IsStillInitializing(ctx)) {
++    return Intercepted::kNo;
++  }
+ 
+-  ContextifyContext::PropertyDefinerCallback(
++  return ContextifyContext::PropertyDefinerCallback(
+       Uint32ToName(ctx->context(), index), desc, args);
+ }
+ 
+ // static
+-void ContextifyContext::IndexedPropertyDeleterCallback(
+-    uint32_t index,
+-    const PropertyCallbackInfo<Boolean>& args) {
++Intercepted ContextifyContext::IndexedPropertyDeleterCallback(
++    uint32_t index, const PropertyCallbackInfo<Boolean>& args) {
+   ContextifyContext* ctx = ContextifyContext::Get(args);
+ 
+   // Still initializing
+-  if (IsStillInitializing(ctx)) return;
++  if (IsStillInitializing(ctx)) {
++    return Intercepted::kNo;
++  }
+ 
+   Maybe<bool> success = ctx->sandbox()->Delete(ctx->context(), index);
+ 
+-  if (success.FromMaybe(false))
+-    return;
++  if (success.FromMaybe(false)) {
++    return Intercepted::kNo;
++  }
+ 
+   // Delete failed on the sandbox, intercept and do not delete on
+   // the global object.
+   args.GetReturnValue().Set(false);
++  return Intercepted::kYes;
+ }
+ 
+ void ContextifyScript::CreatePerIsolateProperties(
+diff --git a/src/node_contextify.h b/src/node_contextify.h
+index d42b5e0c544e726fc3f6d8392a554df9aa480fe9..ea2d513463057715127cb4b4f2d66b4cfcf71351 100644
+--- a/src/node_contextify.h
++++ b/src/node_contextify.h
+@@ -107,42 +107,39 @@ class ContextifyContext : public BaseObject {
+       const v8::FunctionCallbackInfo<v8::Value>& args);
+   static void WeakCallback(
+       const v8::WeakCallbackInfo<ContextifyContext>& data);
+-  static void PropertyGetterCallback(
++  static v8::Intercepted PropertyGetterCallback(
+       v8::Local<v8::Name> property,
+       const v8::PropertyCallbackInfo<v8::Value>& args);
+-  static void PropertySetterCallback(
++  static v8::Intercepted PropertySetterCallback(
+       v8::Local<v8::Name> property,
+       v8::Local<v8::Value> value,
+-      const v8::PropertyCallbackInfo<v8::Value>& args);
+-  static void PropertyDescriptorCallback(
++      const v8::PropertyCallbackInfo<void>& args);
++  static v8::Intercepted PropertyDescriptorCallback(
+       v8::Local<v8::Name> property,
+       const v8::PropertyCallbackInfo<v8::Value>& args);
+-  static void PropertyDefinerCallback(
++  static v8::Intercepted PropertyDefinerCallback(
+       v8::Local<v8::Name> property,
+       const v8::PropertyDescriptor& desc,
+-      const v8::PropertyCallbackInfo<v8::Value>& args);
+-  static void PropertyDeleterCallback(
++      const v8::PropertyCallbackInfo<void>& args);
++  static v8::Intercepted PropertyDeleterCallback(
+       v8::Local<v8::Name> property,
+       const v8::PropertyCallbackInfo<v8::Boolean>& args);
+   static void PropertyEnumeratorCallback(
+       const v8::PropertyCallbackInfo<v8::Array>& args);
+-  static void IndexedPropertyGetterCallback(
+-      uint32_t index,
+-      const v8::PropertyCallbackInfo<v8::Value>& args);
+-  static void IndexedPropertySetterCallback(
++  static v8::Intercepted IndexedPropertyGetterCallback(
++      uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& args);
++  static v8::Intercepted IndexedPropertySetterCallback(
+       uint32_t index,
+       v8::Local<v8::Value> value,
+-      const v8::PropertyCallbackInfo<v8::Value>& args);
+-  static void IndexedPropertyDescriptorCallback(
+-      uint32_t index,
+-      const v8::PropertyCallbackInfo<v8::Value>& args);
+-  static void IndexedPropertyDefinerCallback(
++      const v8::PropertyCallbackInfo<void>& args);
++  static v8::Intercepted IndexedPropertyDescriptorCallback(
++      uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& args);
++  static v8::Intercepted IndexedPropertyDefinerCallback(
+       uint32_t index,
+       const v8::PropertyDescriptor& desc,
+-      const v8::PropertyCallbackInfo<v8::Value>& args);
+-  static void IndexedPropertyDeleterCallback(
+-      uint32_t index,
+-      const v8::PropertyCallbackInfo<v8::Boolean>& args);
++      const v8::PropertyCallbackInfo<void>& args);
++  static v8::Intercepted IndexedPropertyDeleterCallback(
++      uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& args);
+ 
+   v8::Global<v8::Context> context_;
+   std::unique_ptr<v8::MicrotaskQueue> microtask_queue_;
+diff --git a/src/node_env_var.cc b/src/node_env_var.cc
+index bce7ae07214ddf970a530db29ed6970e14b7a5ed..85f82180d48d6cfd7738cd7b1e504f23b38153e8 100644
+--- a/src/node_env_var.cc
++++ b/src/node_env_var.cc
+@@ -16,6 +16,7 @@ using v8::DontEnum;
+ using v8::FunctionTemplate;
+ using v8::HandleScope;
+ using v8::Integer;
++using v8::Intercepted;
+ using v8::Isolate;
+ using v8::Just;
+ using v8::Local;
+@@ -336,24 +337,27 @@ Maybe<bool> KVStore::AssignToObject(v8::Isolate* isolate,
+   return Just(true);
+ }
+ 
+-static void EnvGetter(Local<Name> property,
+-                      const PropertyCallbackInfo<Value>& info) {
++static Intercepted EnvGetter(Local<Name> property,
++                             const PropertyCallbackInfo<Value>& info) {
+   Environment* env = Environment::GetCurrent(info);
+   CHECK(env->has_run_bootstrapping_code());
+   if (property->IsSymbol()) {
+-    return info.GetReturnValue().SetUndefined();
++    info.GetReturnValue().SetUndefined();
++    return Intercepted::kYes;
+   }
+   CHECK(property->IsString());
+   MaybeLocal<String> value_string =
+       env->env_vars()->Get(env->isolate(), property.As<String>());
+   if (!value_string.IsEmpty()) {
+     info.GetReturnValue().Set(value_string.ToLocalChecked());
++    return Intercepted::kYes;
+   }
++  return Intercepted::kNo;
+ }
+ 
+-static void EnvSetter(Local<Name> property,
+-                      Local<Value> value,
+-                      const PropertyCallbackInfo<Value>& info) {
++static Intercepted EnvSetter(Local<Name> property,
++                             Local<Value> value,
++                             const PropertyCallbackInfo<void>& info) {
+   Environment* env = Environment::GetCurrent(info);
+   CHECK(env->has_run_bootstrapping_code());
+   // calling env->EmitProcessEnvWarning() sets a variable indicating that
+@@ -369,35 +373,40 @@ static void EnvSetter(Local<Name> property,
+             "the "
+             "value to a string before setting process.env with it.",
+             "DEP0104")
+-            .IsNothing())
+-      return;
++            .IsNothing()) {
++      return Intercepted::kNo;
++    }
+   }
+ 
+   Local<String> key;
+   Local<String> value_string;
+   if (!property->ToString(env->context()).ToLocal(&key) ||
+       !value->ToString(env->context()).ToLocal(&value_string)) {
+-    return;
++    return Intercepted::kNo;
+   }
+ 
+   env->env_vars()->Set(env->isolate(), key, value_string);
+ 
+-  // Whether it worked or not, always return value.
+-  info.GetReturnValue().Set(value);
++  return Intercepted::kYes;
+ }
+ 
+-static void EnvQuery(Local<Name> property,
+-                     const PropertyCallbackInfo<Integer>& info) {
++static Intercepted EnvQuery(Local<Name> property,
++                            const PropertyCallbackInfo<Integer>& info) {
+   Environment* env = Environment::GetCurrent(info);
+   CHECK(env->has_run_bootstrapping_code());
+   if (property->IsString()) {
+     int32_t rc = env->env_vars()->Query(env->isolate(), property.As<String>());
+-    if (rc != -1) info.GetReturnValue().Set(rc);
++    if (rc != -1) {
++      // Return attributes for the property.
++      info.GetReturnValue().Set(v8::None);
++      return Intercepted::kYes;
++    }
+   }
++  return Intercepted::kNo;
+ }
+ 
+-static void EnvDeleter(Local<Name> property,
+-                       const PropertyCallbackInfo<Boolean>& info) {
++static Intercepted EnvDeleter(Local<Name> property,
++                              const PropertyCallbackInfo<Boolean>& info) {
+   Environment* env = Environment::GetCurrent(info);
+   CHECK(env->has_run_bootstrapping_code());
+   if (property->IsString()) {
+@@ -407,6 +416,7 @@ static void EnvDeleter(Local<Name> property,
+   // process.env never has non-configurable properties, so always
+   // return true like the tc39 delete operator.
+   info.GetReturnValue().Set(true);
++  return Intercepted::kYes;
+ }
+ 
+ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
+@@ -417,9 +427,9 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) {
+       env->env_vars()->Enumerate(env->isolate()));
+ }
+ 
+-static void EnvDefiner(Local<Name> property,
+-                       const PropertyDescriptor& desc,
+-                       const PropertyCallbackInfo<Value>& info) {
++static Intercepted EnvDefiner(Local<Name> property,
++                              const PropertyDescriptor& desc,
++                              const PropertyCallbackInfo<void>& info) {
+   Environment* env = Environment::GetCurrent(info);
+   if (desc.has_value()) {
+     if (!desc.has_writable() ||
+@@ -430,6 +440,7 @@ static void EnvDefiner(Local<Name> property,
+                                                "configurable, writable,"
+                                                " and enumerable "
+                                                "data descriptor");
++      return Intercepted::kYes;
+     } else if (!desc.configurable() ||
+                !desc.enumerable() ||
+                !desc.writable()) {
+@@ -438,6 +449,7 @@ static void EnvDefiner(Local<Name> property,
+                                                "configurable, writable,"
+                                                " and enumerable "
+                                                "data descriptor");
++      return Intercepted::kYes;
+     } else {
+       return EnvSetter(property, desc.value(), info);
+     }
+@@ -447,12 +459,14 @@ static void EnvDefiner(Local<Name> property,
+                                              "'process.env' does not accept an"
+                                              " accessor(getter/setter)"
+                                              " descriptor");
++    return Intercepted::kYes;
+   } else {
+     THROW_ERR_INVALID_OBJECT_DEFINE_PROPERTY(env,
+                                              "'process.env' only accepts a "
+                                              "configurable, writable,"
+                                              " and enumerable "
+                                              "data descriptor");
++    return Intercepted::kYes;
+   }
+ }
+ 
+diff --git a/src/node_external_reference.h b/src/node_external_reference.h
+index 24f0c6771720d8a6cdb684a0d562d01564d433f7..a1ad176c45f1900fb248650eb8533df4690bcf29 100644
+--- a/src/node_external_reference.h
++++ b/src/node_external_reference.h
+@@ -65,16 +65,17 @@ class ExternalReferenceRegistry {
+   V(v8::FunctionCallback)                                                      \
+   V(v8::AccessorNameGetterCallback)                                            \
+   V(v8::AccessorNameSetterCallback)                                            \
+-  V(v8::GenericNamedPropertyDefinerCallback)                                   \
+-  V(v8::GenericNamedPropertyDeleterCallback)                                   \
+-  V(v8::GenericNamedPropertyEnumeratorCallback)                                \
+-  V(v8::GenericNamedPropertyQueryCallback)                                     \
+-  V(v8::GenericNamedPropertySetterCallback)                                    \
+-  V(v8::IndexedPropertySetterCallback)                                         \
+-  V(v8::IndexedPropertyDefinerCallback)                                        \
+-  V(v8::IndexedPropertyDeleterCallback)                                        \
+-  V(v8::IndexedPropertyQueryCallback)                                          \
+-  V(v8::IndexedPropertyDescriptorCallback)                                     \
++  V(v8::NamedPropertyGetterCallback)                                           \
++  V(v8::NamedPropertyDefinerCallback)                                          \
++  V(v8::NamedPropertyDeleterCallback)                                          \
++  V(v8::NamedPropertyEnumeratorCallback)                                       \
++  V(v8::NamedPropertyQueryCallback)                                            \
++  V(v8::NamedPropertySetterCallback)                                           \
++  V(v8::IndexedPropertyGetterCallbackV2)                                       \
++  V(v8::IndexedPropertySetterCallbackV2)                                       \
++  V(v8::IndexedPropertyDefinerCallbackV2)                                      \
++  V(v8::IndexedPropertyDeleterCallbackV2)                                      \
++  V(v8::IndexedPropertyQueryCallbackV2)                                        \
+   V(const v8::String::ExternalStringResourceBase*)
+ 
+ #define V(ExternalReferenceType)                                               \