SharpTS Implementation Status

June 30, 2026 · View on GitHub

This document tracks TypeScript language features and their implementation status in SharpTS.

Last Updated: 2026-06-23 (Tier-1 tech-debt cleanup — NaN-guard parity in RuntimeTypes equality, async-function suspension-walker reconciliation, dead-code removal, and the "Known regression" entry below corrected per PR #906. Prior: Perf epic #856 — compiled output now meets or beats Node.js on 5 of 7 cross-runtime workloads, the other two within ~1.2×; loop-backedge cancellation now emits throw instead of a returning call, recovering ~1.8× on tight numeric loops — see §18)

Legend

  • ✅ Implemented
  • ❌ Missing
  • ⚠️ Partially Implemented

1. TYPE SYSTEM

FeatureStatusNotes
Primitive types (string, number, boolean, null)
void type
any type
Array types (T[])
Object typesStructural typing
InterfacesStructural typing
ClassesNominal typing
Generics (<T>)Full support with true .NET generics and constraints
Variance annotations (in, out, in out)Explicit variance control for generic type parameters (TS 4.7+)
Union Types (string | number)With type narrowing support
Intersection Types (A & B)For combining types with full TypeScript semantics
Literal Types ("success" | "error")String, number, and boolean literals
Type Aliases (type Name = ...)Including function types
Tuple Types ([string, number])Fixed-length typed arrays with optional, rest, and named elements
unknown typeSafer alternative to any
never typeFor exhaustive checking
Type Assertions (as, <Type>)Both as and angle-bracket syntax
as const assertionsDeep readonly inference for literals
Type Guards (is, typeof narrowing)typeof narrowing, user-defined type guards (x is T), assertion functions, property access narrowing
readonly modifierCompile-time enforcement
Optional Properties (prop?:)Partial object shapes
Index Signatures ([key: string]: T)String, number, and symbol key types
object typeNon-primitive type (excludes string, number, boolean, bigint, symbol, null, undefined)
unique symbol typeNominally-typed symbols for const declarations
Type predicates (is, asserts)User-defined type guards (x is T), assertion functions (asserts x is T, asserts x)
satisfies operatorValidates expression matches type without widening (TS 4.9+)
Variadic tuple types[...T] spread in tuples, Prepend/Append/Concat patterns
Definite assignment assertionlet x!: number syntax for variables and class fields

2. ENUMS

FeatureStatusNotes
Numeric Enumsenum Color { Red, Green } with auto-increment
String Enumsenum Color { Red = "RED" }
Const EnumsCompile-time inlined enums with computed value support
Heterogeneous EnumsMixed string/number values

3. CLASSES

FeatureStatusNotes
Basic classesConstructors, methods, fields
Inheritance (extends)Single inheritance
super calls
this keyword
Access modifiers (public/private/protected)Compile-time enforcement
static membersClass-level properties/methods
abstract classesCannot be instantiated
abstract methodsMust be overridden, includes abstract accessors
Getters/Setters (get/set)Property accessors
Parameter propertiesconstructor(public x: number)
implements keywordClass implementing interface
Method overloadingMultiple signatures with implementation function
override keywordExplicit override marker for methods/accessors
Private fields (#field)ES2022 hard private fields with ConditionalWeakTable isolation; full interpreter and IL compiler support
Static blocksstatic { } for static initialization; executes in declaration order with static fields; this binds to class
accessor keywordAuto-accessor class fields (TS 4.9+); full interpreter and IL compiler support with deferred boxing optimization
declare field modifierAmbient field declarations for external initialization (decorators, DI); full interpreter and IL compiler support

4. FUNCTIONS

FeatureStatusNotes
Function declarations
Arrow functions
ClosuresVariable capture works
Default parameters(x = 5)
Type annotationsParameters and return types
Rest parameters (...args)Variable arguments
Spread in calls (fn(...arr))Array expansion
OverloadsMultiple signatures with implementation function
this parameter typingExplicit this type in function declarations
Generic functionsfunction identity<T>(x: T) with type inference
Named function expressionsconst f = function myFunc() {} with self-reference for recursion
Constructor signaturesnew (params): T in interfaces, new on expressions
Call signatures(params): T in interfaces, callable interface types

5. ASYNC/PROMISES

FeatureStatusNotes
PromisesPromise<T> type with await support, new Promise((resolve, reject) => { }) executor constructor
Promise instance methods.then(), .catch(), .finally() with chaining support
async functionsFull state machine compilation
await keywordPause and resume via .NET Task infrastructure
Async arrow functionsIncluding nested async arrows
Async class methodsFull this capture support
Try/catch in asyncAwait inside try/catch/finally blocks
Nested await in argsawait fn(await getValue())
Promise.all/race/any/allSettledFull interpreter support; IL compiler: all/race/allSettled as pure IL state machines, any delegates to runtime
Promise.resolve/rejectStatic factory methods with Promise flattening
Promise.withResolversReturns {promise, resolve, reject} for external promise resolution (ES2024)

6. MODULES

FeatureStatusNotes
import statementsimport { x } from './file'
export statementsexport function/class/const
Default exportsexport default
Namespace importsimport * as X from './file'
Re-exportsexport { x } from './file', export * from './file'
TypeScript namespacesnamespace X { } with declaration merging, dotted syntax, functions, variables, enums, nested namespaces, classes with new Namespace.Class() instantiation
Namespace import aliasimport X = Namespace.Member, export import X = Namespace.Member
Dynamic importsawait import('./file') with module registry for compiled mode, typeof import() typing for literal paths
import typeStatement-level (import type { T }) and inline (import { type T }) type-only imports
import.metaimport.meta.url for module metadata
export = / import =CommonJS interop: export = value, import x = require('path'), export import x = require() (class exports have known limitation)
Ambient module declarationsdeclare module 'x' { } - type-only declarations for external packages
Module augmentationdeclare module './path' { } extends existing modules, declare global { } extends global types
Triple-slash references/// <reference path="..."> for script-style file merging
package.json exportsSubpath exports, conditional exports (types/import/default), wildcard patterns, null restrictions, array fallbacks
Subpath imports (#)"imports" field in package.json with #-prefixed specifiers
Self-referencingPackage imports itself by name through its own exports

7. OPERATORS

FeatureStatusNotes
Arithmetic (+, -, *, /, %)
Comparison (==, !=, <, >, <=, >=)
Logical (&&, ||, !)Short-circuit evaluation
Nullish coalescing (??)
Optional chaining (?.)
Ternary (? :)
typeofReturns "undefined" for undeclared variables (no ReferenceError)
Assignment (=, +=, -=, *=, /=, %=)
Increment/Decrement (++, --)Pre and post
Bitwise (&, |, ^, ~, <<, >>, >>>)Including compound assignments
Strict equality (===, !==)Same behavior as ==/!=
instanceofWith inheritance chain support
in operatorProperty existence check
Exponentiation (**)Right-associative
Spread operator (...)In arrays/objects/calls
Non-null assertion (x!)Postfix operator to assert non-null
Logical assignment (&&=, ||=, ??=)Compound logical assignment operators with short-circuit evaluation
keyof operatorExtract keys as union type
typeof in type positionExtract type from value
Comma operator (,)Sequence expression: evaluates left-to-right, returns last value

8. DESTRUCTURING

FeatureStatusNotes
Array destructuringconst [a, b] = arr
Object destructuringconst { x, y } = obj
Nested destructuringDeep pattern matching
Default values in destructuringconst { x = 5 } = obj (via nullish coalescing)
Array rest patternconst [first, ...rest] = arr
Object rest patternconst { x, ...rest } = obj
Array holesconst [a, , c] = arr
Object renameconst { x: newName } = obj
Parameter destructuringfunction f({ x, y }) and ([a, b]) => ...

9. CONTROL FLOW

FeatureStatusNotes
if/else
while loops
for loopsDesugared to while
for...of loopsArray iteration
switch/caseWith fall-through
break
continue
return
try/catch/finally
throw
for...in loopsObject key iteration
do...while loopsPost-condition loop
Label statementslabel: for (...) with break/continue support
Optional catch bindingcatch { } without parameter (ES2019)

10. BUILT-IN APIS

FeatureStatusNotes
console.logMultiple arguments, printf-style format specifiers (%s, %d, %i, %f, %o, %O, %j, %%)
Math objectPI, E, abs, floor, ceil, round, sqrt, sin, cos, tan, log, exp, sign, trunc, pow, min, max, random
String methodslength, charAt, substring, indexOf, toUpperCase, toLowerCase, trim, replace, split, includes, startsWith, endsWith, slice, repeat, padStart, padEnd, charCodeAt, codePointAt, concat, lastIndexOf, trimStart, trimEnd, replaceAll, at, matchAll
Array methodspush, pop, shift, unshift, reverse, slice, concat, map, filter, forEach, find, findIndex, findLast, findLastIndex, some, every, reduce, reduceRight, includes, indexOf, join, sort, toSorted, toReversed, with, flat, flatMap, splice, toSpliced, at, fill, copyWithin, entries, keys, values
JSON.parse/stringifyWith reviver, replacer, indentation, class instances, toJSON(), BigInt TypeError
Object.keys/values/entries/fromEntries/hasOwnFull support for object literals and class instances
Array.isArrayType guard for array detection
Number methodsparseInt, parseFloat, isNaN, isFinite, isInteger, isSafeInteger, toFixed, toPrecision, toExponential, toString(radix); constants: MAX_VALUE, MIN_VALUE, NaN, POSITIVE_INFINITY, NEGATIVE_INFINITY, MAX_SAFE_INTEGER, MIN_SAFE_INTEGER, EPSILON
Date objectFull local timezone support with constructors, getters, setters, conversion methods
Map/SetFull API (get, set, has, delete, clear, size, keys, values, entries, forEach); for...of iteration; reference equality for object keys; Map.groupBy() (ES2024); ES2025 Set operations (union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf, isDisjointFrom)
WeakMap/WeakSetFull API (get, set, has, delete for WeakMap; add, has, delete for WeakSet); object-only keys/values; no iteration or size
RegExpFull API (test, exec, source, flags, global, ignoreCase, multiline, lastIndex); /pattern/flags literal and new RegExp() constructor; string methods (match, replace, search, split, matchAll) with regex support; named capture groups ((?<name>...)) with .groups property on match results
Array.from()Create array from iterable with optional map function
Array.of()Create array from arguments
Object.assign()Merge objects - copies properties from one or more source objects to a target object, returns the target
Object.fromEntries()Inverse of Object.entries() - converts iterable of [key, value] pairs to object
Object.hasOwn()Safer hasOwnProperty check - returns true for own properties, false for methods
Object.freeze()/seal()/isFrozen()/isSealed()Object immutability - freeze prevents all changes, seal allows modification but prevents adding/removing properties; shallow freeze/seal (nested objects unaffected); works on objects, arrays, class instances
Error classError, TypeError, RangeError, ReferenceError, SyntaxError, URIError, EvalError, AggregateError with name, message, stack, cause (ES2022) properties
Strict mode ("use strict")File-level and function-level strict mode; frozen/sealed object mutations throw TypeError in strict mode
setTimeout/clearTimeoutTimer functions with Timeout handle, ref/unref support
setInterval/clearIntervalRepeating timer functions with Timeout handle, no overlap between executions
setImmediate/clearImmediateImmediate execution timer (runs after current event loop iteration)
globalThisES2020 global object reference with property access and method calls
structuredCloneDeep clone of values (objects, arrays, Map, Set, etc.)
AbortController/AbortSignalnew AbortController(), signal.aborted, abort(reason?), addEventListener/removeEventListener, throwIfAborted, onabort, AbortSignal.abort()/timeout()/any(), fetch signal option
fetch() APIfetch(url, options?) returns Promise<Response>; Response: status, statusText, ok, url, headers, body (Readable stream), bodyUsed, json(), text(), arrayBuffer(), clone(); Headers: get(), set(), has(), delete(), append(), forEach(), entries(), keys(), values(); options: method, headers, body, signal, redirect (follow/manual/error)
Web Streams APIReadableStream, WritableStream, TransformStream with default controllers/readers/writers; pipeTo(), pipeThrough(), tee(), cancel(), getReader()/getWriter(), closed/ready promises, desiredSize backpressure; ByteLengthQueuingStrategy, CountQueuingStrategy; ReadableStream.from(iterable) (eager array/string/Set forms); also exported from node:stream/web. Deferred: BYOB readers, transferable streams, Symbol.asyncIterator on ReadableStream, Response.body migration.
URL/URLSearchParamsFull WHATWG URL API: constructor, href, protocol, host, hostname, port, pathname, search, hash, origin, username, password, searchParams, toString(); URLSearchParams: get(), set(), has(), delete(), append(), entries(), keys(), values(), forEach(), toString(), sort()
TextEncoder/TextDecoderTextEncoder.encode(string)Uint8Array; TextDecoder.decode(buffer)string; UTF-8 encoding/decoding
console methodslog, error, warn, info, debug, clear, time/timeEnd/timeLog, assert, count/countReset, table, dir, group/groupCollapsed/groupEnd, trace
Intl.NumberFormatLocale-aware number/currency/percent formatting; format(), resolvedOptions(); options: style, currency, minimumFractionDigits, maximumFractionDigits, minimumIntegerDigits, useGrouping
Intl.DateTimeFormatLocale-aware date/time formatting; format(), resolvedOptions(); options: dateStyle, timeStyle, year, month, day, weekday, hour, minute, second, hour12, timeZone, timeZoneName, era, fractionalSecondDigits
Intl.CollatorLocale-aware string comparison; compare(), resolvedOptions(); options: usage, sensitivity (base/accent/case/variant), ignorePunctuation, numeric, caseFirst
Intl.PluralRulesPlural category selection (CLDR rules); select(), resolvedOptions(); options: type (cardinal/ordinal); categories: zero, one, two, few, many, other
Intl.RelativeTimeFormatLocale-aware relative time formatting; format(), formatToParts(), resolvedOptions(); options: style (long/short/narrow), numeric (always/auto); units: year, quarter, month, week, day, hour, minute, second
Intl.ListFormatLocale-aware list formatting; format(), formatToParts(), resolvedOptions(); options: style (long/short/narrow), type (conjunction/disjunction/unit)
Intl.SegmenterUnicode text segmentation; segment() returns iterable Segments with containing(); options: granularity (grapheme/word/sentence); segment data: segment, index, input, isWordLike
Intl.DisplayNamesLocale-aware display names; of(), resolvedOptions(); types: language, region, script, currency, calendar, dateTimeField; options: style, fallback (code/none), languageDisplay

11. SYNTAX

FeatureStatusNotes
let / const declarationsBlock-scoped per spec
var declarationsFunction-scoped semantics via parser-time hoisting; supports declarations in nested blocks (if/for/while/try) referenced in the enclosing function scope. Multi-declarator (var a = 1, b = 2) supported.
Multi-declarator let/constlet a = 1, b = 2 and const x = 1, y = 2
Line comments (//)
Double-quoted strings
Template literalsWith interpolation
Object literals
Array literals
Block comments (/* */)
Single-quoted strings
Object method shorthand{ fn() {} }
Object literal accessors{ get x() {}, set x(v) {} } with proper this binding
Computed property names{ [expr]: value }, { "key": v }, { 123: v }
Class expressionsconst C = class { } - interpreter and IL compiler full support
Shorthand properties{ x } instead of { x: x }
Tagged template literalstag`template` syntax with TemplateStringsArray and raw property
Numeric separators1_000_000 for readability

12. ADVANCED FEATURES

FeatureStatusNotes
Decorators (@decorator)Legacy & TC39 Stage 3, class/method/property/parameter decorators, Reflect API, @Namespace for .NET namespaces
Generators (function*)yield, yield*, .next(), .return(), .throw(); for...of integration
Async Generators (async function*)yield, yield*, .next(), .return(), .throw(); for await...of; full IL compiler support
Well-known SymbolsSymbol.iterator, Symbol.asyncIterator, Symbol.toStringTag, Symbol.hasInstance, Symbol.isConcatSpreadable, Symbol.toPrimitive, Symbol.species, Symbol.unscopables, Symbol.dispose, Symbol.asyncDispose
Iterator ProtocolCustom iterables via [Symbol.iterator]() method (interpreter and compiler)
Iterator Helpers (ES2025).map(), .filter(), .take(), .drop(), .flatMap(), .reduce(), .toArray(), .forEach(), .some(), .every(), .find(), .next() protocol; lazy evaluation; chaining; works on arrays, generators, Map/Set iterators
Async Iterator ProtocolCustom async iterables via [Symbol.asyncIterator]() method
for await...ofAsync iteration over async iterators and generators
Symbol.for/Symbol.keyForGlobal symbol registry
SymbolsUnique identifiers via Symbol() constructor
bigint typeArbitrary precision integers with full operation support
Mapped types{ [K in keyof T]: ... }, keyof, indexed access T[K], modifiers (+/-readonly, +/-?)
Conditional typesT extends U ? X : Y, infer keyword, distribution over unions
Template literal types`prefix${string}`, union expansion, pattern matching, infer support
Utility typesPartial<T>, Required<T>, Readonly<T>, Record<K, V>, Pick<T, K>, Omit<T, K>, Uppercase<S>, Lowercase<S>, Capitalize<S>, Uncapitalize<S>
Additional utility typesReturnType<T>, Parameters<T>, ConstructorParameters<T>, InstanceType<T>, ThisType<T>, Awaited<T>, NonNullable<T>, Extract<T, U>, Exclude<T, U>
using/await usingExplicit resource management (TS 5.2+); Symbol.dispose/Symbol.asyncDispose; automatic disposal at scope exit; SuppressedError for disposal errors
Const type parameters<const T> syntax (TS 5.0+) for preserving literal types during inference; readonly semantics for objects/arrays
Variance annotationsin/out/in out modifiers on type parameters (TS 4.7+)
Recursive type aliasesSelf-referential type definitions like `type Node = { next: Node

13. BINARY DATA & THREADING

FeatureStatusNotes
TypedArrays
Int8ArraySigned 8-bit integer array
Uint8ArrayUnsigned 8-bit integer array
Int16ArraySigned 16-bit integer array
Uint16ArrayUnsigned 16-bit integer array
Int32ArraySigned 32-bit integer array
Uint32ArrayUnsigned 32-bit integer array
Float32Array32-bit float array
Float64Array64-bit float array
BigInt64ArraySigned 64-bit BigInt array
BigUint64ArrayUnsigned 64-bit BigInt array
Uint8ClampedArrayClamped unsigned 8-bit integer array
Shared Memory
SharedArrayBufferShared memory for worker threads
Atomicsload, store, add, sub, and, or, xor, exchange, compareExchange, wait, notify
ArrayBufferNon-shared binary buffer: constructor, byteLength, slice(), isView()
DataView
DataViewFull API: constructor, properties (buffer, byteLength, byteOffset), getter/setter methods with endianness support

14. EXTENDED BUILT-IN APIS

This section tracks JavaScript/TypeScript APIs that were historically unimplemented in SharpTS. Most are now supported (✅) and are kept here for status visibility; the rows below reflect current state. The only fully-unimplemented item is the Function constructor (❌); eval is partial (⚠️).

Objects & Types

FeatureStatusNotes
Proxynew Proxy(target, handler), Proxy.revocable(), traps: get/set/has/deleteProperty/apply/construct
WeakRefnew WeakRef(target), .deref()
FinalizationRegistrynew FinalizationRegistry(callback), .register(target, heldValue, token?), .unregister(token)
Intl.NumberFormatSee Section 10
Intl.DateTimeFormatSee Section 10
Intl.CollatorSee Section 10
Intl.PluralRulesSee Section 10
Intl.RelativeTimeFormatSee Section 10
Intl.ListFormatSee Section 10
Intl.SegmenterSee Section 10
Intl.DisplayNamesSee Section 10

Global Functions

FeatureStatusNotes
eval()⚠️Typed as (s: string) => any. Interpreted: direct eval — source runs against the caller's scope chain. Compiled: indirect eval via the SharpTS runtime (EvalBridge) — global builtins resolve but compiled locals are not visible. The build auto-copies SharpTS.dll next to the output when eval is used (see "Standalone DLL Constraint" in CLAUDE.md); with --standalone it is not copied and eval throws "eval not supported" at runtime. Eval'd source is not type-checked. Non-string args returned unchanged (ECMA-262 §19.2.1).
Function constructorCannot create functions from strings
queueMicrotask()Schedules microtask for execution

Object Static Methods

FeatureStatusNotes
Object.create()Creates new object with prototype; supports propertiesObject argument for defining properties via descriptors
Object.is()Same-value comparison; handles NaN and +0/-0 edge cases
Object.getOwnPropertyDescriptor()Full support in both interpreter and compiled mode
Object.defineProperty()Full support including accessor properties (get/set) and descriptor flags in both modes
Object.getPrototypeOf()Returns prototype of an object
Object.setPrototypeOf()Sets prototype of an object
Object.getOwnPropertyNames()Returns all own property names including non-enumerable
Object.getOwnPropertySymbols()Returns array of symbol-keyed properties
Object.preventExtensions()Prevents adding new properties to an object
Object.isExtensible()Returns whether object allows new properties
Object.groupBy()Groups iterable elements by callback return value (ES2024); returns plain object with string keys
Object.defineProperties()Batch version of defineProperty; defines multiple properties from a descriptors object
Object.getOwnPropertyDescriptors()Returns all own property descriptors as an object; works with defineProperties for proper object cloning

Array Methods

FeatureStatusNotes
fill()
reduceRight()Iterates right-to-left
entries()Returns iterator of [index, value] pairs
keys()Returns iterator of indices
values()Returns iterator of values
copyWithin()Copies array elements within the array

String Methods & Static

FeatureStatusNotes
normalize()Unicode normalization (NFC, NFD, NFKC, NFKD)
localeCompare()Locale-aware comparison via string.Compare with CurrentCulture
codePointAt()Full Unicode code point at position; handles surrogate pairs for supplementary characters
String.fromCharCode()Creates string from UTF-16 code units
String.fromCodePoint()Creates string from Unicode code points; handles supplementary characters (> U+FFFF) via surrogate pairs
String.rawTagged template for raw string access without escape processing

Reflect API (Standard)

FeatureStatusNotes
Reflect.get()Property access on target object
Reflect.set()Returns bool; false for frozen objects
Reflect.has()Equivalent to in operator
Reflect.deleteProperty()Returns bool; false for frozen objects
Reflect.apply()Calls function with thisArg and args array
Reflect.construct()Creates instance; interpreter mode only for classes
Reflect.ownKeys()Returns string keys + symbol keys
Reflect.getPrototypeOf()Returns object prototype
Reflect.setPrototypeOf()Returns bool; false for non-extensible objects
Reflect.isExtensible()Returns bool
Reflect.preventExtensions()Returns true
Reflect.getOwnPropertyDescriptor()Returns property descriptor or undefined
Reflect.defineProperty()Returns bool; false on failure (unlike Object.defineProperty which throws)

15. NODE.JS BUILT-IN MODULES

SharpTS implements 20+ Node.js built-in modules accessible via import ... from "node:..." or bare specifiers.

ModuleStatusNotes
fs / fs/promisesreadFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync, unlinkSync, renameSync, copyFileSync, appendFileSync, readFile, writeFile, mkdir, readdir, stat, unlink, rename, rm, access, lstat, realpath, createReadStream, createWriteStream, watch, watchFile, unwatchFile
pathjoin, resolve, dirname, basename, extname, normalize, isAbsolute, relative, parse, format, sep, delimiter, posix, win32. SharpTS divergence: path.win32.isAbsolute('/foo') returns false (requires drive-letter + separator or UNC double-separator). Node returns true for any leading separator.
osplatform, arch, cpus, hostname, homedir, tmpdir, type, release, uptime, totalmem, freemem, EOL, networkInterfaces, loadavg, userInfo
processargv, env, cwd(), exit(), pid, platform, arch, version, stdout, stderr, stdin, hrtime, nextTick, memoryUsage, exitCode; EventEmitter support (on, once, emit, off, removeAllListeners, listeners, listenerCount, eventNames)
cryptocreateHash, createHmac, randomBytes, randomUUID, randomInt, randomFillSync, createCipheriv/Decipheriv, pbkdf2/pbkdf2Sync, scrypt/scryptSync, timingSafeEqual, generateKeyPair/generateKeyPairSync, createSign/Verify, createDiffieHellman, createECDH, hkdf/hkdfSync, getHashes, getCiphers, getCurves, constants
eventsEventEmitter: on, once, emit, removeListener, removeAllListeners, listenerCount, listeners, prependListener, prependOnceListener, off, setMaxListeners, getMaxListeners, eventNames
streamReadable, Writable, Duplex, Transform, PassThrough; finished(stream, opts?, cb), pipeline(source, ...transforms, dest, cb?), addAbortSignal(signal, stream); Readable.from(iterable), Readable.isReadable(stream), Writable.isWritable(stream); instance: toArray(), forEach(fn), map(fn), filter(fn); pause/resume/prefinish events, autoDestroy option, highWaterMark enforcement; object mode support; stream/promises sub-module (pipeline, finished)
bufferBuffer.from, Buffer.alloc, Buffer.allocUnsafe, Buffer.concat, Buffer.isBuffer, Buffer.byteLength; instance methods: toString, slice, copy, write, fill, includes, indexOf, compare, equals, readUInt/Int, writeUInt/Int, toJSON
http / httpscreateServer, request, get; Agent class with constructor, destroy, getName, globalAgent; Server: listen, close; IncomingMessage extends Readable; ServerResponse extends Writable; full event lifecycle
netcreateServer, createConnection/connect, Socket (EventEmitter + Duplex), Server (EventEmitter); isIP, isIPv4, isIPv6; IPC sockets (named pipes on Windows, Unix domain sockets on Linux/macOS)
tlscreateServer, connect, createSecureContext, TLSSocket (extends Socket), Server; DEFAULT_MIN_VERSION/MAX_VERSION; ALPNProtocols, SNICallback, servername; secureConnect/secureConnection/tlsClientError events
dgramcreateSocket, Socket; bind, send, close, address, setBroadcast, setTTL, addMembership, dropMembership; connect, disconnect, remoteAddress, get/setRecvBufferSize, get/setSendBufferSize; message/listening/close/error/connect events
clusterisPrimary/isWorker/isMaster, fork, worker.send/disconnect/kill/isDead/isConnected, process.send/on('message') IPC, cluster events, disconnect, setupPrimary
child_processexecSync, spawnSync, exec, spawn, execFileSync, execFile, fork (IPC via named pipes); ChildProcess: pid, exitCode, killed, stdout, stderr, stdin, connected, kill, send, disconnect
vmrunInNewContext, runInThisContext, runInContext, createContext (name/origin/codeGeneration/microtaskMode), isContext, compileFunction, measureMemory, constants (USE_MAIN_CONTEXT_DEFAULT_LOADER/DONT_CONTEXTIFY); Script (runIn*Context, createCachedData, filename/offsets, cachedData); ESM-in-vm: SourceTextModule + SyntheticModule (link/evaluate/status/namespace/setExport), importModuleDynamically
urlURL, URLSearchParams, fileURLToPath, pathToFileURL, format, parse
utilpromisify, deprecate, types (isDate, isRegExp, isMap, isSet, etc.), format, inspect, TextEncoder, TextDecoder
querystringparse, stringify, escape, unescape
zlibSync: gzipSync, gunzipSync, deflateSync, inflateSync, deflateRawSync, inflateRawSync, brotliCompressSync, brotliDecompressSync; Streaming: createGzip, createGunzip, createDeflate, createInflate, createDeflateRaw, createInflateRaw, createBrotliCompress, createBrotliDecompress, createUnzip; Async callback: gzip, gunzip, deflate, inflate, deflateRaw, inflateRaw, brotliCompress, brotliDecompress, unzip
dnslookup, lookupService, resolve, resolve4, resolve6, reverse, resolveMx, resolveTxt, resolveSrv, resolveCname, resolveNs, resolveSoa, resolvePtr, resolveCaa, resolveNaptr (callback + dns/promises)
assertok, equal, notEqual, deepEqual, notDeepEqual, strictEqual, notStrictEqual, deepStrictEqual, throws, doesNotThrow, rejects, doesNotReject, fail, match, doesNotMatch, assert.strict
readlinecreateInterface (extends EventEmitter), question, close, prompt, pause, resume, write, setPrompt, getPrompt, questionSync
string_decoderStringDecoder: write, end, encoding
timerssetTimeout, clearTimeout, setInterval, clearInterval, setImmediate, clearImmediate
timers/promisesPromise-based setTimeout, setImmediate, setInterval
perf_hooksperformance.now(), timeOrigin, mark(), measure(), getEntries(), getEntriesByName(), getEntriesByType(), clearMarks(), clearMeasures(); PerformanceObserver
worker_threadsWorker, isMainThread, parentPort, workerData, MessageChannel, MessagePort. Worker stdin/stdout/stderr and resourceLimits options are not supported (workers share the parent's console; resourceLimits has no .NET equivalent)
async_hooksAsyncLocalStorage: run, getStore, enterWith, exit, disable; async context propagation via .NET AsyncLocal

Module Implementation Source

14 modules are implemented in TypeScript under stdlib/node/*.ts, embedded in SharpTS.dll as resources and compiled alongside user code at --compile time. The remaining modules stay C#-backed for host-I/O reasons. See docs/plans/embedded-stdlib.md for the provider chain, primitive:* layer, and migration rationale.

ImplementationModules
TypeScript stdlibassert, async_hooks, events, os, path, perf_hooks, process, querystring, readline, string_decoder, timers, timers/promises, tty, url, util
C# / IL (host-I/O)fs, fs/promises, crypto, stream, stream/promises, stream/web, buffer, http, https, net, tls, dgram, cluster, child_process, vm, zlib, dns, dns/promises, worker_threads

16. .NET INTEROP (@DotNetType)

@DotNetType marks a declared class as a facade over a real .NET type, enabling TypeScript code to use BCL types directly. Works in both interpreter and compiled modes as of 2026-04-18.

FeatureStatusNotes
@DotNetType("Namespace.Type") on declare classInstance methods, static methods, constructors, properties, fields
@DotNetOverload("type1,type2,...") overload hintsPin a specific overload when argument-based resolution is ambiguous
Overload resolutionIdentity → widening → narrowing → object cost scale; same semantics in both modes
Generic type instantiationClosed generics via string specifier (e.g., "System.Collections.Generic.List<string>")
Delegate parametersTS functions auto-marshaled to .NET delegates (Action, Func<...>, custom delegates) via DotNetDelegateShim
Event subscription (+= / -=)obj.on(e) / obj.off(e) style plus direct += compound assignment in compiled mode; main-thread-only
Exception mapping.NET exceptions surface as JS-catchable errors with message preservation (DotNetExceptionMapper)
Value / reference type marshalingPrimitives, strings, arrays, dictionaries; DotNetMarshaller centralizes conversion
External assembly discoveryTryResolveExternalType scans loaded AppDomain assemblies; no additional reference wiring needed

Compiled mode uses late-bound reflection to the shim (DotNetDelegateShim / DotNetEventBinder) so the output DLL stays standalone. See docs/dotnet-types.md for the full guide.


17. CONFORMANCE TEST SUITES

Two external corpora pin SharpTS against canonical references. Both run as standalone projects (not in SharpTS.sln); see each project's README for full details. Pass rates here are subset-relative — neither suite runs the full corpus today.

TC39 Test262 (ECMA-262 / JavaScript spec)

SharpTS.Test262/ runs a configurable subset of test262 in both interpreter and compiled-IL modes. Diff harness is committed-baseline-vs-current; hard-fails on regression or new-pass. As of 2026-04-20 the suite is at 10,132/10,132 pass on the configured subset (zero skips) — see feedback_test_perf_changes.md and the various project_*_2026_04_*.md memory entries for context.

Microsoft TypeScript conformance (TS type-checker spec)

SharpTS.TypeScriptConformance/ runs a subset of microsoft/TypeScript's conformance corpus and diffs our type-checker diagnostics against tsc's *.errors.txt baselines. Pinned to TS v5.5.4. Pass classification is on (line, tsCode) tuples — see #80 for the tracking epic.

SubsetTestsPassFailParseErrorSkipped
types/typeRelationships/assignmentCompatibility/7016 (22.9%)5040
types/conditional/90531
Total7916 (20.3%)5571

The parser is no longer the bottleneck. An extended parser sweep took the subset's ParseError count from 57 → 7 (≈86%): ambient declare of non-class declarations, declare function, generic/this/conditional/mapped/indexed-access/constructor/leading-operator types, module Foo {} namespaces, call/construct/index signatures, keyword & string/numeric property names, function-type and arrow optional/rest parameters, and more. Negative-test matching itself was unlocked by propagating canonical TSnnnn codes through the type-checker's error-recovery path (#125), which also added a strictNullChecks option (default on; the runner follows each test's @strict/@strictNullChecks directive).

The dominant bucket is now Fail — tests that parse and reach the type checker but whose diagnostic set doesn't yet match tsc's. These are mostly the assignmentCompatibility cases, which require deeper callable / constructable / structural assignability. The largest remaining levers are structural class-to-class assignability (#129 — SharpTS is nominal by design) and loading tsc's lib.*.d.ts (#99).

Skipped includes:

  • Multi-file tests (Skipped:multi-file-deferred) — cross-file resolution into the runner is follow-up work.
  • Lib-drift skips (Skipped:lib-drift) — tests where tsc expects "method missing" diagnostics our checker doesn't reproduce because we have the surface always-available regardless of @lib. Conservative filter (only fires when our diagnostic set is empty AND every expected code is one of TS2339/TS2304/TS2551/TS7053). See #83 for the design and #99 for the deferred Phase-1.5 work that would eliminate the drift entirely (load tsc's lib.*.d.ts files into the type checker).
  • Directive skips — tests with directives like @experimentalDecorators, @jsx, @isolatedModules we don't intend to honor in Phase 1.

18. PERFORMANCE (compiled output vs Node.js)

Epic #856 tracks closing the compiled-IL gap to Node.js on the cross-runtime benchmark suite (benchmarks/scripts/, run via benchmarks/run-benchmarks.ps1), without regressing .NET interop or language conformance (Test262 + microsoft/TypeScript). Warm steady-state, compiled vs Node at the largest input size:

WorkloadStatusvs Node
fibonacci~2.4× faster — recursion/call core
array-methods~2× faster — typed List<double> HOF pipeline (#872)
stringsfaster (~0.9×) — StringBuilder accumulator promotion (#870) + charCodeAt box-elision (#873)
objectsparity (1.00×) — object literals as shape structs (#862) + cancel-throw codegen (below)
closuresparity (~1.02×) — non-escaping local arrows de-virtualized to direct calls (#858)
count-primes~1.13× (sieve; List<bool> index-write bounds checks are the residual)
factorial~1.22× (tight numeric loop at the codegen floor; V8 is ~0.2 ns/iter tighter; µs-scale)

The original catastrophic gaps (14–117× slower) are closed and the suite now meets-or-beats Node on 5 of 7 workloads, with the other two within ~1.2×. Every win came from re-exposing static types that the naive lowering erased — boxing, object/List<object> representations, reflective dispatch, O(n²) string concat — so RyuJIT can optimize typed code. The emitter's job is to choose the algorithm/representation/dispatch and not erase known types; the JIT optimizes the typed ops it's given.

Loop-backedge cancellation: throw, don't call (2026-06-21). Every compiled loop polls a cooperative-cancellation flag at its backedge so the runner can unwind runaway loops (issue #74). The flag test is an inlined volatile. field read (#874); the cold path used to be call $Runtime.CheckCancellation() (a helper that throws internally). That was the dominant remaining gap on tight loops — not the flag read, which is free. From the JIT's flow-graph view CheckCancellation() is a returning call (its throw is conditional and internal), so the register allocator must assume control returns. On SysV x64 every XMM register is caller-saved, so a returning call inside a loop forces the loop-carried doubles (and counter) to be stack-resident across every iteration — a load/store per use. The backedge now emits call $Runtime.BuildCancellationException(); throw — a factory that only constructs the exception, then a real throw opcode. Because throw does not return, the loop vars are dead on the cancel path and stay in registers on the hot path. Measured ~1.8× on tight numeric loops: objects 2.5×→parity, strings 1.26×→faster, factorial 2.27×→1.22×, count-primes 1.45×→1.13×. Cancellation semantics are unchanged (same OperationCanceledException, same message, thrown at the same point). This benefits all compiled loops, not just the benchmark suite.

Why earlier attempts plateaued: the inline-volatile form (#874) removed the unconditional call overhead but left the returning call in the loop's flow graph, so the XMM spill remained. A throttle-every-N-iterations variant ties it — reducing read frequency doesn't remove the call from the flow graph. The fix is structural: make the cancel path non-returning so the loop body carries no call at all.

The two remaining sub-parity workloads (count-primes ~1.13×, factorial ~1.22×) are at the codegen floor: factorial's loop already runs at the no-cancellation-check speed (V8 generates a marginally tighter multiply loop); count-primes' residual is List<bool> indexed-write bounds checking vs V8's packed-array elision.


Breaking Changes (2026-04-18)

The embedded-stdlib migration removed implicit global bindings for several classes previously created as compile-time fallbacks. User code must now import these from the owning module explicitly (matches ESM-strict semantics and Node's own behavior):

ClassPrevious behaviorRequired now
URL, URLSearchParamsAvailable as globals, backed by a pattern-matched $URL / $URLSearchParams emitter over System.Uri.import { URL, URLSearchParams } from 'url'
PerformanceObserverAvailable as a global, backed by $Runtime.PerfHooksCreateObserver.import { PerformanceObserver } from 'perf_hooks'
AsyncLocalStorageAvailable as a global, backed by $AsyncLocalStorage.import { AsyncLocalStorage } from 'async_hooks'

The underlying implementations are unchanged — only the import requirement is new. Behavior at the import site is identical to the previous global.

Additional behavioral divergence: path.win32.isAbsolute('/foo') returns false (matches WHATWG-like strictness — requires drive-letter + separator or UNC double-separator). Node returns true for any leading separator.

Known stdlib workarounds (tracked debt)

The following stdlib TS files carry workarounds for compiler gaps that surfaced during migration. Behavior is correct at the documented API surface; listed here so future fixes can remove them:

  • stdlib/node/process.ts (nextTick) and stdlib/node/timers.ts (setTimeout/setInterval/setImmediate) — arity-dispatch across 8 positional args because the built-in emitter doesn't expand Expr.Spread when forwarding to primitive methods. Payloads with >8 args are silently truncated.
  • stdlib/node/async_hooks.ts (run, exit) — drops the optional ...args parameter; the underlying SharpTSAsyncLocalStorage still supports it. No current tests exercise this path.

(Resolved #925: parameter defaults — reference and value type — and unset optional reference params now round-trip faithfully through $TSFunction.Invoke. The old param?: T + ?? and != null authoring workarounds have been retired from stdlib/CONTRIBUTING.md.)

Resolved: guest-error identity (2026-04-18 regression → fully resolved 2026-06-24)

  • Guest throw of a string value previously lost its Error identity when it crossed a host function frame: ThrowException.FromResult flattened a guest string throw to a plain CLR Exception, so a downstream catch (e) re-typed it (an error-prefixed string was bound as a typed Error instead of the verbatim string). The same-scope half was fixed in PR #906 (TimersPromises_SetInterval_AbortSignal_PreAborted no longer skipped). The cross-boundary residual is now fixed: ExecutionResult carries a FromGuestThrow origin bit, threaded so ThrowException.FromResult keeps a guest string throw as an identity-carrying ThrowException (only genuinely host-translated strings stay a plain Exception), and the re-catch derives fromHostException from the exception kind. Guest string throws now survive plain function-call, host-callback, and Promise-executor boundaries verbatim in the interpreter — matching compiled mode and Node. See SharpTS.Tests/SharedTests/CaughtErrorIdentityTests.cs.

Known Bugs

IL Compiler Limitations

  • Inner function declarations ✅ Inner function declarations (function inner() {} inside another function) are now fully supported with hoisting, closure capture, and recursion.

Type Checker Limitations

  • Type alias declarations are lazily validated - errors in type alias definitions (e.g., type R = ReturnType<string, number>; with wrong arg count) are only caught when the alias is used, not at declaration time. TypeScript catches these at declaration.

Recently Fixed Bugs (2026-02-10)

  • typeof on undeclared variables throws - Fixed: typeof undeclaredVar now returns "undefined" instead of throwing, matching JavaScript spec. Works in type checker, interpreter, and all compiler emitters (including async/generator state machines).

Recently Fixed Bugs (2026-02-05)

  • Property descriptors in compiled mode - Fixed: Object.defineProperty() and Object.getOwnPropertyDescriptor() now fully support accessor properties (get/set) and descriptor flags (writable, enumerable, configurable) in compiled mode via PropertyDescriptorStore.

Recently Fixed Bugs (2026-02-04)

  • Spreading iterators - Fixed: Type checker now allows spreading any iterable type ([...arr.entries()], [...mySet], [...myMap], [..."hello"], [...generator()]).
  • Destructuring in for...of declarations - Fixed: Parser now supports for (const [i, val] of arr.entries()) and for (const {x, y} of items). Desugars to temp variable with body destructuring.
  • Method chaining on new expressions - Fixed: Parser now correctly allows method chaining directly after new expressions (e.g., new Date().toISOString())
  • String concatenation optimizer incorrect stringification - Fixed: IL compiler's string concat optimizer now calls Stringify() instead of relying on .NET's ToString(), ensuring JavaScript-style output (null → "null", true → "true" not "True")

Recently Fixed Bugs (2026-01-21)

  • Object literal accessor this type inference - Fixed: this in getter/setter bodies now correctly infers the object's type instead of defaulting to any; uses two-pass type checking with literal type widening
  • any + any returning bigint - Fixed: Binary operators now return any when either operand is any, not bigint
  • Spread properties ignored in compiled object literals with accessors - Fixed: MergeIntoTSObject runtime method properly merges spread properties into $Object instances

Recently Fixed Bugs (2026-01-13)

  • yield await expr NullReferenceException - Fixed: State analyzer now assigns yield state before visiting nested await, matching emitter execution order
  • Generator variable capture for module-level variables - Fixed: Generators correctly capture and use module-level variables including with yield*
  • Class expression constructors with default parameters - Fixed: IL compiler now uses direct newobj with constructor builder instead of Activator.CreateInstance

Recently Fixed Bugs (2026-01-12)

  • Generic types with array suffix - Fixed: ParseGenericTypeReference() now properly finds matching > and handles array suffixes (Partial<T>[], Promise<number>[][], etc.)

Recently Fixed Bugs (2026-01-06)

  • Math.round() JS parity - Fixed: Now uses Math.Floor(x + 0.5) for JavaScript-compatible rounding (half-values toward +∞)
  • Object method this binding - Fixed: { fn() { return this.x; } } now correctly binds this in compiled code via __this parameter