From 823905cd3b70ad95556f37d5ebed279cb1aef558 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Wed, 26 Mar 2025 11:20:41 +0000 Subject: [PATCH] interpreter: Support debug-hooks --- internal/interpreter/api.rs | 8 +++++ internal/interpreter/debug_hook.rs | 37 +++++++++++++++++++++++ internal/interpreter/dynamic_item_tree.rs | 2 +- internal/interpreter/eval.rs | 8 ++++- internal/interpreter/global_component.rs | 10 +++++- internal/interpreter/lib.rs | 2 ++ 6 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 internal/interpreter/debug_hook.rs diff --git a/internal/interpreter/api.rs b/internal/interpreter/api.rs index 148be397eb0..9579c0ff385 100644 --- a/internal/interpreter/api.rs +++ b/internal/interpreter/api.rs @@ -1527,6 +1527,14 @@ impl ComponentInstance { ) -> Vec<(i_slint_compiler::object_tree::ElementRc, usize)> { crate::highlight::element_node_at_source_code_position(&self.inner, path, offset) } + + /// Set a callback triggered by `Expression::DebugHook``. + #[cfg(feature = "internal-highlight")] + pub fn set_debug_hook_callback(&self, callback: Option) { + generativity::make_guard!(guard); + let comp = self.inner.unerase(guard); + crate::debug_hook::set_debug_hook_callback(comp, callback); + } } impl ComponentHandle for ComponentInstance { diff --git a/internal/interpreter/debug_hook.rs b/internal/interpreter/debug_hook.rs new file mode 100644 index 00000000000..0ba10e6ae1e --- /dev/null +++ b/internal/interpreter/debug_hook.rs @@ -0,0 +1,37 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 + +use crate::{dynamic_item_tree, Value}; + +use smol_str::SmolStr; + +use std::pin::Pin; + +pub type DebugHookCallback = Box Value>; + +pub(crate) fn set_debug_hook_callback( + component: Pin<&dynamic_item_tree::ItemTreeBox>, + func: Option, +) { + let Some(global_storage) = component.description().compiled_globals.clone() else { + return; + }; + *(global_storage.debug_hook_callback.borrow_mut()) = func; +} + +pub(crate) fn debug_hook_triggered( + component_instance: &dynamic_item_tree::InstanceRef, + id: SmolStr, + value: Value, +) -> Value { + let Some(global_storage) = component_instance.description.compiled_globals.clone() else { + return value; + }; + let callback = global_storage.debug_hook_callback.borrow(); + + if let Some(callback) = callback.as_ref() { + callback(id.as_str(), value) + } else { + value + } +} diff --git a/internal/interpreter/dynamic_item_tree.rs b/internal/interpreter/dynamic_item_tree.rs index 9d06b14878f..6cce8065ed3 100644 --- a/internal/interpreter/dynamic_item_tree.rs +++ b/internal/interpreter/dynamic_item_tree.rs @@ -402,7 +402,7 @@ pub struct ItemTreeDescription<'id> { pub(crate) popup_menu_description: PopupMenuDescription, /// The collection of compiled globals - compiled_globals: Option>, + pub(crate) compiled_globals: Option>, /// The type loader, which will be available only on the top-most `ItemTreeDescription`. /// All other `ItemTreeDescription`s have `None` here. diff --git a/internal/interpreter/eval.rs b/internal/interpreter/eval.rs index e18a8d32fbb..d166bf15c35 100644 --- a/internal/interpreter/eval.rs +++ b/internal/interpreter/eval.rs @@ -396,7 +396,13 @@ pub fn eval_expression(expression: &Expression, local_context: &mut EvalLocalCon } } Expression::EmptyComponentFactory => Value::ComponentFactory(Default::default()), - Expression::DebugHook { expression, .. } => eval_expression(expression, local_context), + Expression::DebugHook { expression, id: _id } => { + let value = eval_expression(expression, local_context); + #[cfg(feature = "internal-highlight")] + let value = crate::debug_hook::debug_hook_triggered(&local_context.component_instance, _id.clone(), value); + value + + } } } diff --git a/internal/interpreter/global_component.rs b/internal/interpreter/global_component.rs index 96958137ad2..5c17f1caa90 100644 --- a/internal/interpreter/global_component.rs +++ b/internal/interpreter/global_component.rs @@ -23,6 +23,9 @@ pub struct CompiledGlobalCollection { /// Map of all exported global singletons and their index in the compiled_globals vector. The key /// is the normalized name of the global. pub exported_globals_by_name: BTreeMap, + + #[cfg(feature = "internal-highlight")] + pub(crate) debug_hook_callback: RefCell>, } impl CompiledGlobalCollection { @@ -54,7 +57,12 @@ impl CompiledGlobalCollection { global }) .collect(); - Self { compiled_globals, exported_globals_by_name } + Self { + compiled_globals, + exported_globals_by_name, + #[cfg(feature = "internal-highlight")] + debug_hook_callback: RefCell::new(None), + } } } diff --git a/internal/interpreter/lib.rs b/internal/interpreter/lib.rs index f8efd56c89b..c7f11b54732 100644 --- a/internal/interpreter/lib.rs +++ b/internal/interpreter/lib.rs @@ -79,6 +79,8 @@ compile_error!( ); mod api; +#[cfg(feature = "internal-highlight")] +mod debug_hook; mod dynamic_item_tree; mod dynamic_type; mod eval;