oxc-project / oxc-project/backlog

AST: Remove Elision type.

Open
#244 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
No language data
Stars
7
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Summary

Represent array holes as None entries in ArrayExpression::elements and remove the synthetic Elision AST node and enum variant.

An elision is the absence of an array element between commas. Modeling absence as a boxed node gives it identity, span, visitor callbacks, and builder APIs that do not correspond to an ESTree node or a runtime expression.

Motivation

Sparse arrays contain holes:

[,]
[1, , 3]
[1, ,]

Oxc currently creates ArrayExpressionElement::Elision(Box<Elision>) for each hole.

The current representation permits artificial states and unnecessary work:

  • an Elision value can be constructed outside an array;
  • a hole owns a NodeId even though there is no syntax node to reference semantically;
  • visitors and transforms must handle an otherwise empty node;
  • consumers repeatedly call is_elision() and branch inside the element enum;
  • every hole requires a boxed arena allocation.

A trailing comma is not itself an extra hole. The vector representation must continue to distinguish [1,] from [1,,] using the parser's delimiter/trailing-comma tracking.

Current AST Shape

pub struct ArrayExpression<'a> {
    pub node_id: Cell<NodeId>,
    pub span: Span,
    pub elements: Vec<'a, ArrayExpressionElement<'a>>,
}

pub enum ArrayExpressionElement<'a> {
    SpreadElement(Box<'a, SpreadElement<'a>>) = 64,
    Elision(Box<'a, Elision>) = 65,
    INHERIT(Expression<'a>),
}

#[estree(via = Null)]
pub struct Elision {
    pub node_id: Cell<NodeId>,
    pub span: Span,
}

The parser creates an Elision when the current token is a comma inside an array element list.

Proposed AST Shape

pub struct ArrayExpression<'a> {
    pub node_id: Cell<NodeId>,
    pub span: Span,
    pub elements: Vec<'a, Option<ArrayExpressionElement<'a>>>,
}

pub enum ArrayExpressionElement<'a> {
    SpreadElement(Box<'a, SpreadElement<'a>>) = 64,
    INHERIT(Expression<'a>),
}

The parser pushes None for a comma that denotes a hole and Some(element) for expressions and spreads. Delimiter logic remains responsible for trailing commas so [1,] produces one Some entry while [1,,] produces Some(1), None.

ESTree serialization maps None to null in the elements array. Visitors skip None. Formatter and codegen use element indexes and delimiter metadata rather than an elision span; comments remain attached to surrounding tokens/nodes according to the existing comment model.

Syntax Mapping

Source form Current representation Proposed representation
[] Empty vector Empty vector
[1] [NumericLiteral(1)] [Some(NumericLiteral(1))]
[,] [Elision] [None]
[1, , 3] [1, Elision, 3] [Some(1), None, Some(3)]
[1,] [1] plus trailing-comma metadata [Some(1)] plus trailing-comma metadata
[...xs] [SpreadElement] [Some(SpreadElement)]

Guaranteed Invariants

  • A hole is represented as the absence of an array element, not a standalone AST node.
  • ArrayExpressionElement always contains an actual expression or spread.
  • Trailing commas remain distinct from holes.
  • ESTree null entries map directly to None.
  • Traversal does not allocate IDs or invoke callbacks for nonexistent elements.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the parser's array-element handling and trace the ArrayExpressionElement consumers named in the issue: ESTree serialization, visitors, formatter, and codegen. Replace elision entries with None while preserving delimiter and trailing-comma behavior, then verify the listed syntax mappings and invariants, including null ESTree entries and skipped visitor callbacks.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.