1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//! Dynamic, term-carrying [`Actor`] for untyped hosts (WR-8).
//!
//! [`super::Actor`] is generic over associated `Call`/`Reply`/`Cast` types, but a
//! JavaScript host is untyped: it hands the VM a request value and awaits a reply
//! value. [`DynActor`] bridges that gap. Its `Call`/`Reply`/`Cast` are all the
//! same opaque payload — a [`WireTerm`], an `Arc`-shared [`OwnedTerm`] graph — so
//! a request marshalled from a host value (e.g. a `JsValue` via the `beamr-wasm`
//! term codec) crosses the actor boundary unchanged, and the reply the actor
//! produces crosses back the same way.
//!
//! The reply is computed by a pure [`ReplyFn`] transform supplied at spawn time:
//! `Fn(&OwnedTerm) -> OwnedTerm`. The transform is `Send + Sync + 'static` so it
//! is captured by the restart-capable spawn factory exactly like any other
//! actor; a host (such as `beamr-wasm`) supplies a transform that invokes a
//! registered host callback to compute the reply, and a native test supplies a
//! plain Rust transform. The actor itself reuses the WR-6 envelope machinery
//! verbatim — it is just an [`super::Actor`] whose message types happen to be
//! opaque terms — so [`super::CoopSenderHandle::call_async`] / its
//! [`super::CallFuture`] drive it with no new correlation, timeout, or wire code.
//!
//! # Term marshalling
//!
//! On the wire a [`WireTerm`] is the term graph itself. [`WireTerm::encode`]
//! deep-copies the owned graph onto the running process heap via
//! [`super::super::native_process::NativeContext::alloc_owned_term`];
//! [`WireTerm::decode`] deep-copies the received heap term back into a fresh,
//! self-contained [`OwnedTerm`] via [`copy_term_to_ets`]. Both reuse the same
//! deep-copier ETS delivery uses, so no term ever dangles across the boundary.
use Arc;
use ;
use crate;
use crateNativeContext;
use crateTerm;
/// A pure transform from a request term graph to a reply term graph.
///
/// `Send + Sync + 'static` so it can be captured by the restart-capable native
/// spawn factory (Decision: the dynamic actor is restart-capable like any other).
pub type ReplyFn = ;
/// An opaque term payload that crosses the dynamic actor boundary.
///
/// `Arc<OwnedTerm>` so it is `Clone` (the [`ActorMessage`] bound) without copying
/// the graph, and `Send + Sync + 'static` so a captured request survives a
/// restart factory.
;
/// A dynamic actor: every inbound call/cast term is run through `reply` and the
/// resulting term is returned (calls) or discarded (casts).