Index: test/cctest/test-api-interceptors.cc |
diff --git a/test/cctest/test-api-interceptors.cc b/test/cctest/test-api-interceptors.cc |
index c81f69d4297c637dc07d51e6644b716e8e48f48e..cc85f6fb31c296820a00ab867072ad9e219a3ce5 100644 |
--- a/test/cctest/test-api-interceptors.cc |
+++ b/test/cctest/test-api-interceptors.cc |
@@ -268,6 +268,23 @@ void CheckThisIndexedPropertySetter( |
.FromJust()); |
} |
+void CheckThisIndexedPropertyDescriptor( |
+ uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDescriptor)); |
+ ApiTestFuzzer::Fuzz(); |
+ CHECK(info.This() |
+ ->Equals(info.GetIsolate()->GetCurrentContext(), bottom) |
+ .FromJust()); |
+} |
+ |
+void CheckThisNamedPropertyDescriptor( |
+ Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDescriptor)); |
+ ApiTestFuzzer::Fuzz(); |
+ CHECK(info.This() |
+ ->Equals(info.GetIsolate()->GetCurrentContext(), bottom) |
+ .FromJust()); |
+} |
void CheckThisNamedPropertySetter( |
Local<Name> property, Local<Value> value, |
@@ -1222,13 +1239,13 @@ namespace { |
void NotInterceptingPropertyDefineCallback( |
Local<Name> name, const v8::PropertyDescriptor& desc, |
const v8::PropertyCallbackInfo<v8::Value>& info) { |
- // Do not intercept by not calling info.GetReturnValue().Set() |
+ // Do not intercept by not calling info.GetReturnValue().Set(). |
} |
void InterceptingPropertyDefineCallback( |
Local<Name> name, const v8::PropertyDescriptor& desc, |
const v8::PropertyCallbackInfo<v8::Value>& info) { |
- // intercept the callback by setting a non-empty handle |
+ // Intercept the callback by setting a non-empty handle |
info.GetReturnValue().Set(name); |
} |
@@ -1648,6 +1665,74 @@ THREADED_TEST(PropertyDefinerCallbackWithSetter) { |
.FromJust()); |
} |
+namespace { |
+void EmptyPropertyDescriptorCallback( |
+ Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ // Do not intercept by not calling info.GetReturnValue().Set(). |
+} |
+ |
+void InterceptingPropertyDescriptorCallback( |
+ Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { |
+ // Intercept the callback by setting a different descriptor. |
+ const char* code = |
+ "var desc = {value: 42};" |
+ "desc;"; |
+ Local<Value> descriptor = v8_compile(code) |
+ ->Run(info.GetIsolate()->GetCurrentContext()) |
+ .ToLocalChecked(); |
+ info.GetReturnValue().Set(descriptor); |
+} |
+} // namespace |
+ |
+THREADED_TEST(PropertyDescriptorCallback) { |
+ v8::HandleScope scope(CcTest::isolate()); |
+ LocalContext env; |
+ |
+ { // Normal behavior of getOwnPropertyDescriptor() with empty callback. |
+ v8::Local<v8::FunctionTemplate> templ = |
+ v8::FunctionTemplate::New(CcTest::isolate()); |
+ templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration( |
+ 0, 0, EmptyPropertyDescriptorCallback, 0, 0, 0)); |
+ env->Global() |
+ ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local()) |
+ .ToLocalChecked() |
+ ->NewInstance(env.local()) |
+ .ToLocalChecked()) |
+ .FromJust(); |
+ const char* code = |
+ "obj.x = 17; " |
+ "var desc = Object.getOwnPropertyDescriptor(obj, 'x');" |
+ "desc.value;"; |
+ CHECK_EQ(17, v8_compile(code) |
+ ->Run(env.local()) |
+ .ToLocalChecked() |
+ ->Int32Value(env.local()) |
+ .FromJust()); |
+ } |
+ |
+ { // Intercept getOwnPropertyDescriptor(). |
+ v8::Local<v8::FunctionTemplate> templ = |
+ v8::FunctionTemplate::New(CcTest::isolate()); |
+ templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration( |
+ 0, 0, InterceptingPropertyDescriptorCallback, 0, 0, 0)); |
+ env->Global() |
+ ->Set(env.local(), v8_str("obj"), templ->GetFunction(env.local()) |
+ .ToLocalChecked() |
+ ->NewInstance(env.local()) |
+ .ToLocalChecked()) |
+ .FromJust(); |
+ const char* code = |
+ "obj.x = 17; " |
+ "var desc = Object.getOwnPropertyDescriptor(obj, 'x');" |
+ "desc.value;"; |
+ CHECK_EQ(42, v8_compile(code) |
+ ->Run(env.local()) |
+ .ToLocalChecked() |
+ ->Int32Value(env.local()) |
+ .FromJust()); |
+ } |
+} |
+ |
int echo_indexed_call_count = 0; |
@@ -1689,17 +1774,16 @@ THREADED_TEST(PropertyHandlerInPrototype) { |
v8::Isolate* isolate = env->GetIsolate(); |
v8::HandleScope scope(isolate); |
- // Set up a prototype chain with three interceptors. |
v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate); |
templ->InstanceTemplate()->SetHandler(v8::IndexedPropertyHandlerConfiguration( |
CheckThisIndexedPropertyHandler, CheckThisIndexedPropertySetter, |
CheckThisIndexedPropertyQuery, CheckThisIndexedPropertyDeleter, |
- CheckThisIndexedPropertyEnumerator, CheckThisIndexedPropertyDefiner)); |
+ CheckThisIndexedPropertyEnumerator)); |
templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration( |
CheckThisNamedPropertyHandler, CheckThisNamedPropertySetter, |
CheckThisNamedPropertyQuery, CheckThisNamedPropertyDeleter, |
- CheckThisNamedPropertyEnumerator, CheckThisNamedPropertyDefiner)); |
+ CheckThisNamedPropertyEnumerator)); |
bottom = templ->GetFunction(env.local()) |
.ToLocalChecked() |
@@ -1736,10 +1820,63 @@ THREADED_TEST(PropertyHandlerInPrototype) { |
// Enumerators. |
CompileRun("for (var p in obj) ;"); |
+} |
+ |
+TEST(PropertyHandlerInPrototypeWithDefine) { |
+ LocalContext env; |
+ v8::Isolate* isolate = env->GetIsolate(); |
+ v8::HandleScope scope(isolate); |
+ |
+ v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate); |
+ templ->InstanceTemplate()->SetHandler(v8::IndexedPropertyHandlerConfiguration( |
+ CheckThisIndexedPropertyHandler, CheckThisIndexedPropertySetter, |
+ CheckThisIndexedPropertyDescriptor, CheckThisIndexedPropertyDeleter, |
+ CheckThisIndexedPropertyEnumerator, CheckThisIndexedPropertyDefiner)); |
+ |
+ templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration( |
+ CheckThisNamedPropertyHandler, CheckThisNamedPropertySetter, |
+ CheckThisNamedPropertyDescriptor, CheckThisNamedPropertyDeleter, |
+ CheckThisNamedPropertyEnumerator, CheckThisNamedPropertyDefiner)); |
+ |
+ bottom = templ->GetFunction(env.local()) |
+ .ToLocalChecked() |
+ ->NewInstance(env.local()) |
+ .ToLocalChecked(); |
+ Local<v8::Object> top = templ->GetFunction(env.local()) |
+ .ToLocalChecked() |
+ ->NewInstance(env.local()) |
+ .ToLocalChecked(); |
+ Local<v8::Object> middle = templ->GetFunction(env.local()) |
+ .ToLocalChecked() |
+ ->NewInstance(env.local()) |
+ .ToLocalChecked(); |
+ |
+ bottom->SetPrototype(env.local(), middle).FromJust(); |
+ middle->SetPrototype(env.local(), top).FromJust(); |
+ env->Global()->Set(env.local(), v8_str("obj"), bottom).FromJust(); |
+ |
+ // Indexed and named get. |
+ CompileRun("obj[0]"); |
+ CompileRun("obj.x"); |
+ |
+ // Indexed and named set. |
+ CompileRun("obj[1] = 42"); |
+ CompileRun("obj.y = 42"); |
+ |
+ // Indexed and named deleter. |
+ CompileRun("delete obj[0]"); |
+ CompileRun("delete obj.x"); |
+ |
+ // Enumerators. |
+ CompileRun("for (var p in obj) ;"); |
// Indexed and named definer. |
CompileRun("Object.defineProperty(obj, 2, {});"); |
CompileRun("Object.defineProperty(obj, 'z', {});"); |
+ |
+ // Indexed and named propertyDescriptor. |
+ CompileRun("Object.getOwnPropertyDescriptor(obj, 2);"); |
+ CompileRun("Object.getOwnPropertyDescriptor(obj, 'z');"); |
} |