Skip to content

Compile classes that extend Array - #2059

Open
ctate wants to merge 4 commits into
mainfrom
ctate/compile-classes-that-a73f15
Open

ctate wants to merge 4 commits into
mainfrom
ctate/compile-classes-that-a73f15

Conversation

@ctate

@ctate ctate commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator
  • Instances of class X extends Array are native arrays with their class's fields after the array header: every array operation, instanceof, inspect output and species construction (map, filter, slice and the rest return the subclass) match Node.
  • Programs without an Array subclass compile to identical LLVM; bench:runtime geomean -0.1% (neutral).
  • Corpus 7720-7726.

A class declared `extends Array` (or `extends Array<T>`) was refused with
"extending classes not declared in the program ('Array')", which blocked
lru-cache at module load. An instance is now an array of the class's
element type: its struct begins with the runtime's array header, whose
reference count it shares, and the class's own fields follow it. The
class's TypeScript type maps to its element array type, so every array
operation applies to an instance, and passing it where an array is
expected passes the same object. The class's own fields, methods,
accessors and statics read the array as the class object.

super() follows the Array constructor: one number argument sets the
length (a RangeError for an invalid one), other arguments become the
elements, and the implicit constructor forwards its arguments the same
way. The runtime finds the class through the array's ext (ScrArrClass:
name, destroy, the own fields, the species constructor), so instanceof
the class (or a binding that holds it) works on static, array-typed and
dyn values, util.inspect
prints `Name(length) [ ..., field: value ]`, Object.keys lists the own
fields, and a release through any array path reaches the class's
teardown. Instances whose elements or fields can form cycles carry the
collector header and are traced.

map, filter, slice, splice, concat, flat and flatMap construct their
result through the class as ArraySpeciesCreate does: `new C(length)` with
the specification's argument, then the elements, then the length where
the specification sets it. A map to another element type retypes the
new instance when its constructor added no elements. Array.of and
Array.from called on the class construct through it. Programs that
declare no Array subclass compile as before.

A generic subclass, a subclass of such a class and `static
[Symbol.species]` are refused at compile time; a species result the
class's constructor cannot construct throws a TypeError.

String() of an array with checked-dynamic elements now uses the
runtime's String() instead of being refused.

Corpus 7720-7726, diagnostics fixture array-subclass-fences.ts.
@vercel

vercel Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
scriptc Ready Ready Preview, v0 Oct 24, 2026 7:23am UTC

@vercel-security-reviewer

Copy link
Copy Markdown

Security review details

Comment thread packages/compiler/src/frontend/lowering/builtins/array-classes.ts
Comment thread packages/runtime/src/scr_array.c Outdated
Comment thread packages/compiler/src/backend/llvm/classes.ts
Comment thread packages/compiler/src/frontend/lowering/builtins/array-classes.ts Outdated

This branch was successfully deployed

1 active deployment
Preview — f13ae449 Deployed Oct 24, 2026 by vercel[bot]
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.

1 participant