Skip to content

fix!: reject optional and arrow constructors - #74

Merged
exKAZUu merged 5 commits into
mainfrom
fix/constructor-primary-syntax
Oct 6, 2026
Merged

exKAZUu merged 5 commits into
mainfrom
fix/constructor-primary-syntax

Conversation

@exKAZUu

@exKAZUu exKAZUu commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Close #57

Why

Standalone new foo?.bar() and new () => 1 currently produce successful trees although JavaScript rejects them. Restricting constructor syntax must preserve the canonical constructor supertype query and valid nested new grouping.

Requirements

  • required: Review our repositories and issues, plus upstream major issues, PRs and new commits, for worthwhile grammar improvements.
  • required: Check existing PRs to prevent duplicates and create a separate PR for each eligible repair worth addressing.
  • required: Run review-booster and complete-pr simultaneously for each PR, then release.
  • required: Reject unparenthesized arrows and optional chains outside constructor parentheses; retain parenthesized optional constructors and nested new grouping (issue fix: reject optional constructors without breaking supertype queries #57).
  • required: Preserve existing constructor supertype query compilation and captures, including (new_expression constructor: (primary_expression) @constructor).
  • required: Preserve existing public nodes, fields, ranges, query captures and incremental parsing except the requested correction; preserve primary and other owners' checkouts.
  • required: Keep source grammar and external scanner consumers synchronized.
  • chosen: Use restricted constructor and nonoptional chain rules aliased to canonical public nodes and primary_expression, with hidden subset supertypes. A filtered subset without canonical aliases loses the required constructor query; copying arbitrary parenthesized expressions or scanning complete nested JavaScript would duplicate unrelated syntax.
  • chosen: Append ARGUMENTLESS_NEW_END at index 33 after the 33 incoming tokens. Mark the zero-width end before non-skipping trivia and reject following arguments, member/index/tag continuations and optional chains; keep ?.decimal conditional syntax. Honor trivia REJECT as a non-comment slash boundary before inspecting the division operand; all 36 division controls retain baseline full trees/captures, including 30 clean and 6 ERROR cases. Four added public division controls fail on d3 and pass after the guard. Preserve old scanner lifetime/state/serialization and suppress the marker in all-token recovery. Precedence alone also accepts invalid chains by ending new early, so a token boundary is necessary; no new serialized state is introduced.
  • chosen: Require generator/native/web runtime 1.2.2, while retaining ABI 15 and the public node schema. Actual web 1.0.16 loads the parser but fails the required constructor supertype query with BadPatternStructure; 1.2.2 compiles and captures it. This is a breaking runtime/source-protocol release: downstream grammar extensions need new conflicts and matching scanner indices; unchanged current TypeScript generation actually fails at _constructor_atom/_type_arguments_target, and its old scanner has no appended JS marker. Existing TypeScript remains pinned to the old parent; its port is a separate repair.
  • chosen: Retain Node-accepted incoming import-call member constructors; 32 Node/Acorn acceptance disagreements are explicit and not evidence of universal standard validity. Canonical aliasing corrects 16 incoming-clean yield.C constructors from yield_expression to identifier, confirmed by Node and Acorn ASTs. Keep the existing context-agnostic identifier policy: 432 strict/async/generator/class controls retain all 308 compiler-accepted parses, while 15 rejected yield contexts become parser-clean and 13 were already clean. Full strict/generator validation remains unmet and needs the function-context architecture tracked in fix: distinguish script await identifiers from module and async operands #55; no universal validation guarantee or impossibility claim is made.
  • chosen: Keep two public API tests because existing corpus missed standalone rejection and supertype membership. Both tests fail on the released parser; valid controls require canonical constructor captures and shared top-level sentinel name/text/ranges/ownership checks, and 12 real optional/arrow/parentheses/trivia/async edits require full fresh-tree/query equivalence and restoration. Moving the sentinel into the function leaves the old test green and fails the shared ownership check. Invalid-arrow recovery may absorb the following declaration into ERROR; preserve and disclose this malformed-buffer limit rather than asserting clean ownership for it.
  • chosen: Preserve async-function constructors through canonical function/generator aliases with a scoped zero-width CONSTRUCTOR_ASYNC_FUNCTION_START at index34. The shared keyword reader selects async only before the whole function keyword with no intervening line terminator, retaining await decisions and two-byte state. A lower constructor-name precedence still rejects the cases; a marker on general function expressions turns declarations into expressions, so keep the marker scoped to constructor functions. Four new public controls fail before repair and pass after it. Of 1544 async/boundary records, all1095 baseline-clean nonoptional controls retain full trees/captures; 128 optional-chain clean parses become requested errors, and one already-ERROR functionValue recovery differs. Seven focused full raw grammarType trees remain exact. All2552 await controls and2072 original constructor records remain exact; corpus retains its one documented ERROR-tree change.
  • chosen: Report same-generator/runtime1.2.2 costs: states3398→3523, C4786918→4769917 bytes, Wasm739503→751024. Six rotating fresh Node samples cost1.016× ordinary/1.082× nested/1.124× argumentless; complete/unfinished25KiB comments1.540×/1.208× and long newlines1.415×. Native-O1 samples1.010×/1.038×/1.104× and1.440×/1.080×/1.312× respectively. No generic speed claim or recovery bound is made.
  • chosen: Require Rust README consumers to use runtime 1.2.2 or newer, matching the native and npm minimum because older locked runtimes fail the required constructor-supertype query. State that minimum for web consumers too; use grammar major 3 for the breaking release from current v2.0.3 rather than the obsolete major-1 example. Remove the stale precedence-only constructor comment instead of restating rules already enforced by public constructor tests; remove the unverified upstream-runtime recovery warning.

Customer Summary

Unparenthesized optional-chain and arrow constructors report syntax errors. Parenthesized optional/arrow constructors, tagged constructors and nested new keep canonical nodes and constructor captures.

Technical Summary

Restricted constructor atoms and chains alias to the existing public node types and primary-expression supertype. The zero-width argumentless-new boundary prevents the parser from accepting an invalid continuation by ending new early; decimal conditional syntax remains available. The markers are appended after all 33 existing external tokens, never emitted during all-token recovery, and introduce no scanner state. Constructor functions use a scoped async-function start marker, with a same-line async/function keyword check; general declarations and await decisions remain intact. Source grammar and scanner must update together.

The native lockfile and declared web runtime use 1.2.2. Public schema and ABI 15 remain unchanged. The newer generator/runtime preserves alias-supertype queries that fail with 1.0.16.

Testing

Current head 7b160e0 passes CI/readiness (launch 1791327657-b6cdc23661a849cc, no new events). Review 008daccf completed with five distinct fixes (three major, two minor) and one service-marked duplicate. Five of seven reviewers completed successful sessions; Claude Sonnet/Opus were unavailable. Last exploration covered a8b3712; completion 7b160e0 is not covered by a measured exploration session, while its test-only repair was independently rechecked. All 30 saved notes and five Requirements versions were inspected; generated tables were checked through regeneration, schema/token invariants and parser behavior. No full-table manual reading or universal recovery/performance claim is made.

Both public constructor tests use the shared checker to assert the trailing sentinel declaration's name, text, ranges and top-level ownership. A valid-source mutation moving the sentinel into the function passes the old checker and fails the new top-level ownership assertion. The focused constructor tests and lint/type verification pass; this test-only change leaves parser and Wasm artifacts unchanged.

The README names runtime 1.2.2 as the minimum for Rust/web consumers and uses grammar major 3 for this breaking release. The obsolete precedence-only constructor comment is removed. Regeneration retains identical parser, grammar JSON, node schema and Wasm bytes; existing runtime-version and query tests plus lint/types pass.

The four public async-constructor controls fail before repair and pass afterward. All 1095 baseline-clean nonoptional async controls retain complete trees/captures; seven focused raw grammarType trees remain exact. Of 1544 async records, 128 invalid optional-chain forms newly report errors, and one already-ERROR functionValue buffer changes recovery. The four public division controls fail on d3 and pass with the scanner guard; both constructor tests, lint and types pass. All 36 division controls preserve released main full trees and seven query sets (30 clean, six ERROR). All 2072 original constructor records remain exact before/after the repairs; rebuilt explicit native and Wasm classifications agree on all 2072. Current 199 corpus and 2552 await comparisons retain their documented outcomes.

  • mise exec rust@1.98.1 -- bun wb verify --full with constructor, runtime-version, query, incremental and corpus files: relevant existing checks pass; both new constructor tests subsequently pass with lint/types. Both new tests fail on released c32; restoring the candidate Wasm and timestamps is verified byte-for-byte.
  • Explicit native and Wasm parsers agree on all 2072 constructor cases: 1104 Node-accepted clean, 968 rejected ERROR. All 1048 incoming-clean accepted cases retain full public trees and seven query sets except 16 compiler/Acorn-confirmed yield.C identifier corrections. All 2552 await controls and 198/199 corpus trees/captures remain exact; one already-ERROR optional-constructor-call assignment recovery changes.
  • All 308 compiler-accepted sources in 432 strict/async/generator/class contexts parse cleanly. Six supported constructor subtype queries compile on both versions; raw grammarType is retained in eight focused constructor controls. Constructor:(expression) fails on both versions and is not newly supported. Twelve real edits match fresh full trees/captures and restore the original tree.
  • Same-generator generated-size comparison and six rotating Node/native performance samples are recorded in Requirements. The strict/generator rejection and malformed-arrow recovery limitations below are measured, not assertions of full validation.

Notes

Breaking release: require runtime 1.2.2 and regenerate grammar/scanner together. TypeScript's current source extension needs a separate conflict/scanner port before it can adopt this parent; current released TypeScript is pinned to the old parent.

The grammar still lacks full Script/Module and innermost function/strict-mode validation (#55). Fifteen compiler-rejected yield contexts become parser-clean while 13 were already clean. Node and Acorn disagree on 32 import-related controls, so Node acceptance is scoped evidence. Legacy call-assignment behavior remains tracked separately in #58. Malformed new () => 1 may absorb a following declaration into ERROR; valid-source ownership and incremental restoration remain checked. Long-trivia costs increase as recorded above.

exKAZUu and others added 2 commits October 7, 2026 06:06
Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
@exKAZUu exKAZUu self-assigned this Oct 6, 2026
exKAZUu and others added 3 commits October 7, 2026 06:47
Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
Check the sentinel declaration's top-level owner, text and ranges in both
public constructor tests through the shared constructor checker.

Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
@exKAZUu
exKAZUu merged commit 7832015 into main Oct 6, 2026
10 checks passed
@exKAZUu
exKAZUu deleted the fix/constructor-primary-syntax branch October 6, 2026 23:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: reject optional constructors without breaking supertype queries

1 participant