Skip to main content

browser_commander/traces/
assets.rs

1//! The in-page code and viewer shared with JavaScript (issue #108).
2//!
3//! `assets.json` is generated by `scripts/generate-trace-assets.mjs` from
4//! `js/src/traces`, so the snapshot capture, the mutation recorder and the
5//! viewer that Rust ships are the same bytes JavaScript runs. It is parsed once.
6
7use std::sync::OnceLock;
8
9use serde::Deserialize;
10
11const ASSETS_JSON: &str = include_str!("assets.json");
12
13/// The in-page functions a recorder evaluates.
14#[derive(Debug, Clone, Deserialize)]
15#[serde(rename_all = "camelCase")]
16pub struct CaptureAssets {
17    /// `function captureSnapshotInPage(options)`.
18    pub capture_snapshot: String,
19    /// `function installMutationRecorderInPage(options)`.
20    pub install_mutation_recorder: String,
21    /// `function drainMutationsInPage(globalName)`.
22    pub drain_mutations: String,
23    /// `function stopMutationRecorderInPage(globalName)`.
24    pub stop_mutation_recorder: String,
25}
26
27/// The viewer's stylesheet and script.
28#[derive(Debug, Clone, Deserialize)]
29pub struct ViewerAssets {
30    /// The contents of the viewer's `<style>` element.
31    pub style: String,
32    /// The contents of the viewer's last `<script>` element.
33    pub script: String,
34}
35
36/// Everything in `assets.json`.
37#[derive(Debug, Clone, Deserialize)]
38#[serde(rename_all = "camelCase")]
39pub struct TraceAssets {
40    /// Says where the file comes from.
41    pub note: String,
42    /// The page global the mutation recorder lives under.
43    pub recorder_global: String,
44    /// The marker redacted values are replaced with.
45    pub redacted: String,
46    /// In-page functions.
47    pub capture: CaptureAssets,
48    /// Viewer stylesheet and script.
49    pub viewer: ViewerAssets,
50}
51
52/// The shared assets, parsed on first use.
53pub fn trace_assets() -> &'static TraceAssets {
54    static ASSETS: OnceLock<TraceAssets> = OnceLock::new();
55    ASSETS.get_or_init(|| {
56        serde_json::from_str(ASSETS_JSON).expect("rust/src/traces/assets.json is generated JSON")
57    })
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn assets_hold_the_in_page_functions() {
66        let assets = trace_assets();
67        assert_eq!(assets.recorder_global, "__browserCommanderTrace__");
68        assert_eq!(assets.redacted, super::super::redaction::REDACTED);
69        assert!(assets
70            .capture
71            .capture_snapshot
72            .starts_with("function captureSnapshotInPage(options)"));
73        assert!(assets
74            .capture
75            .drain_mutations
76            .starts_with("function drainMutationsInPage(globalName)"));
77        assert!(!assets.viewer.script.is_empty());
78    }
79}