diff --git a/package.json b/package.json index 3d3d528..775e511 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tiberjs/runner", - "version": "0.3.0", + "version": "0.3.1", "description": "Job-based structured concurrency, supervision, declarative task groups, and immutable execution context.", "type": "module", "main": "./dist/index.js", diff --git a/src/execution/context/frame.ts b/src/execution/context/frame.ts index cb5fc53..83658b9 100644 --- a/src/execution/context/frame.ts +++ b/src/execution/context/frame.ts @@ -1,41 +1,11 @@ import type { ContextEntry } from "./key.js"; -/** What a frame needs from its own bindings; `Map` satisfies it for many, one object for one. */ -interface Bindings { - has(key: PropertyKey): boolean; - get(key: PropertyKey): unknown; - keys(): Iterable; -} - -/** The common case — one binding per frame — without a hash table. */ -class SingleBinding implements Bindings { - constructor( - private readonly key: PropertyKey, - private readonly value: unknown, - ) {} - - has(key: PropertyKey): boolean { - return key === this.key; - } - - get(key: PropertyKey): unknown { - return key === this.key ? this.value : undefined; - } - - *keys(): Iterable { - yield this.key; - } -} - -function bindingsOf(entries: readonly ContextEntry[]): Bindings { - if (entries.length === 1) { - const [key, value] = entries[0]!; - return new SingleBinding(key.id, value); - } +function entryMap(entries: readonly ContextEntry[]): Map { const values = new Map(); for (const [key, value] of entries) { values.set(key.id, value); } + return values; } @@ -49,9 +19,9 @@ function bindingsOf(entries: readonly ContextEntry[]): Bindings { */ export class ContextFrame { readonly #parent: ContextFrame | null; - readonly #own: Bindings; + readonly #own: ReadonlyMap; - private constructor(parent: ContextFrame | null, own: Bindings) { + private constructor(parent: ContextFrame | null, own: ReadonlyMap) { this.#parent = parent; this.#own = own; } @@ -61,7 +31,7 @@ export class ContextFrame { /** Create a root frame containing the supplied context bindings. */ static from(entries: readonly ContextEntry[]): ContextFrame { - return entries.length === 0 ? ContextFrame.empty : new ContextFrame(null, bindingsOf(entries)); + return entries.length === 0 ? ContextFrame.empty : new ContextFrame(null, entryMap(entries)); } get(key: PropertyKey): unknown { @@ -92,20 +62,18 @@ export class ContextFrame { if (keys.length === 0) { return this; } - if (keys.length === 1) { - const key = keys[0]!; - return new ContextFrame(this, new SingleBinding(key, values[key])); - } + const own = new Map(); for (const key of keys) { - own.set(key, values[key]); + own.set(key, (values as Record)[key]); } + return new ContextFrame(this, own); } /** Return a child frame containing the supplied context bindings. */ withEntries(entries: readonly ContextEntry[]): ContextFrame { - return entries.length === 0 ? this : new ContextFrame(this, bindingsOf(entries)); + return entries.length === 0 ? this : new ContextFrame(this, entryMap(entries)); } keys(): IterableIterator {