From 41003d097d55792c4db02908c785e013324fc586 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Fri, 11 Feb 2022 20:51:13 +0530 Subject: [PATCH] Add v8::FunctionCallbackInfo::NewTarget bindings (#898) --- src/binding.cc | 5 +++++ src/function.rs | 10 ++++++++++ tests/test_api.rs | 25 +++++++++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/src/binding.cc b/src/binding.cc index 53d0d008..fa094d2d 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -1714,6 +1714,11 @@ const v8::Value* v8__FunctionCallbackInfo__Data( return local_to_ptr(self.Data()); } +const v8::Value* v8__FunctionCallbackInfo__NewTarget( + const v8::FunctionCallbackInfo& self) { + return local_to_ptr(self.NewTarget()); +} + void v8__ReturnValue__Set(v8::ReturnValue* self, const v8::Value& value) { self->Set(ptr_to_local(&value)); diff --git a/src/function.rs b/src/function.rs index 59884c11..154a2f04 100644 --- a/src/function.rs +++ b/src/function.rs @@ -66,6 +66,9 @@ extern "C" { fn v8__FunctionCallbackInfo__Data( this: *const FunctionCallbackInfo, ) -> *const Value; + fn v8__FunctionCallbackInfo__NewTarget( + this: *const FunctionCallbackInfo, + ) -> *const Value; fn v8__PropertyCallbackInfo__GetReturnValue( this: *const PropertyCallbackInfo, @@ -215,6 +218,13 @@ impl<'s> FunctionCallbackArguments<'s> { .unwrap() } } + + /// For construct calls, this returns the "new.target" value. + pub fn new_target(&self) -> Local<'s, Value> { + unsafe { + Local::from_raw(v8__FunctionCallbackInfo__NewTarget(self.info)).unwrap() + } + } } #[derive(Debug)] diff --git a/tests/test_api.rs b/tests/test_api.rs index 0ac9aeb4..14d62512 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -1952,6 +1952,21 @@ fn fn_callback( rv.set(s.into()); } +fn fn_callback_new( + scope: &mut v8::HandleScope, + args: v8::FunctionCallbackArguments, + mut rv: v8::ReturnValue, +) { + assert_eq!(args.length(), 0); + assert!(args.new_target().is_object()); + let recv = args.this(); + let key = v8::String::new(scope, "works").unwrap(); + let value = v8::Boolean::new(scope, true); + assert!(recv.set(scope, key.into(), value.into()).unwrap()); + assert!(rv.get(scope).is_undefined()); + rv.set(recv.into()); +} + fn fn_callback2( scope: &mut v8::HandleScope, args: v8::FunctionCallbackArguments, @@ -2073,6 +2088,16 @@ fn function() { let result = eval(scope, "f.prototype").unwrap(); assert!(result.is_undefined()); assert!(eval(scope, "new f()").is_none()); // throws + + let function = v8::Function::builder(fn_callback_new).build(scope).unwrap(); + let name = v8::String::new(scope, "f2").unwrap(); + global.set(scope, name.into(), function.into()).unwrap(); + let f2: v8::Local = + eval(scope, "new f2()").unwrap().try_into().unwrap(); + let key = v8::String::new(scope, "works").unwrap(); + let value = f2.get(scope, key.into()).unwrap(); + assert!(value.is_boolean()); + assert!(value.boolean_value(scope)); } }