Fix invoking JavaScript with C# DOM arguments - #127
Conversation
|
Quick question @lahma: Is this ready or is there anything I can help with / contribute to? BTW: Many thanks - you are my hero 🦸 ! |
|
I'm doing some review rounds for optimal solution, this is on the hot path. Stay tuned!
Happy to help ❤️ |
|
Just FYI - after this all issues are essentially gone. My plan is to introduce some more tests (WPT), round it all up and then have the 1.0.0 (until Thursday, or earlier). This is, of course, not the end of AngleSharp.Js (I rather think this is all the beginning...), but its a major milestone and a massive step forward. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Awesome. I'm building a new version v4.15 of Jint and the big headline is making interop easier and faster. You project is one of the explored integrators so I will have one PR shaping the "optimal" integration soon'ish. Release preparations take time so it might be today or tomorrow... |
|
The fix was here a bit more complex than the first try, so ready for review now. |
FlorianRappl
left a comment
There was a problem hiding this comment.
Awesome - life goal achieved 🥇
Many thanks for all the hard work.
Fixes #76
Cause
JsValue.FromObjectis the conversion a C# caller reaches, and it is the one path that does not go throughEngineExtensions.ToJsValue. Jint therefore wrapped an AngleSharp DOM object in its ordinary CLRObjectWrapperrather than in the DOM proxy, and that wrapper is opaque to this library's own marshalling:JsValueExtensions.FromJsValueonly unwraps aDomNodeInstance, so the argument came back out as the wrapper itself,AsComplexfound no conversion fromObjectWrappertoINode, and the call died withJavaScriptException: [Internal] Could not find corresponding cast target.— the exception reported in the issue. Short of that, script also saw the CLR member surface (TextContent,AppendChild) instead of the DOM one, and the object was not the onedocument.querySelectorhands back for the same node.Fix
EngineInstanceinstalls a JintWrapObjectHandler, the hook Jint consults whenever it wraps a CLR object. An object that resolves to a DOM name is converted withGetDomNode, so it goes through the sameReferenceCachethe rest of the engine uses and one node keeps one JS object no matter which side hands it over. Everything else keeps Jint'sObjectWrapper, which is what a host object registered throughJsScriptingService.Externalis expected to be.PrototypeTypeCache.IsDomTypeis what decides, caching the answer per type since it depends on the type alone. The name may be inherited — abelement answers true throughHTMLElement, which is exactly what makes the DOM view the right one for it — but a bareEventTargetis not enough: AngleSharp hangsHtmlParser,BrowsingContextand the requesters off the very same base class, and those are host objects that have to keep their CLR members.Behaviour change
An AngleSharp DOM object registered in
JsScriptingService.Externalnow reaches script as the DOM object rather than as a CLR wrapper, so script usesdoc.querySelector(…)where it previously useddoc.QuerySelector(…). A collection handed over from C# likewise becomes the DOM collection, which means the array-like conveniences Jint's wrapper gave it (Symbol.iterator, theArray.fromfast path) no longer apply — the same gap collections obtained from script already have. Host objects that are not part of the DOM are untouched.Tests
InteractionTestscovers the issue's repro, the DOM member surface on a C#-created element, the JS identity of one node across the C# and the script path, and that a non-DOM AngleSharp host object keeps its CLR members.