Skip to content

NAPI Serialization for Nodes #466

@OmarTawfik

Description

@OmarTawfik

First reported by @antico5

On Rust, our types do have [serde] attributes for serialization. But on TS side, the types are properties that cannot be JSON.stringify()ied or visualized easily. One workaround is to do:

console.log(
  util.inspect(parseTree, {
    getters: true,
    showHidden: true,
    showProxy: true,
    depth: Infinity,
  })
);

Which produces something like:

RuleNode {
  kind: [Getter: 93],
  range: [Getter] [ 0n, 170n, [length]: 2 ],
  rangeIncludingTrivia: [Getter] [ 0n, 170n, [length]: 2 ],
  type: [Getter: 0]
}

But that is not enough. To make it easier for developers to use this, we can do two things:

One: JSON serialization

  • Expose the [serde] JSON serialization/deserialization through TypeScript APIs on each node. Example:
    • node.toJSON() -> string
    • Node.fromJSON(string) -> Node
  • Expose TypeScript types for the RAW nodes (plain object fields instead of properties), to make it easy to share the CST nodes with other consumers, without having to rely on Slang NAPI boundary to interact with them.

Two: Debugger Visualization

They also reported having to implement their own serialization just to visualize the tree. Example:

Rule: SourceUnit "// SPDX-License-I..."
  Rule: _REPEATED "// SPDX-License-I..."
    Rule: Directive "// SPDX-License-I..."
      Rule: PragmaDirective "// SPDX-License-I..."
# ... redacted

However, instead of leaving it up to users, we can also provide such API, especially that we already have an internal one for unit tests snapshots:

- MappingType (Rule): # 0..30 "mapping(string => bytes32 Bar)"
- MappingKeyword (Token): "mapping" # 0..7
- OpenParen (Token): "(" # 7..8
- MappingKeyType (Rule): # 8..14 "string"
- ElementaryType (Rule): # 8..14 "string"
- StringKeyword (Token): "string" # 8..14
- EqualGreaterThan (Token): "=>" # 15..17
- MappingValueType (Rule): # 18..29 "bytes32 Bar"
- TypeName (Rule): # 18..25 "bytes32"
- ElementaryType (Rule): # 18..25 "bytes32"
- FixedBytesType (Token): "bytes32" # 18..25
- Identifier (Token): "Bar" # 26..29
- CloseParen (Token): ")" # 29..30

We can probably expose this for both Rust and TypeScript, as a public API, with explicitly warning users that this is for dev-time visualization only, and its structure is subject to change at any time.

An additional benefit to this is that TypeScript will be able to generate the same visualization as Rust, unblocking #439

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions