1#[allow(unused_imports)]
2use super::*;
3
4
5#[macro_export]
68macro_rules! extension {
69 {extern $symbol_initializer:ident $(, $symbol_finalizer:ident;
71 move $initializer:path, final $($finalizer:path)?)?;
72 gen $context_initializer:path, final $($context_finalizer:path)?;
73 } => {
74 const _: () = {
75 mod _flash_runtime_extension {
76 use super::*;
77 $crate::extension! {@Extern [$symbol_initializer $(, $symbol_finalizer, $initializer $(, $finalizer)?)?]}
78 #[allow(unsafe_op_in_unsafe_fn)]
79 unsafe extern "C" fn ctx_initializer (
80 ext_data: $crate::c::markers::FREData,
81 ctx_type: $crate::c::markers::FREStr,
82 ctx: $crate::c::markers::FREContext,
83 num_funcs_to_set: *mut u32,
84 funcs_to_set: *mut *const $crate::c::ffi::FRENamedFunction,
85 ) {
86 let context_initializer: $crate::function::ContextInitializer = $context_initializer;
87 $crate::context::FlashRuntime::with_context_initializer(ext_data, ctx_type, &ctx, num_funcs_to_set, funcs_to_set, $context_initializer);
88 }
89 #[allow(unsafe_op_in_unsafe_fn)]
90 unsafe extern "C" fn ctx_finalizer (ctx: $crate::c::markers::FREContext) {
91 $crate::context::FlashRuntime::with(&ctx, |frt| {
92 $(
93 let context_finalizer: $crate::function::ContextFinalizer = $context_finalizer;
94 context_finalizer(frt);
95 )?
96 let raw = $crate::validated::NonNullFREData::new(frt.current_context().get_native_data().expect("Failed to retrieve native data from FFI.")).expect("`ContextRegistry` is expected in native data but is missing.");
97 assert!(<$crate::context::ContextRegistry as $crate::data::Data>::ref_from(raw).is_ok());
98 $crate::data::drop_from(raw);
99 });
100
101 }
102 }
103 };
104 };
105 {@Extern [$symbol_initializer:ident, $symbol_finalizer:ident, $initializer:path $(, $finalizer:path)?]
107 } => {
108 #[allow(unsafe_op_in_unsafe_fn, non_snake_case)]
109 #[unsafe(no_mangle)]
110 pub unsafe extern "C" fn $symbol_initializer (
111 ext_data_to_set: *mut $crate::c::markers::FREData,
112 ctx_initializer_to_set: *mut $crate::c::ffi::FREContextInitializer,
113 ctx_finalizer_to_set: *mut $crate::c::ffi::FREContextFinalizer,
114 ) {
115 assert!(!ext_data_to_set.is_null());
116 assert!(!ctx_initializer_to_set.is_null());
117 assert!(!ctx_finalizer_to_set.is_null());
118 let initializer: $crate::function::Initializer = $initializer;
119 if let Some(ext_data) = initializer() {
120 *ext_data_to_set = $crate::data::into_raw(ext_data).as_ptr();
121 }
122 *ctx_initializer_to_set = ctx_initializer;
123 *ctx_finalizer_to_set = Some(ctx_finalizer);
124 $crate::extension! (@Hook);
125 }
126 #[allow(unsafe_op_in_unsafe_fn, non_snake_case)]
127 #[unsafe(no_mangle)]
128 pub unsafe extern "C" fn $symbol_finalizer (ext_data: $crate::c::markers::FREData) {
129 let ext_data = $crate::validated::NonNullFREData::new(ext_data)
130 .map(|raw| $crate::data::from_raw(raw));
131 $(
132 let finalizer: $crate::function::Finalizer = $finalizer;
133 finalizer(ext_data);
134 )?
135 }
136 };
137 {@Extern [$symbol_initializer:ident]
139 } => {
140 #[allow(unsafe_op_in_unsafe_fn, non_snake_case)]
141 #[unsafe(no_mangle)]
142 pub unsafe extern "C" fn $symbol_initializer (
143 ext_data_to_set: *mut $crate::c::markers::FREData,
144 ctx_initializer_to_set: *mut $crate::c::ffi::FREContextInitializer,
145 ctx_finalizer_to_set: *mut $crate::c::ffi::FREContextFinalizer,
146 ) {
147 assert!(!ext_data_to_set.is_null());
148 assert!(!ctx_initializer_to_set.is_null());
149 assert!(!ctx_finalizer_to_set.is_null());
150 *ctx_initializer_to_set = ctx_initializer;
151 *ctx_finalizer_to_set = Some(ctx_finalizer);
152 $crate::extension! (@Hook);
153 }
154 };
155 (@Hook
157 ) => {
158 static INIT_HOOK: ::std::sync::Once = ::std::sync::Once::new();
159 INIT_HOOK.call_once(|| {
160 let default_hook = ::std::panic::take_hook();
161 ::std::panic::set_hook(Box::new(move |info| {
162 let payload = info.payload_as_str().unwrap_or_default();
163 let location = info.location()
164 .map(|l| format!("at {}:{}:{}", l.file(), l.line(), l.column()))
165 .unwrap_or_default();
166 let backtrace = ::std::backtrace::Backtrace::force_capture();
167 let s = format!("{payload}\n{location}\n{backtrace}");
168 $crate::_internal::LAST_PANIC_INFO.with(|i| {*i.borrow_mut() = Some(s);});
169 default_hook(info);
170 }));
171 });
172 }
173}
174
175
176#[macro_export]
222macro_rules! function {
223 {$name:ident ($($arguments:tt)+) $(-> $return_type:ty)? $body:block
225 } => {
226 #[allow(non_upper_case_globals)]
227 pub const $name: &'static $crate::function::FunctionDefinition = & $crate::function::FunctionDefinition::new(
228 $crate::function!(@Name $name), {
229 #[allow(unsafe_op_in_unsafe_fn)]
230 unsafe extern "C" fn abi(
231 ctx: $crate::c::markers::FREContext,
232 func_data: $crate::c::markers::FREData,
233 argc: u32,
234 argv: *const $crate::c::markers::FREObject,
235 ) -> $crate::c::markers::FREObject {
236 fn func <'a> (
237 frt: &$crate::context::FlashRuntime<'a>,
238 func_data: Option<&mut dyn ::std::any::Any>,
239 args: &[$crate::types::Object<'a>],
240 ) -> $crate::types::Object<'a> {
241 $crate::function! {@Parameters [frt, func_data, args] $($arguments)+}
242 let r = ::std::panic::catch_unwind(|| -> $crate::function!(@Return $($return_type)?) {
243 $body
244 });
245 $crate::function! (@Unwind [frt, r])
246 }
247 $crate::context::FlashRuntime::with_method(&ctx, func_data, argc, argv, func)
248 }
249 abi},
250 );
251 };
252 ($name:ident use $func:path
254 ) => {
255 #[allow(non_upper_case_globals)]
256 pub const $name: &'static $crate::function::FunctionDefinition = & $crate::function::FunctionDefinition::new(
257 $crate::function!(@Name $name), {
258 #[allow(unsafe_op_in_unsafe_fn)]
259 unsafe extern "C" fn abi(
260 ctx: $crate::c::markers::FREContext,
261 func_data: $crate::c::markers::FREData,
262 argc: u32,
263 argv: *const $crate::c::markers::FREObject,
264 ) -> $crate::c::markers::FREObject {
265 let func: $crate::function::Function = $func;
266 let r = ::std::panic::catch_unwind(|| -> $crate::c::markers::FREObject {
267 $crate::context::FlashRuntime::with_method(&ctx, func_data, argc, argv, func)
268 });
269 let frt: $crate::context::FlashRuntime = ::std::mem::transmute(ctx);
270 $crate::function! (@Unwind [&frt, r])
271 }
272 abi},
273 );
274 };
275 (@Name $name:ident
277 ) => {
278 unsafe {
279 let s: &'static str = concat!(stringify!($name), "\0");
280 let s: &'static ::std::ffi::CStr = ::std::ffi::CStr::from_bytes_with_nul_unchecked(s.as_bytes());
281 let s = $crate::validated::UCStr::from_literal_unchecked(s);
282 s
283 }
284 };
285 (@Return $return_type:ty
287 ) => ($return_type);
288 (@Return
290 ) => (());
291 {@Parameters [$f:ident, $d:ident, $a:ident $(,)?]
293 $frt:ident, $data:ident, $args:ident $(,)?
294 } => {
295 let $frt: &$crate::context::FlashRuntime<'a> = $f;
296 let $data: Option<&mut dyn ::std::any::Any> = $d;
297 let $args: &[$crate::types::Object<'a>] = $a;
298 };
299 {@Parameters [$f:ident, $d:ident, $a:ident $(,)?]
301 $frt:ident, $data:ident, _ $(,)?
302 } => {
303 $crate::function! {@Parameters [$f, $d, $a]
304 $frt, $data, _args
305 }
306 };
307 {@Parameters [$f:ident, $d:ident, $a:ident $(,)?]
309 $frt:ident, _, $args:ident $(,)?
310 } => {
311 $crate::function! {@Parameters [$f, $d, $a]
312 $frt, _data, $args
313 }
314 };
315 {@Parameters [$f:ident, $d:ident, $a:ident $(,)?]
317 _, $data:ident, $args:ident $(,)?
318 } => {
319 $crate::function! {@Parameters [$f, $d, $a]
320 _frt, $data, $args
321 }
322 };
323 {@Parameters [$f:ident, $d:ident, $a:ident $(,)?]
325 _, _, $args:ident $(,)?
326 } => {
327 $crate::function! {@Parameters [$f, $d, $a]
328 _frt, _data, $args
329 }
330 };
331 {@Parameters [$f:ident, $d:ident, $a:ident $(,)?]
333 _, $data:ident, _ $(,)?
334 } => {
335 $crate::function! {@Parameters [$f, $d, $a]
336 _frt, $data, _args
337 }
338 };
339 {@Parameters [$f:ident, $d:ident, $a:ident $(,)?]
341 $frt:ident, _, _ $(,)?
342 } => {
343 $crate::function! {@Parameters [$f, $d, $a]
344 $frt, _data, _args
345 }
346 };
347 {@Parameters [$f:ident, $d:ident, $a:ident $(,)?]
349 _, _, _ $(,)?
350 } => {
351 $crate::function! {@Parameters [$f, $d, $a]
352 _frt, _data, _args
353 }
354 };
355 (@Unwind [$frt:expr_2021, $catched:expr_2021]
357 ) => {
358 match $catched {
359 Ok(r) => r.into(),
360 Err(_) => {
361 let info = $crate::_internal::LAST_PANIC_INFO.with(|i| {i.borrow_mut().take()});
362 let msg = info.as_ref()
363 .map(|s|s.as_str())
364 .unwrap_or("Panic occurred but no details were captured.");
365 let err = $crate::types::ErrorObject::new($frt, Some(msg), i32::MIN);
366 err.set_name(Some($crate::types::StringObject::new($frt, "Native Extension Panic Error")));
367 err.into()
368 },
369 }
370 }
371}
372