summaryrefslogtreecommitdiff
path: root/cli/js
diff options
context:
space:
mode:
Diffstat (limited to 'cli/js')
-rw-r--r--cli/js/globals.ts8
-rw-r--r--cli/js/lib.deno.ns.d.ts44
-rw-r--r--cli/js/lib.deno.shared_globals.d.ts94
-rw-r--r--cli/js/web/performance.ts332
-rw-r--r--cli/js/web/streams/internals.ts8
-rw-r--r--cli/js/web/streams/queuing_strategy.ts2
-rw-r--r--cli/js/web/streams/readable_byte_stream_controller.ts2
-rw-r--r--cli/js/web/streams/readable_stream.ts2
-rw-r--r--cli/js/web/streams/readable_stream_default_controller.ts2
-rw-r--r--cli/js/web/streams/readable_stream_default_reader.ts2
-rw-r--r--cli/js/web/streams/transform_stream.ts2
-rw-r--r--cli/js/web/streams/transform_stream_default_controller.ts2
-rw-r--r--cli/js/web/streams/writable_stream.ts2
-rw-r--r--cli/js/web/streams/writable_stream_default_controller.ts2
-rw-r--r--cli/js/web/streams/writable_stream_default_writer.ts2
-rw-r--r--cli/js/web/util.ts8
16 files changed, 490 insertions, 24 deletions
diff --git a/cli/js/globals.ts b/cli/js/globals.ts
index da6288bd2..394460848 100644
--- a/cli/js/globals.ts
+++ b/cli/js/globals.ts
@@ -18,7 +18,6 @@ import * as fetchTypes from "./web/fetch.ts";
import * as headers from "./web/headers.ts";
import * as navigator from "./web/navigator.ts";
import * as permissions from "./web/permissions.ts";
-import * as performanceUtil from "./web/performance.ts";
import type * as promiseTypes from "./web/promise.ts";
import * as queuingStrategy from "./web/streams/queuing_strategy.ts";
import * as readableStream from "./web/streams/readable_stream.ts";
@@ -29,6 +28,7 @@ import * as transformStream from "./web/streams/transform_stream.ts";
import * as url from "./web/url.ts";
import * as urlSearchParams from "./web/url_search_params.ts";
import * as workers from "./web/workers.ts";
+import * as performance from "./web/performance.ts";
import * as writableStream from "./web/streams/writable_stream.ts";
// These imports are not exposed and therefore are fine to just import the
@@ -234,12 +234,16 @@ export const windowOrWorkerGlobalScopeProperties = {
Headers: nonEnumerable(headers.HeadersImpl),
navigator: nonEnumerable(new navigator.NavigatorImpl()),
Navigator: nonEnumerable(navigator.NavigatorImpl),
- performance: writable(new performanceUtil.Performance()),
Permissions: nonEnumerable(permissions.PermissionsImpl),
PermissionStatus: nonEnumerable(permissions.PermissionStatusImpl),
ReadableStream: nonEnumerable(readableStream.ReadableStreamImpl),
Request: nonEnumerable(request.Request),
Response: nonEnumerable(fetchTypes.Response),
+ performance: writable(new performance.PerformanceImpl()),
+ Performance: nonEnumerable(performance.PerformanceImpl),
+ PerformanceEntry: nonEnumerable(performance.PerformanceEntryImpl),
+ PerformanceMark: nonEnumerable(performance.PerformanceMarkImpl),
+ PerformanceMeasure: nonEnumerable(performance.PerformanceMeasureImpl),
TextDecoder: nonEnumerable(textEncoding.TextDecoder),
TextEncoder: nonEnumerable(textEncoding.TextEncoder),
TransformStream: nonEnumerable(transformStream.TransformStreamImpl),
diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts
index 0b46a0c4d..41243d0ca 100644
--- a/cli/js/lib.deno.ns.d.ts
+++ b/cli/js/lib.deno.ns.d.ts
@@ -3,6 +3,9 @@
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
+/** Deno provides extra properties on `import.meta`. These are included here
+ * to ensure that these are still available when using the Deno namepsace in
+ * conjunction with other type libs, like `dom`. */
declare interface ImportMeta {
/** A string representation of the fully qualified module URL. */
url: string;
@@ -19,6 +22,47 @@ declare interface ImportMeta {
main: boolean;
}
+/** Deno supports user timing Level 3 (see: https://w3c.github.io/user-timing)
+ * which is not widely supported yet in other runtimes. These types are here
+ * so that these features are still available when using the Deno namespace
+ * in conjunction with other type libs, like `dom`. */
+declare interface Performance {
+ /** Stores a timestamp with the associated name (a "mark"). */
+ mark(markName: string, options?: PerformanceMarkOptions): PerformanceMark;
+
+ /** Stores the `DOMHighResTimeStamp` duration between two marks along with the
+ * associated name (a "measure"). */
+ measure(
+ measureName: string,
+ options?: PerformanceMeasureOptions
+ ): PerformanceMeasure;
+}
+
+declare interface PerformanceMarkOptions {
+ /** Metadata to be included in the mark. */
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ detail?: any;
+
+ /** Timestamp to be used as the mark time. */
+ startTime?: number;
+}
+
+declare interface PerformanceMeasureOptions {
+ /** Metadata to be included in the measure. */
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ detail?: any;
+
+ /** Timestamp to be used as the start time or string to be used as start
+ * mark.*/
+ start?: string | number;
+
+ /** Duration between the start and end times. */
+ duration?: number;
+
+ /** Timestamp to be used as the end time or string to be used as end mark. */
+ end?: string | number;
+}
+
declare interface Permissions {
/** Resolves to the current status of a permission.
*
diff --git a/cli/js/lib.deno.shared_globals.d.ts b/cli/js/lib.deno.shared_globals.d.ts
index 3492c0da1..893af8bbe 100644
--- a/cli/js/lib.deno.shared_globals.d.ts
+++ b/cli/js/lib.deno.shared_globals.d.ts
@@ -1337,7 +1337,36 @@ declare class Worker extends EventTarget {
terminate(): void;
}
-declare namespace performance {
+declare type PerformanceEntryList = PerformanceEntry[];
+
+declare interface Performance {
+ /** Removes the stored timestamp with the associated name. */
+ clearMarks(markName?: string): void;
+
+ /** Removes stored timestamp with the associated name. */
+ clearMeasures(measureName?: string): void;
+
+ getEntries(): PerformanceEntryList;
+ getEntriesByName(name: string, type?: string): PerformanceEntryList;
+ getEntriesByType(type: string): PerformanceEntryList;
+
+ /** Stores a timestamp with the associated name (a "mark"). */
+ mark(markName: string, options?: PerformanceMarkOptions): PerformanceMark;
+
+ /** Stores the `DOMHighResTimeStamp` duration between two marks along with the
+ * associated name (a "measure"). */
+ measure(
+ measureName: string,
+ options?: PerformanceMeasureOptions
+ ): PerformanceMeasure;
+ /** Stores the `DOMHighResTimeStamp` duration between two marks along with the
+ * associated name (a "measure"). */
+ measure(
+ measureName: string,
+ startMark?: string,
+ endMark?: string
+ ): PerformanceMeasure;
+
/** Returns a current time from Deno's start in milliseconds.
*
* Use the permission flag `--allow-hrtime` return a precise value.
@@ -1347,7 +1376,68 @@ declare namespace performance {
* console.log(`${t} ms since start!`);
* ```
*/
- export function now(): number;
+ now(): number;
+}
+
+declare const Performance: {
+ prototype: Performance;
+ new (): Performance;
+};
+
+declare const performance: Performance;
+
+declare interface PerformanceMarkOptions {
+ /** Metadata to be included in the mark. */
+ detail?: any;
+
+ /** Timestamp to be used as the mark time. */
+ startTime?: number;
+}
+
+declare interface PerformanceMeasureOptions {
+ /** Metadata to be included in the measure. */
+ detail?: any;
+
+ /** Timestamp to be used as the start time or string to be used as start
+ * mark.*/
+ start?: string | number;
+
+ /** Duration between the start and end times. */
+ duration?: number;
+
+ /** Timestamp to be used as the end time or string to be used as end mark. */
+ end?: string | number;
+}
+
+/** Encapsulates a single performance metric that is part of the performance
+ * timeline. A performance entry can be directly created by making a performance
+ * mark or measure (for example by calling the `.mark()` method) at an explicit
+ * point in an application. */
+declare class PerformanceEntry {
+ readonly duration: number;
+ readonly entryType: string;
+ readonly name: string;
+ readonly startTime: number;
+ toJSON(): any;
+}
+
+/** `PerformanceMark` is an abstract interface for `PerformanceEntry` objects
+ * with an entryType of `"mark"`. Entries of this type are created by calling
+ * `performance.mark()` to add a named `DOMHighResTimeStamp` (the mark) to the
+ * performance timeline. */
+declare class PerformanceMark extends PerformanceEntry {
+ readonly detail: any;
+ readonly entryType: "mark";
+ constructor(name: string, options?: PerformanceMarkOptions);
+}
+
+/** `PerformanceMeasure` is an abstract interface for `PerformanceEntry` objects
+ * with an entryType of `"measure"`. Entries of this type are created by calling
+ * `performance.measure()` to add a named `DOMHighResTimeStamp` (the measure)
+ * between two marks to the performance timeline. */
+declare class PerformanceMeasure extends PerformanceEntry {
+ readonly detail: any;
+ readonly entryType: "measure";
}
interface EventInit {
diff --git a/cli/js/web/performance.ts b/cli/js/web/performance.ts
index 67f8f1b6c..eb0479b37 100644
--- a/cli/js/web/performance.ts
+++ b/cli/js/web/performance.ts
@@ -1,10 +1,336 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { now as opNow } from "../ops/timers.ts";
+import { customInspect, inspect } from "./console.ts";
+import { cloneValue, setFunctionName } from "./util.ts";
+
+let performanceEntries: PerformanceEntryList = [];
+
+function findMostRecent(
+ name: string,
+ type: "mark" | "measure"
+): PerformanceEntry | undefined {
+ return performanceEntries
+ .slice()
+ .reverse()
+ .find((entry) => entry.name === name && entry.entryType === type);
+}
+
+function convertMarkToTimestamp(mark: string | number): number {
+ if (typeof mark === "string") {
+ const entry = findMostRecent(mark, "mark");
+ if (!entry) {
+ throw new SyntaxError(`Cannot find mark: "${mark}".`);
+ }
+ return entry.startTime;
+ }
+ if (mark < 0) {
+ throw new TypeError("Mark cannot be negative.");
+ }
+ return mark;
+}
+
+function filterByNameType(
+ name?: string,
+ type?: "mark" | "measure"
+): PerformanceEntryList {
+ return performanceEntries.filter(
+ (entry) =>
+ (name ? entry.name === name : true) &&
+ (type ? entry.entryType === type : true)
+ );
+}
+
+function now(): number {
+ const res = opNow();
+ return res.seconds * 1e3 + res.subsecNanos / 1e6;
+}
+
+export class PerformanceEntryImpl implements PerformanceEntry {
+ #name: string;
+ #entryType: string;
+ #startTime: number;
+ #duration: number;
+
+ get name(): string {
+ return this.#name;
+ }
+
+ get entryType(): string {
+ return this.#entryType;
+ }
+
+ get startTime(): number {
+ return this.#startTime;
+ }
+
+ get duration(): number {
+ return this.#duration;
+ }
+
+ constructor(
+ name: string,
+ entryType: string,
+ startTime: number,
+ duration: number
+ ) {
+ this.#name = name;
+ this.#entryType = entryType;
+ this.#startTime = startTime;
+ this.#duration = duration;
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ toJSON(): any {
+ return {
+ name: this.#name,
+ entryType: this.#entryType,
+ startTime: this.#startTime,
+ duration: this.#duration,
+ };
+ }
+
+ [customInspect](): string {
+ return `${this.constructor.name} { name: "${this.name}", entryType: "${this.entryType}", startTime: ${this.startTime}, duration: ${this.duration} }`;
+ }
+}
+
+export class PerformanceMarkImpl extends PerformanceEntryImpl
+ implements PerformanceMark {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ #detail: any;
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ get detail(): any {
+ return this.#detail;
+ }
+
+ get entryType(): "mark" {
+ return "mark";
+ }
+
+ constructor(
+ name: string,
+ { detail = null, startTime = now() }: PerformanceMarkOptions = {}
+ ) {
+ super(name, "mark", startTime, 0);
+ if (startTime < 0) {
+ throw new TypeError("startTime cannot be negative");
+ }
+ this.#detail = cloneValue(detail);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ toJSON(): any {
+ return {
+ name: this.name,
+ entryType: this.entryType,
+ startTime: this.startTime,
+ duration: this.duration,
+ detail: this.detail,
+ };
+ }
+
+ [customInspect](): string {
+ return this.detail
+ ? `${this.constructor.name} {\n detail: ${inspect(this.detail, {
+ depth: 3,
+ })},\n name: "${this.name}",\n entryType: "${
+ this.entryType
+ }",\n startTime: ${this.startTime},\n duration: ${this.duration}\n}`
+ : `${this.constructor.name} { detail: ${this.detail}, name: "${this.name}", entryType: "${this.entryType}", startTime: ${this.startTime}, duration: ${this.duration} }`;
+ }
+}
+
+export class PerformanceMeasureImpl extends PerformanceEntryImpl
+ implements PerformanceMeasure {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ #detail: any;
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ get detail(): any {
+ return this.#detail;
+ }
+
+ get entryType(): "measure" {
+ return "measure";
+ }
+
+ constructor(
+ name: string,
+ startTime: number,
+ duration: number,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ detail: any = null
+ ) {
+ super(name, "measure", startTime, duration);
+ this.#detail = cloneValue(detail);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ toJSON(): any {
+ return {
+ name: this.name,
+ entryType: this.entryType,
+ startTime: this.startTime,
+ duration: this.duration,
+ detail: this.detail,
+ };
+ }
+
+ [customInspect](): string {
+ return this.detail
+ ? `${this.constructor.name} {\n detail: ${inspect(this.detail, {
+ depth: 3,
+ })},\n name: "${this.name}",\n entryType: "${
+ this.entryType
+ }",\n startTime: ${this.startTime},\n duration: ${this.duration}\n}`
+ : `${this.constructor.name} { detail: ${this.detail}, name: "${this.name}", entryType: "${this.entryType}", startTime: ${this.startTime}, duration: ${this.duration} }`;
+ }
+}
+
+export class PerformanceImpl implements Performance {
+ clearMarks(markName?: string): void {
+ if (markName == null) {
+ performanceEntries = performanceEntries.filter(
+ (entry) => entry.entryType !== "mark"
+ );
+ } else {
+ performanceEntries = performanceEntries.filter(
+ (entry) => !(entry.name === markName && entry.entryType === "mark")
+ );
+ }
+ }
+
+ clearMeasures(measureName?: string): void {
+ if (measureName == null) {
+ performanceEntries = performanceEntries.filter(
+ (entry) => entry.entryType !== "measure"
+ );
+ } else {
+ performanceEntries = performanceEntries.filter(
+ (entry) =>
+ !(entry.name === measureName && entry.entryType === "measure")
+ );
+ }
+ }
+
+ getEntries(): PerformanceEntryList {
+ return filterByNameType();
+ }
+ getEntriesByName(
+ name: string,
+ type?: "mark" | "measure"
+ ): PerformanceEntryList {
+ return filterByNameType(name, type);
+ }
+ getEntriesByType(type: "mark" | "measure"): PerformanceEntryList {
+ return filterByNameType(undefined, type);
+ }
+
+ mark(
+ markName: string,
+ options: PerformanceMarkOptions = {}
+ ): PerformanceMark {
+ // 3.1.1.1 If the global object is a Window object and markName uses the
+ // same name as a read only attribute in the PerformanceTiming interface,
+ // throw a SyntaxError. - not implemented
+ const entry = new PerformanceMarkImpl(markName, options);
+ // 3.1.1.7 Queue entry - not implemented
+ performanceEntries.push(entry);
+ return entry;
+ }
+
+ measure(
+ measureName: string,
+ options?: PerformanceMeasureOptions
+ ): PerformanceMeasure;
+ measure(
+ measureName: string,
+ startMark?: string,
+ endMark?: string
+ ): PerformanceMeasure;
+ measure(
+ measureName: string,
+ startOrMeasureOptions: string | PerformanceMeasureOptions = {},
+ endMark?: string
+ ): PerformanceMeasure {
+ if (startOrMeasureOptions && typeof startOrMeasureOptions === "object") {
+ if (endMark) {
+ throw new TypeError("Options cannot be passed with endMark.");
+ }
+ if (
+ !("start" in startOrMeasureOptions) &&
+ !("end" in startOrMeasureOptions)
+ ) {
+ throw new TypeError("A start or end mark must be supplied in options.");
+ }
+ if (
+ "start" in startOrMeasureOptions &&
+ "duration" in startOrMeasureOptions &&
+ "end" in startOrMeasureOptions
+ ) {
+ throw new TypeError(
+ "Cannot specify start, end, and duration together in options."
+ );
+ }
+ }
+ let endTime: number;
+ if (endMark) {
+ endTime = convertMarkToTimestamp(endMark);
+ } else if (
+ typeof startOrMeasureOptions === "object" &&
+ "end" in startOrMeasureOptions
+ ) {
+ endTime = convertMarkToTimestamp(startOrMeasureOptions.end!);
+ } else if (
+ typeof startOrMeasureOptions === "object" &&
+ "start" in startOrMeasureOptions &&
+ "duration" in startOrMeasureOptions
+ ) {
+ const start = convertMarkToTimestamp(startOrMeasureOptions.start!);
+ const duration = convertMarkToTimestamp(startOrMeasureOptions.duration!);
+ endTime = start + duration;
+ } else {
+ endTime = now();
+ }
+ let startTime: number;
+ if (
+ typeof startOrMeasureOptions === "object" &&
+ "start" in startOrMeasureOptions
+ ) {
+ startTime = convertMarkToTimestamp(startOrMeasureOptions.start!);
+ } else if (
+ typeof startOrMeasureOptions === "object" &&
+ "end" in startOrMeasureOptions &&
+ "duration" in startOrMeasureOptions
+ ) {
+ const end = convertMarkToTimestamp(startOrMeasureOptions.end!);
+ const duration = convertMarkToTimestamp(startOrMeasureOptions.duration!);
+ startTime = end - duration;
+ } else if (typeof startOrMeasureOptions === "string") {
+ startTime = convertMarkToTimestamp(startOrMeasureOptions);
+ } else {
+ startTime = 0;
+ }
+ const entry = new PerformanceMeasureImpl(
+ measureName,
+ startTime,
+ endTime - startTime,
+ typeof startOrMeasureOptions === "object"
+ ? startOrMeasureOptions.detail ?? null
+ : null
+ );
+ performanceEntries.push(entry);
+ return entry;
+ }
-export class Performance {
now(): number {
- const res = opNow();
- return res.seconds * 1e3 + res.subsecNanos / 1e6;
+ return now();
}
}
+
+setFunctionName(PerformanceEntryImpl, "PerformanceEntry");
+setFunctionName(PerformanceMarkImpl, "PerformanceMark");
+setFunctionName(PerformanceMeasureImpl, "PerformanceMeasure");
+setFunctionName(PerformanceImpl, "Performance");
diff --git a/cli/js/web/streams/internals.ts b/cli/js/web/streams/internals.ts
index f6b20ccaf..58a62e3cb 100644
--- a/cli/js/web/streams/internals.ts
+++ b/cli/js/web/streams/internals.ts
@@ -19,7 +19,7 @@ import { WritableStreamDefaultWriterImpl } from "./writable_stream_default_write
import { WritableStreamImpl } from "./writable_stream.ts";
import { AbortSignalImpl } from "../abort_signal.ts";
import { DOMExceptionImpl as DOMException } from "../dom_exception.ts";
-import { cloneValue } from "../util.ts";
+import { cloneValue, setFunctionName } from "../util.ts";
import { assert, AssertionError } from "../../util.ts";
export type AbortAlgorithm = (reason?: any) => PromiseLike<void>;
@@ -1320,12 +1320,6 @@ export function resetQueue<R>(container: Container<R>): void {
container[sym.queueTotalSize] = 0;
}
-/** An internal function which provides a function name for some generated
- * functions, so stack traces are a bit more readable. */
-export function setFunctionName(fn: Function, value: string): void {
- Object.defineProperty(fn, "name", { value, configurable: true });
-}
-
/** An internal function which mimics the behavior of setting the promise to
* handled in JavaScript. In this situation, an assertion failure, which
* shouldn't happen will get thrown, instead of swallowed. */
diff --git a/cli/js/web/streams/queuing_strategy.ts b/cli/js/web/streams/queuing_strategy.ts
index d2717874e..8aa30e142 100644
--- a/cli/js/web/streams/queuing_strategy.ts
+++ b/cli/js/web/streams/queuing_strategy.ts
@@ -1,7 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { setFunctionName } from "./internals.ts";
import { customInspect } from "../console.ts";
+import { setFunctionName } from "../util.ts";
export class CountQueuingStrategyImpl implements CountQueuingStrategy {
highWaterMark: number;
diff --git a/cli/js/web/streams/readable_byte_stream_controller.ts b/cli/js/web/streams/readable_byte_stream_controller.ts
index 65409dc1e..4a7ffae12 100644
--- a/cli/js/web/streams/readable_byte_stream_controller.ts
+++ b/cli/js/web/streams/readable_byte_stream_controller.ts
@@ -18,12 +18,12 @@ import {
readableStreamHasDefaultReader,
readableStreamGetNumReadRequests,
readableStreamCreateReadResult,
- setFunctionName,
} from "./internals.ts";
import type { ReadableStreamImpl } from "./readable_stream.ts";
import * as sym from "./symbols.ts";
import { assert } from "../../util.ts";
import { customInspect } from "../console.ts";
+import { setFunctionName } from "../util.ts";
export class ReadableByteStreamControllerImpl
implements ReadableByteStreamController {
diff --git a/cli/js/web/streams/readable_stream.ts b/cli/js/web/streams/readable_stream.ts
index 3191c0859..cf730d23a 100644
--- a/cli/js/web/streams/readable_stream.ts
+++ b/cli/js/web/streams/readable_stream.ts
@@ -9,7 +9,6 @@ import {
isWritableStream,
isWritableStreamLocked,
makeSizeAlgorithmFromSizeFunction,
- setFunctionName,
setPromiseIsHandledToTrue,
readableStreamCancel,
ReadableStreamGenericReader,
@@ -25,6 +24,7 @@ import type { ReadableStreamDefaultControllerImpl } from "./readable_stream_defa
import * as sym from "./symbols.ts";
import { customInspect } from "../console.ts";
import { AbortSignalImpl } from "../abort_signal.ts";
+import { setFunctionName } from "../util.ts";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class ReadableStreamImpl<R = any> implements ReadableStream<R> {
diff --git a/cli/js/web/streams/readable_stream_default_controller.ts b/cli/js/web/streams/readable_stream_default_controller.ts
index 47cb719c7..066bc8a8f 100644
--- a/cli/js/web/streams/readable_stream_default_controller.ts
+++ b/cli/js/web/streams/readable_stream_default_controller.ts
@@ -18,11 +18,11 @@ import {
readableStreamDefaultControllerGetDesiredSize,
resetQueue,
SizeAlgorithm,
- setFunctionName,
} from "./internals.ts";
import type { ReadableStreamImpl } from "./readable_stream.ts";
import * as sym from "./symbols.ts";
import { customInspect } from "../console.ts";
+import { setFunctionName } from "../util.ts";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class ReadableStreamDefaultControllerImpl<R = any>
diff --git a/cli/js/web/streams/readable_stream_default_reader.ts b/cli/js/web/streams/readable_stream_default_reader.ts
index 01b679cd3..4ed0a5c7c 100644
--- a/cli/js/web/streams/readable_stream_default_reader.ts
+++ b/cli/js/web/streams/readable_stream_default_reader.ts
@@ -9,11 +9,11 @@ import {
readableStreamReaderGenericCancel,
readableStreamReaderGenericInitialize,
readableStreamReaderGenericRelease,
- setFunctionName,
} from "./internals.ts";
import type { ReadableStreamImpl } from "./readable_stream.ts";
import * as sym from "./symbols.ts";
import { customInspect } from "../console.ts";
+import { setFunctionName } from "../util.ts";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class ReadableStreamDefaultReaderImpl<R = any>
diff --git a/cli/js/web/streams/transform_stream.ts b/cli/js/web/streams/transform_stream.ts
index 548a20b38..1c63a553b 100644
--- a/cli/js/web/streams/transform_stream.ts
+++ b/cli/js/web/streams/transform_stream.ts
@@ -7,7 +7,6 @@ import {
invokeOrNoop,
isTransformStream,
makeSizeAlgorithmFromSizeFunction,
- setFunctionName,
setUpTransformStreamDefaultControllerFromTransformer,
validateAndNormalizeHighWaterMark,
} from "./internals.ts";
@@ -16,6 +15,7 @@ import * as sym from "./symbols.ts";
import type { TransformStreamDefaultControllerImpl } from "./transform_stream_default_controller.ts";
import type { WritableStreamImpl } from "./writable_stream.ts";
import { customInspect, inspect } from "../console.ts";
+import { setFunctionName } from "../util.ts";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class TransformStreamImpl<I = any, O = any>
diff --git a/cli/js/web/streams/transform_stream_default_controller.ts b/cli/js/web/streams/transform_stream_default_controller.ts
index 78beaf879..22087fb0b 100644
--- a/cli/js/web/streams/transform_stream_default_controller.ts
+++ b/cli/js/web/streams/transform_stream_default_controller.ts
@@ -4,7 +4,6 @@ import {
FlushAlgorithm,
isTransformStreamDefaultController,
readableStreamDefaultControllerGetDesiredSize,
- setFunctionName,
TransformAlgorithm,
transformStreamDefaultControllerEnqueue,
transformStreamDefaultControllerError,
@@ -14,6 +13,7 @@ import type { ReadableStreamDefaultControllerImpl } from "./readable_stream_defa
import * as sym from "./symbols.ts";
import type { TransformStreamImpl } from "./transform_stream.ts";
import { customInspect } from "../console.ts";
+import { setFunctionName } from "../util.ts";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class TransformStreamDefaultControllerImpl<I = any, O = any>
diff --git a/cli/js/web/streams/writable_stream.ts b/cli/js/web/streams/writable_stream.ts
index 8a31f512d..2dea5311b 100644
--- a/cli/js/web/streams/writable_stream.ts
+++ b/cli/js/web/streams/writable_stream.ts
@@ -8,7 +8,6 @@ import {
isWritableStream,
isWritableStreamLocked,
makeSizeAlgorithmFromSizeFunction,
- setFunctionName,
setUpWritableStreamDefaultControllerFromUnderlyingSink,
writableStreamAbort,
writableStreamClose,
@@ -19,6 +18,7 @@ import * as sym from "./symbols.ts";
import type { WritableStreamDefaultControllerImpl } from "./writable_stream_default_controller.ts";
import type { WritableStreamDefaultWriterImpl } from "./writable_stream_default_writer.ts";
import { customInspect } from "../console.ts";
+import { setFunctionName } from "../util.ts";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class WritableStreamImpl<W = any> implements WritableStream<W> {
diff --git a/cli/js/web/streams/writable_stream_default_controller.ts b/cli/js/web/streams/writable_stream_default_controller.ts
index b957c2c8f..0fe5f7ef9 100644
--- a/cli/js/web/streams/writable_stream_default_controller.ts
+++ b/cli/js/web/streams/writable_stream_default_controller.ts
@@ -6,7 +6,6 @@ import {
isWritableStreamDefaultController,
Pair,
resetQueue,
- setFunctionName,
SizeAlgorithm,
WriteAlgorithm,
writableStreamDefaultControllerClearAlgorithms,
@@ -15,6 +14,7 @@ import {
import * as sym from "./symbols.ts";
import type { WritableStreamImpl } from "./writable_stream.ts";
import { customInspect } from "../console.ts";
+import { setFunctionName } from "../util.ts";
export class WritableStreamDefaultControllerImpl<W>
implements WritableStreamDefaultController {
diff --git a/cli/js/web/streams/writable_stream_default_writer.ts b/cli/js/web/streams/writable_stream_default_writer.ts
index 09b47c69f..2e19af923 100644
--- a/cli/js/web/streams/writable_stream_default_writer.ts
+++ b/cli/js/web/streams/writable_stream_default_writer.ts
@@ -6,7 +6,6 @@ import {
isWritableStream,
isWritableStreamDefaultWriter,
isWritableStreamLocked,
- setFunctionName,
setPromiseIsHandledToTrue,
writableStreamCloseQueuedOrInFlight,
writableStreamDefaultWriterAbort,
@@ -19,6 +18,7 @@ import * as sym from "./symbols.ts";
import type { WritableStreamImpl } from "./writable_stream.ts";
import { customInspect } from "../console.ts";
import { assert } from "../../util.ts";
+import { setFunctionName } from "../util.ts";
export class WritableStreamDefaultWriterImpl<W>
implements WritableStreamDefaultWriter<W> {
diff --git a/cli/js/web/util.ts b/cli/js/web/util.ts
index 53ff8ef22..281048cd8 100644
--- a/cli/js/web/util.ts
+++ b/cli/js/web/util.ts
@@ -208,3 +208,11 @@ export function getHeaderValueParams(value: string): Map<string, string> {
export function hasHeaderValueOf(s: string, value: string): boolean {
return new RegExp(`^${value}[\t\s]*;?`).test(s);
}
+
+/** An internal function which provides a function name for some generated
+ * functions, so stack traces are a bit more readable.
+ *
+ * @internal */
+export function setFunctionName(fn: Function, value: string): void {
+ Object.defineProperty(fn, "name", { value, configurable: true });
+}