From 62d33c4d7e7d2fac99274748b9e59fa6c9f75745 Mon Sep 17 00:00:00 2001 From: Sujay Jayakar Date: Tue, 30 Nov 2021 12:55:41 -0800 Subject: [PATCH] Add Function::GetScript{Line,Column}Number bindings (#843) --- src/binding.cc | 10 +++++++- src/function.rs | 14 +++++++++++ tests/test_api.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/binding.cc b/src/binding.cc index c05b7264..40f215e0 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -1565,6 +1565,14 @@ void v8__Function__SetName(const v8::Function& self, const v8::String& name) { return ptr_to_local(&self)->SetName(ptr_to_local(&name)); } +int v8__Function__GetScriptColumnNumber(const v8::Function& self) { + return ptr_to_local(&self)->GetScriptColumnNumber(); +} + +int v8__Function__GetScriptLineNumber(const v8::Function& self) { + return ptr_to_local(&self)->GetScriptLineNumber(); +} + const v8::Signature* v8__Signature__New(v8::Isolate* isolate, const v8::FunctionTemplate* templ) { return local_to_ptr(v8::Signature::New(isolate, ptr_to_local(templ))); @@ -2795,4 +2803,4 @@ const char* v8__CompiledWasmModule__SourceUrl(v8::CompiledWasmModule* self, void v8__CompiledWasmModule__DELETE(v8::CompiledWasmModule* self) { delete self; } -} // extern "C" \ No newline at end of file +} // extern "C" diff --git a/src/function.rs b/src/function.rs index 8c1d10cb..82323e35 100644 --- a/src/function.rs +++ b/src/function.rs @@ -42,6 +42,8 @@ extern "C" { ) -> *const Object; fn v8__Function__GetName(this: *const Function) -> *const String; fn v8__Function__SetName(this: *const Function, name: *const String); + fn v8__Function__GetScriptColumnNumber(this: *const Function) -> int; + fn v8__Function__GetScriptLineNumber(this: *const Function) -> int; fn v8__FunctionCallbackInfo__GetReturnValue( info: *const FunctionCallbackInfo, @@ -460,4 +462,16 @@ impl Function { pub fn set_name(&self, name: Local) { unsafe { v8__Function__SetName(self, &*name) } } + + /// Get the (zero-indexed) column number of the function's definition, if available. + pub fn get_script_column_number(&self) -> Option { + let ret = unsafe { v8__Function__GetScriptColumnNumber(self) }; + (ret >= 0).then(|| ret as u32) + } + + /// Get the (zero-indexed) line number of the function's definition, if available. + pub fn get_script_line_number(&self) -> Option { + let ret = unsafe { v8__Function__GetScriptLineNumber(self) }; + (ret >= 0).then(|| ret as u32) + } } diff --git a/tests/test_api.rs b/tests/test_api.rs index 325c39df..2071b2bc 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -1985,6 +1985,65 @@ fn function() { } } +#[test] +fn function_column_and_line_numbers() { + let _setup_guard = setup(); + let isolate = &mut v8::Isolate::new(Default::default()); + { + let scope = &mut v8::HandleScope::new(isolate); + let context = v8::Context::new(scope); + let scope = &mut v8::ContextScope::new(scope, context); + let source = mock_source( + scope, + "google.com", + r#"export function f(a, b) { + return a; +} + +export function anotherFunctionG(a, b) { + return b; +}"#, + ); + let module = v8::script_compiler::compile_module(scope, source).unwrap(); + let result = + module.instantiate_module(scope, unexpected_module_resolve_callback); + assert!(result.is_some()); + module.evaluate(scope).unwrap(); + assert_eq!(v8::ModuleStatus::Evaluated, module.get_status()); + + let namespace = module.get_module_namespace(); + assert!(namespace.is_module_namespace_object()); + let namespace_obj = namespace.to_object(scope).unwrap(); + + let f_str = v8::String::new(scope, "f").unwrap(); + let f_function_obj: v8::Local = namespace_obj + .get(scope, f_str.into()) + .unwrap() + .try_into() + .unwrap(); + // The column number is zero-indexed and indicates the position of the end of the name. + assert_eq!(f_function_obj.get_script_column_number(), Some(17)); + // The line number is zero-indexed as well. + assert_eq!(f_function_obj.get_script_line_number(), Some(0)); + + let g_str = v8::String::new(scope, "anotherFunctionG").unwrap(); + let g_function_obj: v8::Local = namespace_obj + .get(scope, g_str.into()) + .unwrap() + .try_into() + .unwrap(); + assert_eq!(g_function_obj.get_script_column_number(), Some(32)); + assert_eq!(g_function_obj.get_script_line_number(), Some(4)); + + let fn_template = v8::FunctionTemplate::new(scope, fn_callback); + let function = fn_template + .get_function(scope) + .expect("Unable to create function"); + assert_eq!(function.get_script_column_number(), None); + assert_eq!(function.get_script_line_number(), None); + } +} + #[test] fn constructor() { let _setup_guard = setup();