Donner SVG 0.8.0-pre
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
ReproFile.h File Reference

Data model for a .donner-repro file: a recorded sequence of editor UI inputs (mouse events, keyboard events, wheel events, window resizes) plus enough session metadata to re-instantiate the editor and replay the events deterministically. More...

#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
Include dependency graph for ReproFile.h:
This graph shows which files directly or indirectly include this file:

Classes

struct  donner::editor::repro::ReproViewport
 Snapshot of the editor viewport used to map window coordinates into SVG-document coordinates. More...
struct  donner::editor::repro::ReproHit
 Hit-test checkpoint captured at mouse-down time. More...
struct  donner::editor::repro::ReproAction
 One semantic editor action that fired within a frame. MCP-generated repros use actions for deterministic operations that are not raw pointer input, such as selecting the Pen tool or changing active paint. More...
struct  donner::editor::repro::ReproEvent
 One discrete event that fired within a frame. Frame-state (mouse position, button mask) lives on the owning frame record; this captures only events that can't be reconstructed from continuous state (key presses, character input, wheel deltas, resizes). More...
struct  donner::editor::repro::ReproFrame
 One frame's snapshot: continuous input state + any discrete events that fired during the frame. More...
struct  donner::editor::repro::ReproExpectedCrop
 Optional pixel crop attached to a replay expectation. More...
struct  donner::editor::repro::ReproExpectation
 Human-reviewed expectation metadata for important replay fixtures. More...
 Session-level metadata captured at recording start. More...
struct  donner::editor::repro::ReproFile
 In-memory form of a loaded or in-progress recording. More...
struct  donner::editor::repro::ReproReplaySecurityPolicy
 Ambient capabilities granted while replaying an untrusted recording. More...
struct  donner::editor::repro::ReproSvgFile
 SVG source loaded from a replay-relative path. More...

Namespaces

namespace  donner
 Top-level Donner namespace, which is split into different sub-namespaces such as donner::svg and donner::css.

Enumerations

enum class  donner::editor::repro::ReproExpectationProofKind {
  PresentedPixels ,
  ActiveDragAlignment ,
  Selection ,
  WorkerLiveness
}
 What a curated replay fixture is expected to prove.

Functions

std::string donner::editor::repro::ReproSvgDisplayName (const ReproMetadata &metadata)
 Return a bounded display-only name for replay SVG metadata without constructing a native path.
bool donner::editor::repro::IsSafeReproSvgPath (std::string_view path)
 Returns whether a recorded SVG path is a safe replay-directory-relative path.
std::optional< ReproSvgFiledonner::editor::repro::ReadReproSvgFile (const std::filesystem::path &rnrPath, std::string_view recordedSvgPath)
 Read a recorded SVG through a descriptor-rooted sandbox beneath the replay directory.
bool donner::editor::repro::WriteReproFile (const std::filesystem::path &path, const ReproFile &file)
 Serialize file to the given path in NDJSON form. Returns true on success; on failure writes an error message to stderr and returns false. Atomic: writes to path.tmp then renames over path, so a crash mid-write never truncates an existing file.
std::optional< ReproFiledonner::editor::repro::ParseReproFile (std::string_view contents)
 Parse an in-memory NDJSON repro document.
std::optional< ReproFiledonner::editor::repro::ReadReproFile (const std::filesystem::path &path)
 Parse an NDJSON repro file. Returns std::nullopt on any error (file missing, version mismatch, malformed line); writes details to stderr. When reading a v1 file, the v2-only fields stay default-constructed.

Variables

constexpr int donner::editor::repro::kReproFileVersion = 4
 File format version written by the current serializer.
constexpr size_t donner::editor::repro::kMaximumReproFileSize = 64 * 1024 * 1024
 Maximum accepted .donner-repro file size.
constexpr size_t donner::editor::repro::kMaximumReproMetadataLineBytes = 32 * 1024 * 1024
 Maximum accepted metadata-line size, including an embedded SVG snapshot.
constexpr size_t donner::editor::repro::kMaximumReproFrameLineBytes = 2 * 1024 * 1024
 Maximum accepted frame-line size.
