Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
50 changes: 9 additions & 41 deletions src/execution/context/frame.ts
Original file line number Diff line number Diff line change
@@ -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<PropertyKey>;
}

/** 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<PropertyKey> {
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<PropertyKey, unknown> {
const values = new Map<PropertyKey, unknown>();
for (const [key, value] of entries) {
values.set(key.id, value);
}

return values;
}

Expand All @@ -49,9 +19,9 @@ function bindingsOf(entries: readonly ContextEntry[]): Bindings {
*/
export class ContextFrame {
readonly #parent: ContextFrame | null;
readonly #own: Bindings;
readonly #own: ReadonlyMap<PropertyKey, unknown>;

private constructor(parent: ContextFrame | null, own: Bindings) {
private constructor(parent: ContextFrame | null, own: ReadonlyMap<PropertyKey, unknown>) {
this.#parent = parent;
this.#own = own;
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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<PropertyKey, unknown>();
for (const key of keys) {
own.set(key, values[key]);
own.set(key, (values as Record<PropertyKey, unknown>)[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<PropertyKey> {
Expand Down