Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
zigdom
lightpanda with a Zig-native DOM
Install
Needs cargo
Testing
Still a work in progress. But the test filter has been improved.
TEST_FILTER="..."or (make test F="...") can now run specific HTML file cases using the#partial_file_name:Prototype
The prototype system relies on two special fields. The
_protofield references the parent of a type. For example:Elementhas a_proto: *Nodefield,Nodehas a_proto: *EventTargetfield,EventTargethas no_protofieldGoing the other way, "parents" have a
_typefield which is a tagged union:As a convention, parents expose an
asmethod:As a convenience, children expose an
as$Ancestor, e.g.input.asElement()orinput.asNode(), although some code might simply accessinput._proto.Bonus: The special return union types, e.g.
Node.UnionorElement.Union, are no longer needed. You can return any part of the prototype chain. In other words, as far as the JS bridge is concerned, you can returninputorinput.asElement()orinput.asNode().Explicit JS Mapping
Naming conventions are no longer used to create the JS mapping. Every type that is mapped has a nested
JsApiandJsApi.Metastruct:A bit more tedious, but new APIs aren't added that often. Allows for having per-definition configuration (e.g. enabling DOMExceptions on individually methods, rather than the entire type). Can also result in more idiomatic Zig code. For example,
Element.innerHTMLis able to take an *Io.Writer, with the mapper providing a wrapper:Consistent DOM handling
Whether an element is created by the parser or via
document.createElement, the same code path is taken (as much as possible). This creates more consistency, e.g. in setting theselect.selectedIndex. Individual DOM elements can opt-into build callbacks. For example Input.zig gets "created" events:Naming Convention
Underscore fields names are used throughout the WebAPI in large part to avoid naming conflicts. Structs-as-a-file is used extensively, and field names are more likely to cause conflicts in this setup.
In non WebAPI classes (e.g. the Page), they are used as "private" markers. Within the project, there's now a clear "lightpanda" library, and I'm starting to think about what should and shouldn't be exposed from the library.
Memory
This branch was born from an experiment that used a hybrid memory management - arenas for DOM objects and reference counting for other types (e.g. XHR objects). Some of this complexity is retained (
page._factory), despite everything using eitherpage.arenaorpage.call_arena. I'm hopeful that some explicit memory management can be re-added in the future (XHR objects can hold onto large amounts of memory) - but right now, it's worthless complexity.Note 1
In both
mainandzigdom, most types that are returned to JavaScript are placed on the heap. The JS bridge handles this. Sozigdomisn't putting more objects on the heap thanmain, it's just being more explicit about it.Note 2
Values of the
_typeunion are almost always pointers. The only exception are 8-byte leaf nodes (i.e. leaf nodes that only have a_proto: *Parentfield) which can be directly embedded into the union.There's a real tradeoff here. But in general, zigdom aims for memory efficiency at the cost of performance and, in this case, potential fragmentation (which I'm hoping can be solved by a smarter allocation strategy). This is clearly generating many more small allocations than libdom was.