diff options
author | Kitson Kelly <me@kitsonkelly.com> | 2020-07-11 12:38:15 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-10 22:38:15 -0400 |
commit | 40d081d3d9f64bcd2524da86fb78808ac1d7b888 (patch) | |
tree | 2232fda10c06d80d749f975b691974c506caa63d /cli/js | |
parent | d01eb6d9c506eef765fde8e40f9b90619b2ec83c (diff) |
feat: add performance user timing APIs (#6421)
Diffstat (limited to 'cli/js')
-rw-r--r-- | cli/js/globals.ts | 8 | ||||
-rw-r--r-- | cli/js/lib.deno.ns.d.ts | 44 | ||||
-rw-r--r-- | cli/js/lib.deno.shared_globals.d.ts | 94 | ||||
-rw-r--r-- | cli/js/web/performance.ts | 332 | ||||
-rw-r--r-- | cli/js/web/streams/internals.ts | 8 | ||||
-rw-r--r-- | cli/js/web/streams/queuing_strategy.ts | 2 | ||||
-rw-r--r-- | cli/js/web/streams/readable_byte_stream_controller.ts | 2 | ||||
-rw-r--r-- | cli/js/web/streams/readable_stream.ts | 2 | ||||
-rw-r--r-- | cli/js/web/streams/readable_stream_default_controller.ts | 2 | ||||
-rw-r--r-- | cli/js/web/streams/readable_stream_default_reader.ts | 2 | ||||
-rw-r--r-- | cli/js/web/streams/transform_stream.ts | 2 | ||||
-rw-r--r-- | cli/js/web/streams/transform_stream_default_controller.ts | 2 | ||||
-rw-r--r-- | cli/js/web/streams/writable_stream.ts | 2 | ||||
-rw-r--r-- | cli/js/web/streams/writable_stream_default_controller.ts | 2 | ||||
-rw-r--r-- | cli/js/web/streams/writable_stream_default_writer.ts | 2 | ||||
-rw-r--r-- | cli/js/web/util.ts | 8 |
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 }); +} |