diff --git a/lib/scope-internal.ts b/lib/scope-internal.ts index 9351d0a81..b933b890d 100644 --- a/lib/scope-internal.ts +++ b/lib/scope-internal.ts @@ -5,6 +5,54 @@ import { createTask } from "./task.ts"; import type { Context, Operation, Scope, Task } from "./types.ts"; +// Shared prototype so all scope instances have the same hidden class, +// avoiding deoptimization when V8 encounters differently-shaped scope objects. +const scopePrototype = { + [Symbol.toStringTag]: "Scope", + get(this: ScopeInternal, context: Context): T | undefined { + return (this.contexts[context.name] ?? context.defaultValue) as + | T + | undefined; + }, + set(this: ScopeInternal, context: Context, value: T): T { + return this.contexts[context.name] = value; + }, + expect(this: ScopeInternal, context: Context): T { + let value = this.get(context); + if (typeof value === "undefined") { + let error = new Error(context.name); + error.name = `MissingContextError`; + throw error; + } + return value; + }, + delete(this: ScopeInternal, context: Context): boolean { + return delete this.contexts[context.name]; + }, + hasOwn(this: ScopeInternal, context: Context): boolean { + return !!Reflect.getOwnPropertyDescriptor(this.contexts, context.name); + }, + run(this: ScopeInternal, operation: () => Operation): Task { + return createTask({ owner: this, operation }); + }, + spawn( + this: ScopeInternal, + operation: () => Operation, + ): Operation> { + // deno-lint-ignore no-this-alias + let owner = this; + return { + *[Symbol.iterator]() { + return createTask({ owner, operation }); + }, + }; + }, + ensure(this: ScopeInternal, op: () => Operation): () => void { + this.destructors.add(op); + return () => this.destructors.delete(op); + }, +}; + export function createScopeInternal( parent?: Scope, ): [ScopeInternal, () => Operation] { @@ -14,46 +62,9 @@ export function createScopeInternal( let contexts: Record = Object.create( parent ? (parent as ScopeInternal).contexts : null, ); - let scope: ScopeInternal = Object.create({ - [Symbol.toStringTag]: "Scope", - contexts, - get(context: Context): T | undefined { - return (contexts[context.name] ?? context.defaultValue) as T | undefined; - }, - set(context: Context, value: T): T { - return contexts[context.name] = value; - }, - expect(context: Context): T { - let value = scope.get(context); - if (typeof value === "undefined") { - let error = new Error(context.name); - error.name = `MissingContextError`; - throw error; - } - return value; - }, - delete(context: Context): boolean { - return delete contexts[context.name]; - }, - hasOwn(context: Context): boolean { - return !!Reflect.getOwnPropertyDescriptor(contexts, context.name); - }, - run(operation: () => Operation): Task { - return createTask({ owner: scope, operation }); - }, - spawn(operation: () => Operation): Operation> { - return { - *[Symbol.iterator]() { - return createTask({ owner: scope, operation }); - }, - }; - }, - - ensure(op: () => Operation): () => void { - destructors.add(op); - return () => destructors.delete(op); - }, - }); + let scope: ScopeInternal = Object.create(scopePrototype); + scope.contexts = contexts; + scope.destructors = destructors; scope.set(Priority, scope.expect(Priority) + 1); scope.set(Children, new Set()); @@ -97,5 +108,6 @@ export function createScopeInternal( export interface ScopeInternal extends Scope, AsyncDisposable { contexts: Record; + destructors: Set<() => Operation>; ensure(op: () => Operation): () => void; } diff --git a/www/assets/prism-atom-one-dark.css b/www/assets/prism-atom-one-dark.css index 653e01920..6999c4fc1 100644 --- a/www/assets/prism-atom-one-dark.css +++ b/www/assets/prism-atom-one-dark.css @@ -24,11 +24,11 @@ pre { margin-right: -16px; border-left: 4px solid rgba( - 0, - 0, - 0, - 0 - ); /* Set placeholder for highlight accent border color to transparent */ + 0, + 0, + 0, + 0 + ); /* Set placeholder for highlight accent border color to transparent */ } .code-line.inserted { @@ -275,10 +275,7 @@ pre[class*="language-"] { color: var(--prism-hue-3); } -.language-javascript - .token.template-string - > .token.interpolation - > .token.interpolation-punctuation.punctuation { +.language-javascript .token.template-string > .token.interpolation > .token.interpolation-punctuation.punctuation { color: var(--prism-hue-5-2); } @@ -406,9 +403,7 @@ div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus { /* Hovering over a linkable line number (in the gutter area) */ /* Requires Line Numbers plugin as well */ -pre[id].linkable-line-numbers.linkable-line-numbers - span.line-numbers-rows - > span:hover:before { +pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before { background-color: var(--prism-syntax-cursor-line); } diff --git a/www/blog/2026-02-06-structured-concurrency-for-javascript/structured-concurrency-js.svg b/www/blog/2026-02-06-structured-concurrency-for-javascript/structured-concurrency-js.svg index 92e46fce7..7cc68bff2 100644 --- a/www/blog/2026-02-06-structured-concurrency-for-javascript/structured-concurrency-js.svg +++ b/www/blog/2026-02-06-structured-concurrency-for-javascript/structured-concurrency-js.svg @@ -133,7 +133,8 @@ /> - + } + diff --git a/www/blog/2026-02-13-abortcontroller-abort-doesnt-mean-it-stopped/abortcontroller-abort.svg b/www/blog/2026-02-13-abortcontroller-abort-doesnt-mean-it-stopped/abortcontroller-abort.svg index 708d102db..4108b853d 100644 --- a/www/blog/2026-02-13-abortcontroller-abort-doesnt-mean-it-stopped/abortcontroller-abort.svg +++ b/www/blog/2026-02-13-abortcontroller-abort-doesnt-mean-it-stopped/abortcontroller-abort.svg @@ -94,7 +94,8 @@ /> - + } + diff --git a/www/blog/2026-04-07-strict-structured-concurrency/foreground-background.svg b/www/blog/2026-04-07-strict-structured-concurrency/foreground-background.svg index 85bf4c607..c7fb6cc59 100644 --- a/www/blog/2026-04-07-strict-structured-concurrency/foreground-background.svg +++ b/www/blog/2026-04-07-strict-structured-concurrency/foreground-background.svg @@ -114,7 +114,8 @@ - + .svg-annotation { + fill: #9ca3af; + } + } + diff --git a/www/blog/2026-04-07-strict-structured-concurrency/strict-structured-concurrency.svg b/www/blog/2026-04-07-strict-structured-concurrency/strict-structured-concurrency.svg index ab29bfd54..bf430dc05 100644 --- a/www/blog/2026-04-07-strict-structured-concurrency/strict-structured-concurrency.svg +++ b/www/blog/2026-04-07-strict-structured-concurrency/strict-structured-concurrency.svg @@ -152,7 +152,8 @@ - + } + diff --git a/www/blog/blog-image-template.svg b/www/blog/blog-image-template.svg index d6212a3a5..ddf3f8f24 100644 --- a/www/blog/blog-image-template.svg +++ b/www/blog/blog-image-template.svg @@ -148,7 +148,8 @@ /> - + } +