constexpr size_t donner::editor::repro::kMaximumReproActionPropertyValueBytes = 64 * 1024
 Maximum decoded bytes accepted for one semantic action property value.
constexpr size_t donner::editor::repro::kMaximumReproRetainedStringBytes = 24 * 1024 * 1024
 Maximum aggregate decoded string bytes accepted while parsing one replay.
constexpr size_t donner::editor::repro::kMaximumReproScanWorkBytes = 128 * 1024 * 1024
 Maximum aggregate structural scan work accepted while parsing one replay.
constexpr size_t donner::editor::repro::kMaximumReproFrames = 10'000
 Maximum number of frames accepted from one replay file.
constexpr size_t donner::editor::repro::kMaximumReproPlaybackFrames = 1'024
 Maximum number of frames that one untrusted replay may execute.
constexpr size_t donner::editor::repro::kMaximumReproPixelFrames = 128 * 1024 * 1024
 Maximum aggregate physical-pixel frames that one replay may request.
constexpr size_t donner::editor::repro::kMaximumParsedReproPixelFrames = 8ULL * 1024 * 1024 * 1024
 Maximum aggregate physical-pixel frame metadata accepted while parsing one replay.
constexpr size_t donner::editor::repro::kMaximumReproItemsPerFrame = 1'024
 Maximum number of actions or events accepted in one frame.
constexpr size_t donner::editor::repro::kMaximumReproItems = 100'000
 Maximum combined number of actions and events accepted from one replay file.
constexpr int donner::editor::repro::kMaximumReproDimension = 8'192
 Maximum accepted logical window dimension in replay metadata and resize events.
constexpr int donner::editor::repro::kMaximumReproPixelDimension = 8'192
 Maximum accepted physical-pixel dimension derived from replay metadata.
constexpr size_t donner::editor::repro::kMaximumReproPixels = 16 * 1024 * 1024
 Maximum accepted physical-pixel area derived from replay metadata (64 MiB RGBA).
constexpr double donner::editor::repro::kMaximumReproDevicePixelRatio = 4.0
 Maximum accepted device-pixel ratio in replay metadata and viewport snapshots.
constexpr double donner::editor::repro::kMaximumReproDurationSeconds = 30.0
 Maximum accepted duration of a paced replay.
constexpr double donner::editor::repro::kMaximumReproDeltaMilliseconds = 5'000.0
 Maximum accepted time step for one replay frame.
constexpr int donner::editor::repro::kMaxMouseButtons = 5
 Maximum number of mouse buttons recorded. Matches ImGui's ImGuiMouseButton_COUNT.
constexpr ReproReplaySecurityPolicy donner::editor::repro::kUntrustedReproReplaySecurityPolicy {}
 Security policy applied by all untrusted replay entry points.
constexpr std::size_t donner::editor::repro::kMaximumReproSvgPathBytes = 4096
 Maximum byte length accepted for a replay-relative SVG path.
constexpr std::size_t donner::editor::repro::kMaximumReproSvgPathComponents = 256
 Maximum number of components accepted for a replay-relative SVG path.

Detailed Description

Data model for a .donner-repro file: a recorded sequence of editor UI inputs (mouse events, keyboard events, wheel events, window resizes) plus enough session metadata to re-instantiate the editor and replay the events deterministically.

The file records at the raw ImGui-input level (below menu action dispatch, below tool dispatch, below the compositor) so every stage of the stack - from Donner's DOM mutations down through the RendererTinySkia pixel ops - is exercised during playback. That breadth is the point: a recording made in the live editor reproduces the bug regardless of which layer it lives in.

Format is one JSON object per line (NDJSON):

