Context nullification, cached monitor nodes

This commit is contained in:
Adam
2025-07-10 01:47:40 -07:00
parent 1398405529
commit cf0a32b9b1
82 changed files with 2235 additions and 1684 deletions

View File

@@ -7,7 +7,7 @@ use std::sync::atomic::AtomicU64;
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::token::Comma;
use syn::{Error, Ident, PatIdent, Token, WhereClause, WherePredicate, parse_quote};
use syn::{Error, Ident, PatIdent, Token, TypeParamBound, WhereClause, WherePredicate, parse_quote};
static NODE_ID: AtomicU64 = AtomicU64::new(0);
pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStream2> {
@@ -346,6 +346,8 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
let properties = &attributes.properties_string.as_ref().map(|value| quote!(Some(#value))).unwrap_or(quote!(None));
let node_input_accessor = generate_node_input_references(parsed, fn_generics, &field_idents, &graphene_core, &identifier);
let context_dependencies = input.context_dependency.clone();
Ok(quote! {
/// Underlying implementation for [#struct_name]
#[inline]
@@ -373,10 +375,10 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
mod #mod_name {
use super::*;
use #graphene_core as gcore;
use gcore::{Node, NodeIOTypes, concrete, fn_type, fn_type_fut, future, ProtoNodeIdentifier, WasmNotSync, NodeIO};
use gcore::{Node, NodeIOTypes, concrete, fn_type, fn_type_fut, future, ProtoNodeIdentifier, WasmNotSync, NodeIO, ContextDependency};
use gcore::value::ClonedNode;
use gcore::ops::TypeNode;
use gcore::registry::{NodeMetadata, FieldMetadata, NODE_REGISTRY, NODE_METADATA, DynAnyNode, DowncastBothNode, DynFuture, TypeErasedBox, PanicNode, RegistryValueSource, RegistryWidgetOverride};
use gcore::registry::{NodeMetadata, FieldMetadata, NODE_REGISTRY, NODE_METADATA, NODE_CONTEXT_DEPENDENCY, DynAnyNode, DowncastBothNode, DynFuture, TypeErasedBox, PanicNode, RegistryValueSource, RegistryWidgetOverride};
use gcore::ctor::ctor;
// Use the types specified in the implementation
@@ -429,6 +431,17 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
};
NODE_METADATA.lock().unwrap().insert(#identifier(), metadata);
}
#[cfg_attr(not(target_arch = "wasm32"), ctor)]
fn register_context_dependency() {
let mut context_dependency = NODE_CONTEXT_DEPENDENCY.lock().unwrap();
context_dependency.insert(
#identifier,
vec![
#(ContextDependency::#context_dependencies,)*
]
);
}
}
})
}
@@ -602,7 +615,6 @@ fn generate_register_node_impl(parsed: &ParsedNodeFn, field_names: &[&Ident], st
));
}
let registry_name = format_ident!("__node_registry_{}_{}", NODE_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst), struct_name);
Ok(quote! {
#[cfg_attr(not(target_arch = "wasm32"), ctor)]
@@ -615,11 +627,13 @@ fn generate_register_node_impl(parsed: &ParsedNodeFn, field_names: &[&Ident], st
]
);
}
#[cfg(target_arch = "wasm32")]
#[unsafe(no_mangle)]
extern "C" fn #registry_name() {
register_node();
register_metadata();
register_context_dependency();
}
})
}

View File

@@ -135,6 +135,7 @@ pub(crate) struct Input {
pub(crate) pat_ident: PatIdent,
pub(crate) ty: Type,
pub(crate) implementations: Punctuated<Type, Comma>,
pub(crate) context_dependency: Vec<proc_macro2::TokenStream>,
}
impl Parse for Implementation {
@@ -350,6 +351,7 @@ fn parse_inputs(inputs: &Punctuated<FnArg, Comma>) -> syn::Result<(Input, Vec<Pa
pat_ident,
ty: (**ty).clone(),
implementations,
context_dependency: Vec::new(),
});
} else if let Pat::Ident(pat_ident) = &**pat {
let field = parse_field(pat_ident.clone(), (**ty).clone(), attrs).map_err(|e| Error::new_spanned(pat_ident, format!("Failed to parse argument '{}': {}", pat_ident.ident, e)))?;
@@ -630,6 +632,24 @@ pub fn new_node_fn(attr: TokenStream2, item: TokenStream2) -> TokenStream2 {
impl ParsedNodeFn {
fn replace_impl_trait_in_input(&mut self) {
if let Type::ImplTrait(impl_trait) = self.input.ty.clone() {
let mut dependency_tokens = Vec::new();
for bound in &impl_trait.bounds {
if let syn::TypeParamBound::Trait(trait_bound) = bound {
if let Some(ident) = trait_bound.path.get_ident() {
match ident.to_string().as_str() {
"ExtractFootprint" => dependency_tokens.push(quote::quote! {ExtractFootprint}),
"ExtractDownstreamTransform" => dependency_tokens.push(quote::quote! {ExtractDownstreamTransform}),
"ExtractRealTime" => dependency_tokens.push(quote::quote! {ExtractRealTime}),
"ExtractAnimationTime" => dependency_tokens.push(quote::quote! {ExtractAnimationTime}),
"ExtractIndex" => dependency_tokens.push(quote::quote! {ExtractIndex}),
"ExtractVarArgs" => dependency_tokens.push(quote::quote! {ExtractVarArgs}),
_ => {}
}
}
}
}
self.input.context_dependency = dependency_tokens;
let ident = Ident::new("_Input", impl_trait.span());
let mut bounds = impl_trait.bounds;
bounds.push(parse_quote!('n));
@@ -768,6 +788,7 @@ mod tests {
pat_ident: pat_ident("a"),
ty: parse_quote!(f64),
implementations: Punctuated::new(),
context_dependency: Vec::new(),
},
output_type: parse_quote!(f64),
is_async: false,
@@ -829,6 +850,7 @@ mod tests {
pat_ident: pat_ident("footprint"),
ty: parse_quote!(Footprint),
implementations: Punctuated::new(),
context_dependency: Vec::new(),
},
output_type: parse_quote!(T),
is_async: false,
@@ -901,6 +923,7 @@ mod tests {
pat_ident: pat_ident("_"),
ty: parse_quote!(impl Ctx),
implementations: Punctuated::new(),
context_dependency: Vec::new(),
},
output_type: parse_quote!(VectorData),
is_async: false,
@@ -958,6 +981,7 @@ mod tests {
pat_ident: pat_ident("image"),
ty: parse_quote!(RasterDataTable<P>),
implementations: Punctuated::new(),
context_dependency: Vec::new(),
},
output_type: parse_quote!(RasterDataTable<P>),
is_async: false,
@@ -1027,6 +1051,7 @@ mod tests {
pat_ident: pat_ident("a"),
ty: parse_quote!(f64),
implementations: Punctuated::new(),
context_dependency: Vec::new(),
},
output_type: parse_quote!(f64),
is_async: false,
@@ -1084,6 +1109,7 @@ mod tests {
pat_ident: pat_ident("api"),
ty: parse_quote!(&WasmEditorApi),
implementations: Punctuated::new(),
context_dependency: Vec::new(),
},
output_type: parse_quote!(RasterDataTable<CPU>),
is_async: true,
@@ -1141,6 +1167,7 @@ mod tests {
pat_ident: pat_ident("input"),
ty: parse_quote!(i32),
implementations: Punctuated::new(),
context_dependency: Vec::new(),
},
output_type: parse_quote!(i32),
is_async: false,