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
//! A page can nest calls as deeply as a browser lets it.
//!
//! Boa's defaults are a sandbox's: 512 nested calls, and a value stack of
//! 10240 slots that runs out first at roughly seven slots a frame. Neither
//! number is reachable by anything a page author would recognise as recursion.
//! A framework spends the frames instead: a Solid application renders its
//! component tree as nested calls and threads each one through the reactive
//! graph's owner chain, so depth grows with how deeply the page is nested.
//!
//! Measured on support.cafe, driven headlessly: the home page renders, and
//! following the link to `/login` throws
//!
//! RuntimeLimitError: reached the maximum number of recursive calls
//!
//! part-way through the render, leaving a fragment of a page. Nothing in the
//! route recurses; it is simply deeper than 512 frames.
//!
//! The error is also not catchable. It unwinds the whole execution rather than
//! arriving as a JavaScript exception, so a page's own error boundary cannot
//! report it and the only trace is a line in the host's log. That is why the
//! depth is measured here in two steps: the recursion runs in one evaluation
//! and the deepest frame it reached is read back in another.
use ScriptDocument;
/// The deepest frame a plain recursive function reaches before the engine
/// stops it.
/// The number this exists for.
///
/// A lower bound rather than an equality, so the test says what a page needs
/// rather than restating the constant beside it. 4000 is comfortably past what
/// the fleet's deepest route was measured to want and comfortably under the
/// 8192 configured, which leaves room to tune either limit without rewriting
/// the test.
/// Still a limit, and still a clean one.
///
/// The point of raising the ceiling is not to remove it. Runaway recursion has
/// to stop with an error rather than by exhausting the machine, and the value
/// stack has to be large enough that the call limit is what stops it: with only
/// the call limit raised, the stack ran out first at 1462 frames and reported
/// "reached the maximum stack size", which names the wrong thing.