{"v":3,"svg":"path.svg","svg_base":"path.svg","svg_hash":"fnv1a64:...",
"svg_src":"<svg>...</svg>","wnd":[1600,900],"scale":2.0,"exp":false}
{"f":0,"t":0.0,"dt":16.6,"mx":100.5,"my":50.2,"btn":0,"mod":0,
"mdx":12.4,"mdy":33.1,
"vp":{"ox":560,"oy":22,"pw":1040,"ph":878,"dpr":2,
"z":1.0,"pdx":446,"pdy":256,"psx":1080,"psy":461,
"vbx":0,"vby":0,"vbw":892,"vbh":512}}
{"f":1,"t":16.6,"dt":16.7,"mx":120.0,"my":50.0,"btn":1,"mod":0,
"e":[{"k":"mdown","b":0,"hit":{"id":"lightning","tag":"g"}}]}
...

Frame records carry the full mouse state plus any discrete events that fired during that frame. Discrete events are keyed by short type codes:

code meaning fields
mdown mouse button down b (button index 0-4), hit{}
mup mouse button up b
kdown keyboard key down k (ImGui key enum), m (mods)
kup keyboard key up k, m
chr character input c (UTF-32 code point)
wheel mouse wheel dx, dy (float units)
resize window resize w, h
focus window focus change on (0/1)

The "frame record" itself captures the continuous state (mouse position + current button mask) so a dropped event in the discrete list can't leave the player in an inconsistent state - the next frame's state trumps.

Since v2 the frame record can also carry:

  • mdx / mdy: mouse position in SVG-document coordinates
  • vp: a snapshot of the editor viewport at record time
  • mdown.hit: the element under the cursor at mouse-down time

Since v3 the metadata line can also carry a deterministic snapshot of the initial SVG source:

  • svg_base: basename of the originally opened filename
  • svg_hash: stable content hash of svg_src
  • svg_src: optional embedded SVG source text

Since v4 frame records can also carry semantic editor actions:

  • a: ordered action objects for tool/paint operations that are not raw pointer input.

Function Documentation

◆ IsSafeReproSvgPath()

bool donner::editor::repro::IsSafeReproSvgPath ( std::string_view path)
nodiscard

Returns whether a recorded SVG path is a safe replay-directory-relative path.

Absolute paths, empty paths, and any parent-directory component are rejected. This validation is also applied while parsing legacy replay metadata that lacks an embedded SVG snapshot.

Parameters
pathRecorded path from replay metadata.
Returns
True when the path is safe for replay-directory-relative resolution.

◆ ReadReproSvgFile()

std::optional< ReproSvgFile > donner::editor::repro::ReadReproSvgFile ( const std::filesystem::path & rnrPath,
std::string_view recordedSvgPath )
nodiscard

Read a recorded SVG through a descriptor-rooted sandbox beneath the replay directory.

Symlinks and other filesystem objects that could escape or block the read are rejected. Explicit caller-supplied SVG overrides do not use this function and remain unrestricted.

Parameters
rnrPathPath to the replay file.
recordedSvgPathReplay metadata path, relative to the replay directory.
Returns
The bounded SVG source and resolved path, or nullopt on any containment/read failure.

◆ ReproSvgDisplayName()

std::string donner::editor::repro::ReproSvgDisplayName ( const ReproMetadata & metadata)
nodiscard

Return a bounded display-only name for replay SVG metadata without constructing a native path.

Directory components, absolute roots, invalid UTF-8, and embedded NULs are discarded. The returned value is informational only and must not be used as a current/save path.

Variable Documentation

◆ kMaximumParsedReproPixelFrames

size_t donner::editor::repro::kMaximumParsedReproPixelFrames = 8ULL * 1024 * 1024 * 1024
constexpr

Maximum aggregate physical-pixel frame metadata accepted while parsing one replay.

Parsing does not allocate a surface per frame. This larger, still finite ceiling preserves compatibility with archived recordings that callers compact before playback; execution always enforces the stricter kMaximumReproPixelFrames limit.

◆ kReproFileVersion

int donner::editor::repro::kReproFileVersion = 4
constexpr

File format version written by the current serializer.

The reader accepts:

  • v1: legacy files with window-space mouse data only
  • v2: adds doc-space mouse coords, viewport snapshots, and mouse-down hit-test checkpoints
  • v3: adds optional embedded SVG source snapshots
  • v4: adds semantic frame actions (a)