mirror of
https://github.com/denoland/deno.git
synced 2025-09-30 14:11:14 +00:00
feat: add performance user timing APIs (#6421)
This commit is contained in:
parent
d01eb6d9c5
commit
40d081d3d9
17 changed files with 536 additions and 26 deletions
|
@ -18,7 +18,6 @@ import * as fetchTypes from "./web/fetch.ts";
|
||||||
import * as headers from "./web/headers.ts";
|
import * as headers from "./web/headers.ts";
|
||||||
import * as navigator from "./web/navigator.ts";
|
import * as navigator from "./web/navigator.ts";
|
||||||
import * as permissions from "./web/permissions.ts";
|
import * as permissions from "./web/permissions.ts";
|
||||||
import * as performanceUtil from "./web/performance.ts";
|
|
||||||
import type * as promiseTypes from "./web/promise.ts";
|
import type * as promiseTypes from "./web/promise.ts";
|
||||||
import * as queuingStrategy from "./web/streams/queuing_strategy.ts";
|
import * as queuingStrategy from "./web/streams/queuing_strategy.ts";
|
||||||
import * as readableStream from "./web/streams/readable_stream.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 url from "./web/url.ts";
|
||||||
import * as urlSearchParams from "./web/url_search_params.ts";
|
import * as urlSearchParams from "./web/url_search_params.ts";
|
||||||
import * as workers from "./web/workers.ts";
|
import * as workers from "./web/workers.ts";
|
||||||
|
import * as performance from "./web/performance.ts";
|
||||||
import * as writableStream from "./web/streams/writable_stream.ts";
|
import * as writableStream from "./web/streams/writable_stream.ts";
|
||||||
|
|
||||||
// These imports are not exposed and therefore are fine to just import the
|
// These imports are not exposed and therefore are fine to just import the
|
||||||
|
@ -234,12 +234,16 @@ export const windowOrWorkerGlobalScopeProperties = {
|
||||||
Headers: nonEnumerable(headers.HeadersImpl),
|
Headers: nonEnumerable(headers.HeadersImpl),
|
||||||
navigator: nonEnumerable(new navigator.NavigatorImpl()),
|
navigator: nonEnumerable(new navigator.NavigatorImpl()),
|
||||||
Navigator: nonEnumerable(navigator.NavigatorImpl),
|
Navigator: nonEnumerable(navigator.NavigatorImpl),
|
||||||
performance: writable(new performanceUtil.Performance()),
|
|
||||||
Permissions: nonEnumerable(permissions.PermissionsImpl),
|
Permissions: nonEnumerable(permissions.PermissionsImpl),
|
||||||
PermissionStatus: nonEnumerable(permissions.PermissionStatusImpl),
|
PermissionStatus: nonEnumerable(permissions.PermissionStatusImpl),
|
||||||
ReadableStream: nonEnumerable(readableStream.ReadableStreamImpl),
|
ReadableStream: nonEnumerable(readableStream.ReadableStreamImpl),
|
||||||
Request: nonEnumerable(request.Request),
|
Request: nonEnumerable(request.Request),
|
||||||
Response: nonEnumerable(fetchTypes.Response),
|
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),
|
TextDecoder: nonEnumerable(textEncoding.TextDecoder),
|
||||||
TextEncoder: nonEnumerable(textEncoding.TextEncoder),
|
TextEncoder: nonEnumerable(textEncoding.TextEncoder),
|
||||||
TransformStream: nonEnumerable(transformStream.TransformStreamImpl),
|
TransformStream: nonEnumerable(transformStream.TransformStreamImpl),
|
||||||
|
|
44
cli/js/lib.deno.ns.d.ts
vendored
44
cli/js/lib.deno.ns.d.ts
vendored
|
@ -3,6 +3,9 @@
|
||||||
/// <reference no-default-lib="true" />
|
/// <reference no-default-lib="true" />
|
||||||
/// <reference lib="esnext" />
|
/// <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 {
|
declare interface ImportMeta {
|
||||||
/** A string representation of the fully qualified module URL. */
|
/** A string representation of the fully qualified module URL. */
|
||||||
url: string;
|
url: string;
|
||||||
|
@ -19,6 +22,47 @@ declare interface ImportMeta {
|
||||||
main: boolean;
|
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 {
|
declare interface Permissions {
|
||||||
/** Resolves to the current status of a permission.
|
/** Resolves to the current status of a permission.
|
||||||
*
|
*
|
||||||
|
|
94
cli/js/lib.deno.shared_globals.d.ts
vendored
94
cli/js/lib.deno.shared_globals.d.ts
vendored
|
@ -1337,7 +1337,36 @@ declare class Worker extends EventTarget {
|
||||||
terminate(): void;
|
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.
|
/** Returns a current time from Deno's start in milliseconds.
|
||||||
*
|
*
|
||||||
* Use the permission flag `--allow-hrtime` return a precise value.
|
* Use the permission flag `--allow-hrtime` return a precise value.
|
||||||
|
@ -1347,7 +1376,68 @@ declare namespace performance {
|
||||||
* console.log(`${t} ms since start!`);
|
* 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 {
|
interface EventInit {
|
||||||
|
|
|
@ -1,10 +1,336 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
import { now as opNow } from "../ops/timers.ts";
|
import { now as opNow } from "../ops/timers.ts";
|
||||||
|
import { customInspect, inspect } from "./console.ts";
|
||||||
|
import { cloneValue, setFunctionName } from "./util.ts";
|
||||||
|
|
||||||
export class Performance {
|
let performanceEntries: PerformanceEntryList = [];
|
||||||
now(): number {
|
|
||||||
|
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();
|
const res = opNow();
|
||||||
return res.seconds * 1e3 + res.subsecNanos / 1e6;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
now(): number {
|
||||||
|
return now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setFunctionName(PerformanceEntryImpl, "PerformanceEntry");
|
||||||
|
setFunctionName(PerformanceMarkImpl, "PerformanceMark");
|
||||||
|
setFunctionName(PerformanceMeasureImpl, "PerformanceMeasure");
|
||||||
|
setFunctionName(PerformanceImpl, "Performance");
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { WritableStreamDefaultWriterImpl } from "./writable_stream_default_write
|
||||||
import { WritableStreamImpl } from "./writable_stream.ts";
|
import { WritableStreamImpl } from "./writable_stream.ts";
|
||||||
import { AbortSignalImpl } from "../abort_signal.ts";
|
import { AbortSignalImpl } from "../abort_signal.ts";
|
||||||
import { DOMExceptionImpl as DOMException } from "../dom_exception.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";
|
import { assert, AssertionError } from "../../util.ts";
|
||||||
|
|
||||||
export type AbortAlgorithm = (reason?: any) => PromiseLike<void>;
|
export type AbortAlgorithm = (reason?: any) => PromiseLike<void>;
|
||||||
|
@ -1320,12 +1320,6 @@ export function resetQueue<R>(container: Container<R>): void {
|
||||||
container[sym.queueTotalSize] = 0;
|
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
|
/** An internal function which mimics the behavior of setting the promise to
|
||||||
* handled in JavaScript. In this situation, an assertion failure, which
|
* handled in JavaScript. In this situation, an assertion failure, which
|
||||||
* shouldn't happen will get thrown, instead of swallowed. */
|
* shouldn't happen will get thrown, instead of swallowed. */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
import { setFunctionName } from "./internals.ts";
|
|
||||||
import { customInspect } from "../console.ts";
|
import { customInspect } from "../console.ts";
|
||||||
|
import { setFunctionName } from "../util.ts";
|
||||||
|
|
||||||
export class CountQueuingStrategyImpl implements CountQueuingStrategy {
|
export class CountQueuingStrategyImpl implements CountQueuingStrategy {
|
||||||
highWaterMark: number;
|
highWaterMark: number;
|
||||||
|
|
|
@ -18,12 +18,12 @@ import {
|
||||||
readableStreamHasDefaultReader,
|
readableStreamHasDefaultReader,
|
||||||
readableStreamGetNumReadRequests,
|
readableStreamGetNumReadRequests,
|
||||||
readableStreamCreateReadResult,
|
readableStreamCreateReadResult,
|
||||||
setFunctionName,
|
|
||||||
} from "./internals.ts";
|
} from "./internals.ts";
|
||||||
import type { ReadableStreamImpl } from "./readable_stream.ts";
|
import type { ReadableStreamImpl } from "./readable_stream.ts";
|
||||||
import * as sym from "./symbols.ts";
|
import * as sym from "./symbols.ts";
|
||||||
import { assert } from "../../util.ts";
|
import { assert } from "../../util.ts";
|
||||||
import { customInspect } from "../console.ts";
|
import { customInspect } from "../console.ts";
|
||||||
|
import { setFunctionName } from "../util.ts";
|
||||||
|
|
||||||
export class ReadableByteStreamControllerImpl
|
export class ReadableByteStreamControllerImpl
|
||||||
implements ReadableByteStreamController {
|
implements ReadableByteStreamController {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import {
|
||||||
isWritableStream,
|
isWritableStream,
|
||||||
isWritableStreamLocked,
|
isWritableStreamLocked,
|
||||||
makeSizeAlgorithmFromSizeFunction,
|
makeSizeAlgorithmFromSizeFunction,
|
||||||
setFunctionName,
|
|
||||||
setPromiseIsHandledToTrue,
|
setPromiseIsHandledToTrue,
|
||||||
readableStreamCancel,
|
readableStreamCancel,
|
||||||
ReadableStreamGenericReader,
|
ReadableStreamGenericReader,
|
||||||
|
@ -25,6 +24,7 @@ import type { ReadableStreamDefaultControllerImpl } from "./readable_stream_defa
|
||||||
import * as sym from "./symbols.ts";
|
import * as sym from "./symbols.ts";
|
||||||
import { customInspect } from "../console.ts";
|
import { customInspect } from "../console.ts";
|
||||||
import { AbortSignalImpl } from "../abort_signal.ts";
|
import { AbortSignalImpl } from "../abort_signal.ts";
|
||||||
|
import { setFunctionName } from "../util.ts";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export class ReadableStreamImpl<R = any> implements ReadableStream<R> {
|
export class ReadableStreamImpl<R = any> implements ReadableStream<R> {
|
||||||
|
|
|
@ -18,11 +18,11 @@ import {
|
||||||
readableStreamDefaultControllerGetDesiredSize,
|
readableStreamDefaultControllerGetDesiredSize,
|
||||||
resetQueue,
|
resetQueue,
|
||||||
SizeAlgorithm,
|
SizeAlgorithm,
|
||||||
setFunctionName,
|
|
||||||
} from "./internals.ts";
|
} from "./internals.ts";
|
||||||
import type { ReadableStreamImpl } from "./readable_stream.ts";
|
import type { ReadableStreamImpl } from "./readable_stream.ts";
|
||||||
import * as sym from "./symbols.ts";
|
import * as sym from "./symbols.ts";
|
||||||
import { customInspect } from "../console.ts";
|
import { customInspect } from "../console.ts";
|
||||||
|
import { setFunctionName } from "../util.ts";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export class ReadableStreamDefaultControllerImpl<R = any>
|
export class ReadableStreamDefaultControllerImpl<R = any>
|
||||||
|
|
|
@ -9,11 +9,11 @@ import {
|
||||||
readableStreamReaderGenericCancel,
|
readableStreamReaderGenericCancel,
|
||||||
readableStreamReaderGenericInitialize,
|
readableStreamReaderGenericInitialize,
|
||||||
readableStreamReaderGenericRelease,
|
readableStreamReaderGenericRelease,
|
||||||
setFunctionName,
|
|
||||||
} from "./internals.ts";
|
} from "./internals.ts";
|
||||||
import type { ReadableStreamImpl } from "./readable_stream.ts";
|
import type { ReadableStreamImpl } from "./readable_stream.ts";
|
||||||
import * as sym from "./symbols.ts";
|
import * as sym from "./symbols.ts";
|
||||||
import { customInspect } from "../console.ts";
|
import { customInspect } from "../console.ts";
|
||||||
|
import { setFunctionName } from "../util.ts";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export class ReadableStreamDefaultReaderImpl<R = any>
|
export class ReadableStreamDefaultReaderImpl<R = any>
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {
|
||||||
invokeOrNoop,
|
invokeOrNoop,
|
||||||
isTransformStream,
|
isTransformStream,
|
||||||
makeSizeAlgorithmFromSizeFunction,
|
makeSizeAlgorithmFromSizeFunction,
|
||||||
setFunctionName,
|
|
||||||
setUpTransformStreamDefaultControllerFromTransformer,
|
setUpTransformStreamDefaultControllerFromTransformer,
|
||||||
validateAndNormalizeHighWaterMark,
|
validateAndNormalizeHighWaterMark,
|
||||||
} from "./internals.ts";
|
} from "./internals.ts";
|
||||||
|
@ -16,6 +15,7 @@ import * as sym from "./symbols.ts";
|
||||||
import type { TransformStreamDefaultControllerImpl } from "./transform_stream_default_controller.ts";
|
import type { TransformStreamDefaultControllerImpl } from "./transform_stream_default_controller.ts";
|
||||||
import type { WritableStreamImpl } from "./writable_stream.ts";
|
import type { WritableStreamImpl } from "./writable_stream.ts";
|
||||||
import { customInspect, inspect } from "../console.ts";
|
import { customInspect, inspect } from "../console.ts";
|
||||||
|
import { setFunctionName } from "../util.ts";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export class TransformStreamImpl<I = any, O = any>
|
export class TransformStreamImpl<I = any, O = any>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import {
|
||||||
FlushAlgorithm,
|
FlushAlgorithm,
|
||||||
isTransformStreamDefaultController,
|
isTransformStreamDefaultController,
|
||||||
readableStreamDefaultControllerGetDesiredSize,
|
readableStreamDefaultControllerGetDesiredSize,
|
||||||
setFunctionName,
|
|
||||||
TransformAlgorithm,
|
TransformAlgorithm,
|
||||||
transformStreamDefaultControllerEnqueue,
|
transformStreamDefaultControllerEnqueue,
|
||||||
transformStreamDefaultControllerError,
|
transformStreamDefaultControllerError,
|
||||||
|
@ -14,6 +13,7 @@ import type { ReadableStreamDefaultControllerImpl } from "./readable_stream_defa
|
||||||
import * as sym from "./symbols.ts";
|
import * as sym from "./symbols.ts";
|
||||||
import type { TransformStreamImpl } from "./transform_stream.ts";
|
import type { TransformStreamImpl } from "./transform_stream.ts";
|
||||||
import { customInspect } from "../console.ts";
|
import { customInspect } from "../console.ts";
|
||||||
|
import { setFunctionName } from "../util.ts";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export class TransformStreamDefaultControllerImpl<I = any, O = any>
|
export class TransformStreamDefaultControllerImpl<I = any, O = any>
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {
|
||||||
isWritableStream,
|
isWritableStream,
|
||||||
isWritableStreamLocked,
|
isWritableStreamLocked,
|
||||||
makeSizeAlgorithmFromSizeFunction,
|
makeSizeAlgorithmFromSizeFunction,
|
||||||
setFunctionName,
|
|
||||||
setUpWritableStreamDefaultControllerFromUnderlyingSink,
|
setUpWritableStreamDefaultControllerFromUnderlyingSink,
|
||||||
writableStreamAbort,
|
writableStreamAbort,
|
||||||
writableStreamClose,
|
writableStreamClose,
|
||||||
|
@ -19,6 +18,7 @@ import * as sym from "./symbols.ts";
|
||||||
import type { WritableStreamDefaultControllerImpl } from "./writable_stream_default_controller.ts";
|
import type { WritableStreamDefaultControllerImpl } from "./writable_stream_default_controller.ts";
|
||||||
import type { WritableStreamDefaultWriterImpl } from "./writable_stream_default_writer.ts";
|
import type { WritableStreamDefaultWriterImpl } from "./writable_stream_default_writer.ts";
|
||||||
import { customInspect } from "../console.ts";
|
import { customInspect } from "../console.ts";
|
||||||
|
import { setFunctionName } from "../util.ts";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export class WritableStreamImpl<W = any> implements WritableStream<W> {
|
export class WritableStreamImpl<W = any> implements WritableStream<W> {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import {
|
||||||
isWritableStreamDefaultController,
|
isWritableStreamDefaultController,
|
||||||
Pair,
|
Pair,
|
||||||
resetQueue,
|
resetQueue,
|
||||||
setFunctionName,
|
|
||||||
SizeAlgorithm,
|
SizeAlgorithm,
|
||||||
WriteAlgorithm,
|
WriteAlgorithm,
|
||||||
writableStreamDefaultControllerClearAlgorithms,
|
writableStreamDefaultControllerClearAlgorithms,
|
||||||
|
@ -15,6 +14,7 @@ import {
|
||||||
import * as sym from "./symbols.ts";
|
import * as sym from "./symbols.ts";
|
||||||
import type { WritableStreamImpl } from "./writable_stream.ts";
|
import type { WritableStreamImpl } from "./writable_stream.ts";
|
||||||
import { customInspect } from "../console.ts";
|
import { customInspect } from "../console.ts";
|
||||||
|
import { setFunctionName } from "../util.ts";
|
||||||
|
|
||||||
export class WritableStreamDefaultControllerImpl<W>
|
export class WritableStreamDefaultControllerImpl<W>
|
||||||
implements WritableStreamDefaultController {
|
implements WritableStreamDefaultController {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import {
|
||||||
isWritableStream,
|
isWritableStream,
|
||||||
isWritableStreamDefaultWriter,
|
isWritableStreamDefaultWriter,
|
||||||
isWritableStreamLocked,
|
isWritableStreamLocked,
|
||||||
setFunctionName,
|
|
||||||
setPromiseIsHandledToTrue,
|
setPromiseIsHandledToTrue,
|
||||||
writableStreamCloseQueuedOrInFlight,
|
writableStreamCloseQueuedOrInFlight,
|
||||||
writableStreamDefaultWriterAbort,
|
writableStreamDefaultWriterAbort,
|
||||||
|
@ -19,6 +18,7 @@ import * as sym from "./symbols.ts";
|
||||||
import type { WritableStreamImpl } from "./writable_stream.ts";
|
import type { WritableStreamImpl } from "./writable_stream.ts";
|
||||||
import { customInspect } from "../console.ts";
|
import { customInspect } from "../console.ts";
|
||||||
import { assert } from "../../util.ts";
|
import { assert } from "../../util.ts";
|
||||||
|
import { setFunctionName } from "../util.ts";
|
||||||
|
|
||||||
export class WritableStreamDefaultWriterImpl<W>
|
export class WritableStreamDefaultWriterImpl<W>
|
||||||
implements WritableStreamDefaultWriter<W> {
|
implements WritableStreamDefaultWriter<W> {
|
||||||
|
|
|
@ -208,3 +208,11 @@ export function getHeaderValueParams(value: string): Map<string, string> {
|
||||||
export function hasHeaderValueOf(s: string, value: string): boolean {
|
export function hasHeaderValueOf(s: string, value: string): boolean {
|
||||||
return new RegExp(`^${value}[\t\s]*;?`).test(s);
|
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 });
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
import { unitTest, assert, createResolvable } from "./test_util.ts";
|
import {
|
||||||
|
unitTest,
|
||||||
|
assert,
|
||||||
|
assertEquals,
|
||||||
|
createResolvable,
|
||||||
|
} from "./test_util.ts";
|
||||||
|
|
||||||
unitTest({ perms: { hrtime: false } }, async function performanceNow(): Promise<
|
unitTest({ perms: { hrtime: false } }, async function performanceNow(): Promise<
|
||||||
void
|
void
|
||||||
|
@ -13,3 +18,42 @@ unitTest({ perms: { hrtime: false } }, async function performanceNow(): Promise<
|
||||||
}, 10);
|
}, 10);
|
||||||
await resolvable;
|
await resolvable;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
unitTest(function performanceMark() {
|
||||||
|
const mark = performance.mark("test");
|
||||||
|
assert(mark instanceof PerformanceMark);
|
||||||
|
assertEquals(mark.detail, null);
|
||||||
|
assertEquals(mark.name, "test");
|
||||||
|
assertEquals(mark.entryType, "mark");
|
||||||
|
assert(mark.startTime > 0);
|
||||||
|
assertEquals(mark.duration, 0);
|
||||||
|
const entries = performance.getEntries();
|
||||||
|
assert(entries[entries.length - 1] === mark);
|
||||||
|
const markEntries = performance.getEntriesByName("test", "mark");
|
||||||
|
assert(markEntries[markEntries.length - 1] === mark);
|
||||||
|
});
|
||||||
|
|
||||||
|
unitTest(function performanceMeasure() {
|
||||||
|
const mark = performance.mark("test");
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
try {
|
||||||
|
const measure = performance.measure("test", "test");
|
||||||
|
assert(measure instanceof PerformanceMeasure);
|
||||||
|
assertEquals(measure.detail, null);
|
||||||
|
assertEquals(measure.name, "test");
|
||||||
|
assertEquals(measure.entryType, "measure");
|
||||||
|
assert(measure.startTime > 0);
|
||||||
|
assertEquals(mark.startTime, measure.startTime);
|
||||||
|
assert(measure.duration >= 100 && measure.duration < 200);
|
||||||
|
const entries = performance.getEntries();
|
||||||
|
assert(entries[entries.length - 1] === measure);
|
||||||
|
const measureEntries = performance.getEntriesByName("test", "measure");
|
||||||
|
assert(measureEntries[measureEntries.length - 1] === measure);
|
||||||
|
} catch (e) {
|
||||||
|
return reject(e);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue