Commit 02f139c
committed
Add bail-out handler API for flushing buffered state on graceful bail-out.
Graceful bail-out (`MemoryLimitExceeded` or `ContentHandlerError` with the
matching flag on) flushes the unparsed input remainder raw to the sink and
propagates the error. That is enough for handlers that only transform tokens
they see, but handlers that buffer state across the document (e.g. ROFL's
email-obfuscation module, which holds up to ~128 chars in a text buffer while
deciding whether they belong to an email) lose that state on bail-out and
produce a response with a gap.
This commit adds a hook that fires once on a graceful bail-out, immediately
before the raw flush, and lets handlers append final bytes to the sink:
1. New rewritable unit `BailOut` with a single method
`append(content, content_type)`, modelled after `DocumentEnd::append`. The
wrapper carries the rewriter's current encoding (after any
`<meta charset>`-driven change), so encoding-correctness is automatic.
2. New builder method `Settings::append_bail_out_handler` (and the
`RewriteStrSettings` mirror) plus `bail_out!` macro for type-hint
ergonomics, parallel to the existing `element!` / `end!` macros.
3. `HandlerTypes` grows a `BailOutHandler<'h>` associated type, with
`LocalHandlerTypes` aliasing `BailOutHandler<'h>` and `SendHandlerTypes`
aliasing `BailOutHandlerSend<'h>`. Matching `IntoHandler` impls cover both
bare-closure cases.
4. `TransformController` grows a `handle_bail_out` method with an empty
default impl so existing implementors (test fixtures, parser-trace tool)
keep compiling. `HtmlRewriteController` overrides it to iterate the
user-registered handlers in registration order.
5. `Dispatcher::run_bail_out_handlers` constructs the `BailOut` wrapper and
delegates to the controller. It is invoked from every existing graceful
bail-out site in `TransformStream::write()` (3 sites: `Arena::append`,
`Parser::parse`, `Arena::init_with`) and `TransformStream::end()` (1 site),
gated on `should_bail_out_for(&err)`. Hook output therefore lands in the
sink as `[transformed prefix] + [hook output] + [raw remainder]`.
6. `RewritingError` is marked `#[non_exhaustive]` so we can add variants in
future minor releases. `match`es still work; only exhaustive external
matches need a catch-all arm.
The `end()` bail-out site is defensive: it is symmetric with the `write()`
sites but is not reachable through normal input. EOF-in-tag / -attribute /
-comment emits as text per HTML5, so content-handler errors don't fire from
`parser.parse(_, true)`, and memory errors fire earlier in `write()`. Tested
implicitly via the shared call path.1 parent ba25359 commit 02f139c
9 files changed
Lines changed: 517 additions & 21 deletions
File tree
- src
- rewritable_units
- rewriter
- transform_stream
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
14 | 25 | | |
15 | 26 | | |
16 | 27 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
41 | 41 | | |
42 | 42 | | |
43 | 43 | | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
59 | | - | |
60 | | - | |
61 | | - | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
62 | 63 | | |
63 | 64 | | |
64 | 65 | | |
| |||
95 | 96 | | |
96 | 97 | | |
97 | 98 | | |
98 | | - | |
| 99 | + | |
99 | 100 | | |
100 | 101 | | |
101 | 102 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | 10 | | |
| |||
83 | 84 | | |
84 | 85 | | |
85 | 86 | | |
| 87 | + | |
86 | 88 | | |
87 | 89 | | |
88 | 90 | | |
| |||
0 commit comments