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
//! View memoization.
//!
//! Wraps a view subtree in a `__memo__` marker node so the runtime
//! can reuse the previously-normalized subtree when the author-
//! supplied deps are unchanged.
//!
//! The view function still runs - `view(&model)` is pure, so
//! short-circuiting it would require thread-local trickery. What the
//! cache avoids is re-walking the subtree through normalization
//! (scope prefixing, a11y rewrites) and re-emitting patches for
//! unchanged subtrees downstream.
use DefaultHasher;
use ;
use PropMap;
use crateView;
/// Cache a view subtree by a stable key plus a set of hashable deps.
///
/// The `key` identifies the memo call site (one stable id per
/// distinct memo in the view tree). The `deps` are hashed on every
/// render; when the hash matches the previous render's, normalization
/// reuses the cached subtree instead of re-walking it.
///
/// ```ignore
/// column().children([
/// memo("header", (model.user_id, model.revision), || {
/// expensive_header_view(&model)
/// }),
/// text(&model.dynamic_text),
/// ])
/// ```
///
/// Any `Hash` deps work: a tuple, a single `&str`, a `u64`, a custom
/// type that derives `Hash`. Implementations should avoid hashing
/// floats unless they have deliberate bit-level semantics.
///
/// The `view_fn` always runs (the view function is pure; the SDK
/// can't know deps haven't changed without hashing them, which
/// requires calling the closure once and comparing after the fact).
/// The saving is downstream: normalization, tree diff, and renderer
/// apply all reuse the cached subtree on a hit.