Important note: at the moment this requires a couple of PRs:
dom typeThere is a new dom data type featuring a special notation. The type is accompanied by the dom module (see https://github.com/remixlabs/protoquery/wiki/stdlib-dom).
Values of type dom use a symbol table for storing the scalar (and sometimes non-scalar) values the DOM tree is composed of. These values are then simply referenced via indices into this table. The compiler understands a notation like
{ _rmx_type: "dom_group",
props: { style: { s1: v1, ... },
events: { e1: u1, ... },
p1: q1,
...
},
children: [ ... ]
}:dom
where the important part is the :dom suffix. There are also a couple of restrictions of this notation, see https://github.com/remixlabs/protoquery/wiki/stdlib-dom#the-dom-data-type for details.
Now, values of type dom are already represented as arrays of integers in Mix, and each of these integers is considered a symbol. When a cell of type dom is printed, the dom representation is converted back to conventional records, but this really happens only when printing cells. For example look at this REPL session:
> cell p = {_rmx_type:"foo"}:dom
p : dom
p = { _rmx_type: "foo" }
> p
$value = dom.domNode ([ [ 2139, 2051, 2051 ], [ ] ])
The cell printer automatically converts the value back, but when you look directly at the value, you’ll see the array encoding. At this point, this means that the new dom type is fairly backwards-compatible from the perspective of clients (because these only look at the printed cell values).
sync keywordThe other necessary ingredient is spreadsheet synchronization. You can mark cells with the sync keyword, like:
sync cell p = {_rmx_type:"foo"}:dom
We now require that the value on the right-hand side of a sync cell must have type dom. The sync keyword marks that the contents of this cell are synchronized to the client, i.e. the cell may appear in the special $sync messages that are used for this purpose in the track protocol. Whenever the contents of the cell change, the cell is automatically transmitted again.
Also, when a sync cell is used in another cell, the sync cell is only included by reference. In JSON notation such references look like { _rmx_type:"cell", index: <index> } where the index is the numeric index of the cell in the spreadsheet. The new dom data type also supports cell references (i.e. these can be encoded with symbols).
Now, the protocol is extended: The $sync messages transmit the contents of cells no longer as JSON values, but as arrays of symbols. This means that you need to enable synchronization in order to get the benefits of the DOM compression.
enable-sync$ rlwrap ./progs/mix_client -local-vm -no-libs -enable-sync
> sync cell p = {_rmx_type:"foo"}:dom
p : dom
$symbols = [ null, false, true, [ ], "", "dom_agenda", "dom_agendaItem", "dom_calendar", "dom_cameraPreview", "dom_datePeriod", "dom_datePicker", "dom_group", "dom_icon", "dom_intField", "dom_image", "dom_lottieView", "dom_map", "dom_mapMarker", "dom_markedDate", "dom_scrollGroup", "dom_statusBar", "dom_switch", "dom_text", "dom_textInput", "alignContent", "alignItems", "alignSelf", "backgroundColor", "borderBottomColor", "borderBottomLeftRadius", "borderBottomRightRadius", "borderBottomStyle", "borderBottomWidth", "borderColor", "borderLeftColor", "borderLeftWidth", "borderRadius", "borderRightColor", "borderRightWidth", "borderStyle", "borderTopColor", "borderTopLeftRadius", "borderTopRightRadius", "borderTopWidth", "borderWidth", "bottom", "color", "display", "flexBasis", "flexDirection", "flexGrow", "flexShrink", "flexWrap", "fontFamily", "fontSize", "fontStyle", "fontWeight", "height", "justifyContent", "left", "lineHeight", "name", "margin", "marginBottom", "marginLeft", "marginRight", "marginTop", "minHeight", "minWidth", "outline", "overflowX", "overflowY", "padding", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop", "placeholder", "position", "right", "shadowColor", "shadowOffset", "shadowOpacity", "shadowRadius", "textAlign", "textDecorationLine", "top", "type", "value", "width", "zIndex", "foo" ]
$sync = [ "view-0", 3, [ 2139, 2051, 2051 ] ]
$sync = [ "view-0" ]
$syncSwitch = "view-0"
p = { _rmx_type: "cell", index: 3 }
> sync cell q = {_rmx_type:"bar", children:[p]}:dom
q : dom
$symbols = [ "bar" ]
$sync = [ "view-0", 4, [ 2140, 2051, 2051, 1, 5, 19, 0, 3 ] ]
$sync = [ "view-0" ]
$syncSwitch = "view-0"
q = { _rmx_type: "cell", index: 4 }
As you can see, p (index 3) and q (index 4) are now both printed as cell reference. The contents of the cell are put into $sync only.