Add reusable SVG JavaScript runtime#519
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f597c51f36
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cab4e698fd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ef65638484
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7ee7479c3a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d85e7a69f7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6f1d684fac
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ebac8ff08e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7bacb8c296
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f0b452b7d3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1b7c014606
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f182408830
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8ec0f73c96
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2f38058bdf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9ef76f1694
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| foreach (var element in BuildRoute(target)) | ||
| { | ||
| animationFrameDirty |= svg?.RecordAnimationPointerEvent(element, eventType) == true; | ||
| var javaScriptResult = svg?.DispatchJavaScriptEvent(element, target, relatedElement, ToJavaScriptEventType(svgEventName), svgEventName, input, ref javaScriptEvent); |
There was a problem hiding this comment.
Dispatch JS capture listeners in pointer tunnel phase
Routed pointer events currently invoke JavaScript only in the target-to-root loop (svg.DispatchJavaScriptEvent(...)), while the tunnel pass (DispatchTunnelEvent) does not execute JavaScript listeners. In practice, listeners registered with addEventListener(..., true) never run for real pointer input (click/move/up/down), even though capture works for dispatchEvent, so capture-dependent handlers silently break in interactive scenarios.
Useful? React with 👍 / 👎.
| } | ||
|
|
||
| var nodes = new List<ISvgNode>(element.Children.Count * 2); | ||
| nodes.Add(new SvgContentNode { Content = "\n" }); |
There was a problem hiding this comment.
Remove synthetic newline nodes from use instance trees
GetChildNodes injects artificial "\n" text nodes when an element has multiple children but no explicit Nodes. That fabricates DOM children that were never present in the referenced content, so <use> instance traversal (firstChild, childNodes, sibling/index-based logic) can observe extra text nodes and incorrect ordering.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 866719d5a9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| InitializeJavaScriptRuntime(svgDocument); | ||
| InvalidateRetainedSceneGraph(); | ||
|
|
||
| var animationController = new SvgAnimationController(svgDocument); |
There was a problem hiding this comment.
Attach animation host before executing document scripts
LoadSvgDocument runs InitializeJavaScriptRuntime(svgDocument) before creating/replacing the new SvgAnimationController, and InitializeJavaScriptRuntime executes <script>/onload immediately. In that phase runtime.AnimationHost is still null, so animation DOM calls like beginElement()/beginElementAt() are dropped (SvgJavaScriptRuntime.BeginElement is a null-conditional no-op), which causes load-time script-driven animations to fail to start or schedule correctly.
Useful? React with 👍 / 👎.
| var eventType = NormalizeEventType(evt.type); | ||
| if (string.IsNullOrWhiteSpace(eventType)) | ||
| { | ||
| return true; |
There was a problem hiding this comment.
Throw on dispatchEvent when event type is uninitialized
DispatchEventCore treats an empty/whitespace event type as a successful dispatch and returns true, but this should be an invalid-state error for uninitialized events (for example, document.createEvent('Event') dispatched without initEvent). Returning success masks script errors and diverges from DOM behavior expected by callers that rely on the exception path.
Useful? React with 👍 / 👎.
PR Summary: Add Reusable SVG JavaScript Runtime
Title
Add reusable SVG JavaScript runtime
Related Issue
Addresses JavaScript and DOM support requested in issue #422.
Summary
This PR moves the JavaScript and DOM surface into a standalone
Svg.JavaScriptproject, keeps the host boundary reusable, and wires that runtime intoSvg.Skiafor rendering, hit-testing, animation, and mutation refresh.The branch now covers the full DOM-focused W3C SVG 1.1 JavaScript slice in this test harness, including animation DOM, path DOM, text DOM, scripted event handling,
useinstance dispatch, and browser-style geometry APIs. Performance was treated as a hard constraint: text DOM is exposed lazily over the real shaped layout path, animation DOM is integrated into the existing controller instead of adding a second timing engine, and benchmark checks againstmasterstayed flat or better on the affected hot paths.JavaScript remains opt-in at the library level. Consumers still need to enable it through the relevant shared
SKSvgSettingssurface or directly on anSKSvginstance. The Avalonia and Uno test apps now enable it by default so the runtime and DOM bridge can be exercised interactively.What Changed
Standalone
Svg.JavaScriptRuntimesrc/Svg.JavaScript.Svg.Skia.nodeValue,textContent,innerHTMLSVGPathSeg-style fixture supportsetTimeout/clearTimeout, including delayed callbacks and function handlersDOMExceptioncodes needed by the W3C rowsAnimation DOM
SVGAnimationElement/ElementTimeControlDOM behavior on top of the existing animation controller:beginElementbeginElementAtendElementendElementAtgetStartTime.begin/.endtiming and imperative begin/end scheduling.onbegin/onendand routed those callbacks back through the JavaScript runtime.Text DOM Over Real Layout
Svg.JavaScriptintoSvg.Skia.getComputedTextLengthgetNumberOfCharsgetSubStringLengthgetStartPositionOfChargetEndPositionOfChargetExtentOfChargetRotationOfChargetCharNumAtPositionselectSubStringSvg.Skia Integration
onloaduseinstance target routingRefreshFromSourceDocument()to rebuild rendered output after source-DOM mutation where needed.SKSvgSettings.CopyTo()/Clone()helpers and reused them fromSKSvg.Clone()so JavaScript, timeout, external-script, font, viewport, and color settings stay consistent whenever settings are copied.Control Settings Propagation And Samples
SKSvgSettingsinto everySKSvgcreated bySvg.Controls.Skia.Avalonia.SvgSource:SvgDocumentloadsSKSvgSettingsinto everySKSvgcreated byUno.Svg.Skia.SvgSourcethrough the same load paths.SkiaModelsettings surfaces for SvgML Avalonia, Uno, and MAUI inline controls, then applied those settings before each generated control load.samples/TestAppsamples/UnoTestAppCSS / Raw Value / Compatibility Behavior
styleattribute replacement/removalW3C Harness And Baselines
struct-dom-13-fgetIntersectionList()root-node assertion by filtering the W3C draft watermark overlay only for W3C suite fixtures, while preserving normal application documents that use adraft-watermarkgroup.W3C DOM Coverage
This branch turns on the remaining DOM-focused W3C rows exercised by the JavaScript runtime in this suite, including:
animate-dom-01-fanimate-dom-02-fanimate-script-elem-01-binteract-dom-01-bscript-handle-01-bscript-handle-02-bscript-handle-03-bscript-handle-04-bpaths-dom-01-fpaths-dom-02-fstruct-dom-12-bsvgdom-over-01-ftext-dom-01-ftext-dom-02-ftext-dom-03-ftext-dom-04-ftext-dom-05-fcoords-dom-01-fthroughcoords-dom-04-fmasking-path-09-bmasking-path-12-fscript-specify-02-fstruct-dom-06-bstruct-dom-07-fstruct-dom-13-fstruct-dom-16-fstruct-dom-17-fstruct-dom-18-fstruct-dom-19-fstruct-dom-20-fstruct-svg-01-fstruct-use-13-fstruct-use-14-fstruct-use-15-ftypes-dom-06-ftypes-dom-08-fCurrent DOM-focused W3C filter state on this branch:
47 passed0 skippedThe only JavaScript-related W3C row still explicitly skipped in this area is
script-specify-01-f, because the legacy baseline is stale and current Chrome is not a valid oracle for its obsoletecontentScriptTypebehavior.Perf Validation
Performance and memory usage were treated as release gates for this work.
Animation Benchmarks vs
masterAdvanceLayeredFrame 64/4:273 usvs283 usAdvanceLayeredFrame 64/16:1.495 msvs1.509 msAdvanceLayeredFrame 256/4:946 usvs1.104 msAdvanceLayeredFrame 256/16:4.800 msvs4.664 msThe only slight regression case was the highest-density
256/16run, and it stayed within normal short-run variance. The meaningful regression that showed up earlier during development was removed before landing this branch.Text Benchmarks vs
master+/-1%Verification
Validated on this branch with:
Additional focused runtime coverage was added for:
setTimeoutordering andclearTimeoutElementTimeControlsemanticsgetStartTimeinvalid-state behaviorSvgSourcepaths-dom-01-f/paths-dom-02-fsvgdom-over-01-fstruct-dom-07-f,struct-dom-13-f, andstruct-dom-18-fstruct-dom-13-fdocument-rootgetIntersectionList()length behavior with the W3C draft watermark overlay presentCommit Breakdown
Recent branch-top commits:
Fix W3C DOM intersection list watermarkEnable JavaScript in Uno test appPropagate SVG settings in SvgML controlsPropagate shared settings in Skia SVG sourcesAdd reusable SVG settings copy helpersAddress JavaScript DOM review commentsAdd W3C DOM performance implementation planEnable JavaScript in the test appEnable W3C DOM fixtures and capturesAdd DOM animation and text runtime supportEarlier foundation commits on the same PR established the standalone runtime extraction, parser/raw-value support, initial host integration, CSS compatibility fixes, broader DOM/runtime APIs, and the first wave of W3C coverage.
Risk And Follow-Up