Intercepting the setting of static and instance methods

95 views
Skip to first unread message

Darin Dimitrov

unread,
Mar 2, 2020, 4:10:26 AM3/2/20
to v8-users
I am embedding V8 in my application and registered a custom class (MyClass). I am looking for a way to intercept the setting of methods on this class.

Here's my code:

    

auto platform = platform::NewDefaultPlatform();
V8
::InitializePlatform(platform.get());
V8
::Initialize();
std
::string flags = "--expose_gc --jitless";
V8
::SetFlagsFromString(flags.c_str(), flags.size());
Isolate::CreateParams create_params;
create_params
.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();

Isolate* isolate = Isolate::New(create_params);
{
   
Isolate::Scope isolate_scope(isolate);
   
HandleScope handle_scope(isolate);

   
Local<FunctionTemplate> myClassTemplate = FunctionTemplate::New(isolate);
   
Local<FunctionTemplate> myInstanceMethodTemplate = FunctionTemplate::New(isolate);
    myClassTemplate
->InstanceTemplate()->Set(v8::String::NewFromUtf8(isolate, "myInstanceMethod", v8::NewStringType::kNormal).ToLocalChecked(), myInstanceMethodTemplate);

   
Local<ObjectTemplate> globalTemplate = ObjectTemplate::New(isolate);
    globalTemplate
->Set(v8::String::NewFromUtf8(isolate, "MyClass", v8::NewStringType::kNormal).ToLocalChecked(), myClassTemplate);

   
Local<v8::Context> context = v8::Context::New(isolate, nullptr, globalTemplate);
   
Context::Scope context_scope(context);
   
{
       
Local<v8::Function> myClassCtor = myClassTemplate->GetFunction(context).ToLocalChecked();
       
Local<v8::Function> myStaticMethod = v8::Function::New(context, nullptr).ToLocalChecked();
       
assert(myClassCtor->Set(context, v8::String::NewFromUtf8(isolate, "myStaticMethod", v8::NewStringType::kNormal).ToLocalChecked(), myStaticMethod).FromMaybe(false));

        std
::string src = R"(
           // I want to intercept setting this static method and raise some C++ callback when this code is executed
           MyClass.myStaticMethod = () => { };

           // I want to intercept setting this instance method and raise some C++ callback when this code is executed
           MyClass.prototype.myInstanceMethod = () => { };
       )"
;

       
Local<v8::String> source = v8::String::NewFromUtf8(isolate, src.c_str(), v8::NewStringType::kNormal).ToLocalChecked();
       
Local<Script> script = Script::Compile(context, source).ToLocalChecked();
       
Local<Value> result = script->Run(context).ToLocalChecked();
       
assert(!result.IsEmpty());
   
}

}

isolate
->Dispose();
V8
::Dispose();
V8
::ShutdownPlatform();
delete create_params.array_buffer_allocator;



In this code I need a C++ callback to be raised when the script is trying to replace some existing static or instance method on my custom class.

Is there some API in V8 that I can use to achieve that?

I have tried registering a NamedPropertyHandlerConfiguration but my callback is never called:

myClassTemplate->InstanceTemplate()->SetHandler(NamedPropertyHandlerConfiguration(nullptr, [](Local<Name> property, Local<Value> value, const PropertyCallbackInfo<Value>& info) {
    printf
("ok");
}));


Basically I need a way to detect that some script is trying to replace the methods which I have registered manually.

Darin Dimitrov

unread,
Mar 2, 2020, 4:32:50 AM3/2/20
to v8-users
I managed to intercept the setting of the instance method with the following:

myClassTemplate->PrototypeTemplate()->SetHandler(NamedPropertyHandlerConfiguration(nullptr, [](Local<Name> property, Local<Value> value, const PropertyCallbackInfo<Value>& info) {
    printf
("This will be called when setting the instance method on the prototype");
}));


So the question remains only for the static method interception.

Darin Dimitrov

unread,
Mar 3, 2020, 7:20:04 AM3/3/20
to v8-users
I tried every possible method but cannot intercept setting members on a Local<Function> instance. Also couldn't find any example in the https://chromium.googlesource.com/v8/v8/+/refs/heads/lkgr/test/cctest/test-api-interceptors.cc

Is this simply not possible?

Ben Noordhuis

unread,
Mar 3, 2020, 4:21:00 PM3/3/20
to v8-users
On Tue, Mar 3, 2020 at 1:20 PM Darin Dimitrov <darin.d...@gmail.com> wrote:
>
> I tried every possible method but cannot intercept setting members on a Local<Function> instance. Also couldn't find any example in the https://chromium.googlesource.com/v8/v8/+/refs/heads/lkgr/test/cctest/test-api-interceptors.cc
>
> Is this simply not possible?

I think for Function objects, you can't do better than SetAccessor(),
but that only lets you intercept a single predetermined named property
and I infer you want to intercept them all.

Darin Dimitrov

unread,
Mar 3, 2020, 4:39:34 PM3/3/20
to v8-users
Ben, yes, unfortunately the SetAccessor method doesn't allow intercepting the setting of any arbitrary member (property or function) on the function.


On Tuesday, March 3, 2020 at 11:21:00 PM UTC+2, Ben Noordhuis wrote:

Darin Dimitrov

unread,
Mar 4, 2020, 7:31:16 AM3/4/20
to v8-users
I was able to achieve this by exposing some internal functionality. Normally there's already a SetHandler method on a FunctionTemplate but it is not available in the public API: https://source.chromium.org/chromium/chromium/src/+/master:v8/src/objects/templates-inl.h;l=72;drc=b892cf58e162a8f66cd76d7472f129fe0fb6a7d1;bpv=1;bpt=1

After exposing it, I was able to intercept the setting of any property on my function.
Reply all
Reply to author
Forward
0 new messages