mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-07-02 06:35:09 -05:00
Remove shims, workaround for bug in peformance.measure
This commit is contained in:
@@ -49,9 +49,7 @@ namespace ts.performance {
|
||||
* @param markName The name of the mark.
|
||||
*/
|
||||
export function mark(markName: string) {
|
||||
if (performanceImpl) {
|
||||
performanceImpl.mark(markName);
|
||||
}
|
||||
performanceImpl?.mark(markName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,19 +62,7 @@ namespace ts.performance {
|
||||
* used.
|
||||
*/
|
||||
export function measure(measureName: string, startMarkName?: string, endMarkName?: string) {
|
||||
if (performanceImpl) {
|
||||
// NodeJS perf_hooks depends on call arity, not 'undefined' checks, so we
|
||||
// need to be sure we call 'measure' with the correct number of arguments.
|
||||
if (startMarkName === undefined) {
|
||||
performanceImpl.measure(measureName);
|
||||
}
|
||||
else if (endMarkName === undefined) {
|
||||
performanceImpl.measure(measureName, startMarkName);
|
||||
}
|
||||
else {
|
||||
performanceImpl.measure(measureName, startMarkName, endMarkName);
|
||||
}
|
||||
}
|
||||
performanceImpl?.measure(measureName, startMarkName, endMarkName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,9 +89,7 @@ namespace ts.performance {
|
||||
* @param cb The action to perform for each measure
|
||||
*/
|
||||
export function forEachMeasure(cb: (measureName: string, duration: number) => void) {
|
||||
perfEntryList?.getEntriesByType("measure").forEach(entry => {
|
||||
cb(entry.name, entry.duration);
|
||||
});
|
||||
perfEntryList?.getEntriesByType("measure").forEach(({ name, duration }) => { cb(name, duration); });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +102,7 @@ namespace ts.performance {
|
||||
/** Enables (and resets) performance measurements for the compiler. */
|
||||
export function enable() {
|
||||
if (!performanceImpl) {
|
||||
perfHooks ||= tryGetNativePerformanceHooks() || ShimPerformance?.createPerformanceHooksShim(timestamp);
|
||||
perfHooks ||= tryGetNativePerformanceHooks();
|
||||
if (!perfHooks) return false;
|
||||
perfObserver ||= new perfHooks.PerformanceObserver(list => perfEntryList = list);
|
||||
perfObserver.observe({ entryTypes: ["mark", "measure"] });
|
||||
|
||||
@@ -9,7 +9,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
export interface Performance {
|
||||
clearMarks(name?: string): void;
|
||||
mark(name: string): void;
|
||||
measure(name: string, startMark?: string, endMark?: string): void;
|
||||
now(): number;
|
||||
@@ -41,14 +40,20 @@ namespace ts {
|
||||
declare const performance: Performance | undefined;
|
||||
declare const PerformanceObserver: PerformanceObserverConstructor | undefined;
|
||||
|
||||
function tryGetWebPerformanceHooks(): PerformanceHooks | undefined {
|
||||
if (typeof performance === "object" &&
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
function hasRequiredAPI(performance: Performance | undefined, PerformanceObserver: PerformanceObserverConstructor | undefined) {
|
||||
return typeof performance === "object" &&
|
||||
typeof performance.timeOrigin === "number" &&
|
||||
typeof performance.clearMarks === "function" &&
|
||||
typeof performance.mark === "function" &&
|
||||
typeof performance.measure === "function" &&
|
||||
typeof performance.now === "function" &&
|
||||
typeof PerformanceObserver === "function") {
|
||||
typeof PerformanceObserver === "function";
|
||||
}
|
||||
|
||||
function tryGetWebPerformanceHooks(): PerformanceHooks | undefined {
|
||||
if (typeof performance === "object" &&
|
||||
typeof PerformanceObserver === "function" &&
|
||||
hasRequiredAPI(performance, PerformanceObserver)) {
|
||||
return {
|
||||
performance,
|
||||
PerformanceObserver
|
||||
@@ -59,16 +64,38 @@ namespace ts {
|
||||
function tryGetNodePerformanceHooks(): PerformanceHooks | undefined {
|
||||
if (typeof module === "object" && typeof require === "function") {
|
||||
try {
|
||||
const perfHooks = require("perf_hooks") as typeof import("perf_hooks");
|
||||
const { performance, PerformanceObserver } = perfHooks;
|
||||
if (typeof performance === "object" &&
|
||||
typeof performance.timeOrigin === "number" &&
|
||||
typeof performance.clearMarks === "function" &&
|
||||
typeof performance.mark === "function" &&
|
||||
typeof performance.measure === "function" &&
|
||||
typeof performance.now === "function" &&
|
||||
typeof PerformanceObserver === "function") {
|
||||
return perfHooks;
|
||||
const { performance, PerformanceObserver } = require("perf_hooks") as typeof import("perf_hooks");
|
||||
if (hasRequiredAPI(performance, PerformanceObserver)) {
|
||||
// There is a bug in Node's performance.measure prior to 12.16.3/13.13.0 that does not
|
||||
// match the Web Performance API specification. Node's implementation did not allow
|
||||
// optional `start` and `end` arguments for `performance.measure`.
|
||||
// See https://github.com/nodejs/node/pull/32651 for more information.
|
||||
const version = new Version(process.versions.node);
|
||||
const range = new VersionRange("<12 || 13 <13.13");
|
||||
if (range.test(version)) {
|
||||
return {
|
||||
performance: {
|
||||
get timeOrigin() { return performance.timeOrigin; },
|
||||
now() { return performance.now(); },
|
||||
mark(name) { return performance.mark(name); },
|
||||
measure(name, start = "nodeStart", end?) {
|
||||
if (end === undefined) {
|
||||
end = "__performance.measure-fix__";
|
||||
performance.mark(end);
|
||||
}
|
||||
performance.measure(name, start, end);
|
||||
if (end = "__performance.measure-fix__") {
|
||||
performance.clearMarks("__performance.measure-fix__");
|
||||
}
|
||||
}
|
||||
},
|
||||
PerformanceObserver
|
||||
};
|
||||
}
|
||||
return {
|
||||
performance,
|
||||
PerformanceObserver
|
||||
};
|
||||
}
|
||||
}
|
||||
catch {
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
interface PerformanceHooksShim {
|
||||
performance: PerformanceShim;
|
||||
PerformanceObserver: PerformanceObserverShimConstructor;
|
||||
}
|
||||
|
||||
interface PerformanceShim {
|
||||
clearMarks(name?: string): void;
|
||||
mark(name: string): void;
|
||||
measure(name: string, startMark?: string, endMark?: string): void;
|
||||
now(): number;
|
||||
timeOrigin: number;
|
||||
}
|
||||
|
||||
interface PerformanceEntryShim {
|
||||
name: string;
|
||||
entryType: string;
|
||||
startTime: number;
|
||||
duration: number;
|
||||
}
|
||||
|
||||
interface PerformanceObserverEntryListShim {
|
||||
getEntries(): PerformanceEntryListShim;
|
||||
getEntriesByName(name: string, type?: string): PerformanceEntryListShim;
|
||||
getEntriesByType(type: string): PerformanceEntryListShim;
|
||||
}
|
||||
|
||||
interface PerformanceObserverShim {
|
||||
disconnect(): void;
|
||||
observe(options: { entryTypes: readonly string[] }): void;
|
||||
}
|
||||
|
||||
type PerformanceObserverShimConstructor = new (callback: (list: PerformanceObserverEntryListShim, observer: PerformanceObserverShim) => void) => PerformanceObserverShim;
|
||||
|
||||
type PerformanceEntryListShim = PerformanceEntryShim[];
|
||||
|
||||
interface PerformanceObserverList {
|
||||
readonly head: PerformanceObserverNode;
|
||||
tail: PerformanceObserverNode;
|
||||
}
|
||||
|
||||
interface PerformanceObserverNode {
|
||||
observer: PerformanceObserverData;
|
||||
entryTypes: readonly string[];
|
||||
prev: PerformanceObserverNode | undefined;
|
||||
next: PerformanceObserverNode | undefined;
|
||||
}
|
||||
|
||||
interface PerformanceObserverData {
|
||||
buffer: PerformanceEntryShim[];
|
||||
node: PerformanceObserverNode | undefined;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export namespace ShimPerformance {
|
||||
export function createPerformanceHooksShim(now: () => number): PerformanceHooksShim {
|
||||
const timeOrigin = now();
|
||||
const observerList = createObserverList();
|
||||
let marks = createDictionary<number>();
|
||||
|
||||
function clearMarks(name?: string) {
|
||||
if (name !== undefined) {
|
||||
delete marks[name];
|
||||
}
|
||||
else {
|
||||
marks = createDictionary();
|
||||
}
|
||||
}
|
||||
|
||||
function mark(markName: string) {
|
||||
const timestamp = now();
|
||||
marks[markName] = timestamp;
|
||||
if (observerList.head) {
|
||||
emit(createPerformanceEntry(markName, "mark", timestamp, 0));
|
||||
}
|
||||
}
|
||||
|
||||
function measure(measureName: string, startMark?: string, endMark?: string) {
|
||||
if (observerList.head) {
|
||||
const end = (endMark !== undefined ? marks[endMark] : undefined) ?? now();
|
||||
const start = (startMark !== undefined ? marks[startMark] : undefined) ?? timeOrigin;
|
||||
emit(createPerformanceEntry(measureName, "measure", start, end - start));
|
||||
}
|
||||
}
|
||||
|
||||
function emit(entry: PerformanceEntryShim) {
|
||||
let node: PerformanceObserverNode | undefined = observerList.head;
|
||||
while (node) {
|
||||
node = node.next;
|
||||
if (node) {
|
||||
if (node.entryTypes.indexOf(entry.entryType) !== -1) {
|
||||
node.observer.buffer.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createDictionary<T>(): Record<string, T | undefined> {
|
||||
// eslint-disable-next-line boolean-trivia, no-null/no-null
|
||||
const obj = Object.create(null);
|
||||
obj.__ = undefined;
|
||||
delete obj.__;
|
||||
return obj;
|
||||
}
|
||||
|
||||
function createObserverList(): PerformanceObserverList {
|
||||
const sentinel = {} as PerformanceObserverNode;
|
||||
sentinel.prev = sentinel;
|
||||
return { head: sentinel, tail: sentinel };
|
||||
}
|
||||
|
||||
function createObserverNode(observer: PerformanceObserverData, entryTypes: readonly string[]): PerformanceObserverNode {
|
||||
return { observer, entryTypes, prev: undefined, next: undefined };
|
||||
}
|
||||
|
||||
function createObserverData(): PerformanceObserverData {
|
||||
return { node: undefined, buffer: [] };
|
||||
}
|
||||
|
||||
function createPerformanceEntry(name: string, entryType: string, startTime: number, duration: number): PerformanceEntryShim {
|
||||
return { name, entryType, startTime, duration };
|
||||
}
|
||||
|
||||
class PerformanceObserverEntryList implements PerformanceObserverEntryListShim {
|
||||
private _data: PerformanceObserverData;
|
||||
|
||||
constructor(ref: PerformanceObserverData) {
|
||||
this._data = ref;
|
||||
}
|
||||
|
||||
getEntries(): PerformanceEntryShim[] {
|
||||
return this._data.buffer.slice();
|
||||
}
|
||||
|
||||
getEntriesByName(name: string, type?: string): PerformanceEntryShim[] {
|
||||
return this._data.buffer.filter(event => event.name === name && (type === undefined || event.entryType === type));
|
||||
}
|
||||
|
||||
getEntriesByType(type: string): PerformanceEntryShim[] {
|
||||
return this._data.buffer.filter(event => event.entryType === type);
|
||||
}
|
||||
}
|
||||
|
||||
class PerformanceObserver implements PerformanceObserverShim {
|
||||
private _data = createObserverData();
|
||||
|
||||
constructor(callback: (list: PerformanceObserverEntryListShim, observer: PerformanceObserver) => void) {
|
||||
const list = new PerformanceObserverEntryList(this._data);
|
||||
callback(list, this);
|
||||
}
|
||||
|
||||
observe(options: { entryTypes: readonly string[] }) {
|
||||
let entryTypes = options.entryTypes;
|
||||
entryTypes = entryTypes.filter(entryType => entryType === "mark" || entryType === "measure");
|
||||
if (entryTypes.length === 0) return;
|
||||
if (this._data.node) {
|
||||
this._data.node.entryTypes = entryTypes;
|
||||
}
|
||||
else {
|
||||
const node = createObserverNode(this._data, entryTypes);
|
||||
node.prev = observerList.tail;
|
||||
observerList.tail.next = node;
|
||||
observerList.tail = node;
|
||||
this._data.node = node;
|
||||
}
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
const node = this._data.node;
|
||||
if (node) {
|
||||
// all nodes in have a 'prev' pointer.
|
||||
if (node.prev === undefined) throw new Error("Illegal state");
|
||||
if (node.next) {
|
||||
node.next.prev = node.prev;
|
||||
}
|
||||
else {
|
||||
// a node in the list without a 'next' pointer must be the tail
|
||||
if (observerList.tail !== node) throw new Error("Illegal state");
|
||||
observerList.tail = node.prev;
|
||||
}
|
||||
node.prev.next = node.next;
|
||||
node.next = node.prev;
|
||||
node.prev = undefined;
|
||||
this._data.node = undefined;
|
||||
this._data.buffer.length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
performance: {
|
||||
clearMarks,
|
||||
mark,
|
||||
measure,
|
||||
now,
|
||||
timeOrigin
|
||||
},
|
||||
PerformanceObserver
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,5 @@
|
||||
},
|
||||
"files": [
|
||||
"collectionShims.ts",
|
||||
"performanceShims.ts",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -75,7 +75,6 @@
|
||||
"unittests/semver.ts",
|
||||
"unittests/createMapShim.ts",
|
||||
"unittests/createSetShim.ts",
|
||||
"unittests/createPerformanceHooksShim.ts",
|
||||
"unittests/transform.ts",
|
||||
"unittests/config/commandLineParsing.ts",
|
||||
"unittests/config/configurationExtension.ts",
|
||||
|
||||
@@ -1,251 +0,0 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-expressions */ // chai's expect allows you to use dot-property assertions like `.is.empty`
|
||||
namespace ts {
|
||||
describe("unittests:: createPerformanceHooksShim", () => {
|
||||
it("has expected API", () => {
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(Date.now);
|
||||
expect(performance).to.be.an("object");
|
||||
expect(performance.timeOrigin).to.be.a("number");
|
||||
expect(performance.clearMarks).to.be.a("function");
|
||||
expect(performance.mark).to.be.a("function");
|
||||
expect(performance.measure).to.be.a("function");
|
||||
expect(performance.now).to.be.a("function");
|
||||
expect(PerformanceObserver).to.be.a("function");
|
||||
let list!: PerformanceObserverEntryList;
|
||||
let observer2!: PerformanceObserver;
|
||||
const observer = new PerformanceObserver((_list, observer) => { list = _list; observer2 = observer; });
|
||||
expect(list).to.be.an("object");
|
||||
expect(observer2).to.be.an("object");
|
||||
expect(observer2).to.equal(observer);
|
||||
expect(observer2.disconnect).to.be.a("function");
|
||||
expect(observer2.observe).to.be.a("function");
|
||||
expect(list.getEntries).to.be.a("function");
|
||||
expect(list.getEntriesByName).to.be.a("function");
|
||||
expect(list.getEntriesByType).to.be.a("function");
|
||||
});
|
||||
it("only listens for events while connected", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp++;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
|
||||
performance.mark("a");
|
||||
const entries1 = list.getEntries();
|
||||
observer.observe({ entryTypes: ["mark"] });
|
||||
performance.mark("b");
|
||||
const entries2 = list.getEntries();
|
||||
observer.disconnect();
|
||||
performance.mark("c");
|
||||
const entries3 = list.getEntries();
|
||||
|
||||
expect(entries1).to.be.empty;
|
||||
expect(entries2).to.not.be.empty;
|
||||
expect(entries3).to.be.empty;
|
||||
});
|
||||
it("Can get entries by name and type (mark)", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp++;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["mark", "measure"] });
|
||||
performance.mark("a");
|
||||
performance.measure("b", "a");
|
||||
const entries = list.getEntriesByName("a", "mark");
|
||||
const entries2 = list.getEntriesByName("b", "mark");
|
||||
observer.disconnect();
|
||||
expect(entries).to.have.lengthOf(1);
|
||||
expect(entries[0]).to.be.an("object");
|
||||
expect(entries[0].name).to.equal("a");
|
||||
expect(entries[0].entryType).to.equal("mark");
|
||||
expect(entries2).to.be.empty;
|
||||
});
|
||||
it("Can get entries by name and type (measure)", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp++;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["mark", "measure"] });
|
||||
performance.mark("a");
|
||||
performance.measure("b", "a");
|
||||
const entries = list.getEntriesByName("b", "measure");
|
||||
const entries2 = list.getEntriesByName("a", "measure");
|
||||
observer.disconnect();
|
||||
expect(entries).to.have.lengthOf(1);
|
||||
expect(entries[0]).to.be.an("object");
|
||||
expect(entries[0].name).to.equal("b");
|
||||
expect(entries[0].entryType).to.equal("measure");
|
||||
expect(entries2).to.be.empty;
|
||||
});
|
||||
it("Can get entries by name", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp++;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["mark", "measure"] });
|
||||
performance.mark("a");
|
||||
performance.measure("b", "a");
|
||||
const entries = list.getEntriesByName("a");
|
||||
const entries2 = list.getEntriesByName("b");
|
||||
observer.disconnect();
|
||||
expect(entries).to.not.be.empty;
|
||||
expect(entries).to.have.lengthOf(1);
|
||||
expect(entries[0]).to.be.an("object");
|
||||
expect(entries[0].name).to.equal("a");
|
||||
expect(entries[0].entryType).to.equal("mark");
|
||||
expect(entries2).to.have.lengthOf(1);
|
||||
expect(entries2[0]).to.be.an("object");
|
||||
expect(entries2[0].name).to.equal("b");
|
||||
expect(entries2[0].entryType).to.equal("measure");
|
||||
});
|
||||
it("Can get entries by type", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp++;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["mark", "measure"] });
|
||||
performance.mark("a");
|
||||
performance.measure("b", "a");
|
||||
const entries = list.getEntriesByType("mark");
|
||||
const entries2 = list.getEntriesByType("measure");
|
||||
observer.disconnect();
|
||||
expect(entries).to.have.lengthOf(1);
|
||||
expect(entries[0]).to.be.an("object");
|
||||
expect(entries[0].name).to.equal("a");
|
||||
expect(entries[0].entryType).to.equal("mark");
|
||||
expect(entries2).to.have.lengthOf(1);
|
||||
expect(entries2[0]).to.be.an("object");
|
||||
expect(entries2[0].name).to.equal("b");
|
||||
expect(entries2[0].entryType).to.equal("measure");
|
||||
});
|
||||
it("Can get entries", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp++;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["mark", "measure"] });
|
||||
performance.mark("a");
|
||||
performance.measure("b", "a");
|
||||
const entries = list.getEntries();
|
||||
observer.disconnect();
|
||||
expect(entries).to.have.lengthOf(2);
|
||||
expect(entries[0]).to.be.an("object");
|
||||
expect(entries[0].name).to.equal("a");
|
||||
expect(entries[0].entryType).to.equal("mark");
|
||||
expect(entries[1]).to.be.an("object");
|
||||
expect(entries[1].name).to.equal("b");
|
||||
expect(entries[1].entryType).to.equal("measure");
|
||||
});
|
||||
it("Unobserved entries are ignored", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp++;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["mark"] });
|
||||
performance.mark("a");
|
||||
performance.measure("b", "a");
|
||||
const entries = list.getEntries();
|
||||
observer.disconnect();
|
||||
expect(entries).to.have.lengthOf(1);
|
||||
expect(entries[0]).to.be.an("object");
|
||||
expect(entries[0].name).to.equal("a");
|
||||
expect(entries[0].entryType).to.equal("mark");
|
||||
});
|
||||
it("Changing what's observed only affects new entries", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp++;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["mark"] });
|
||||
performance.mark("a");
|
||||
performance.measure("b", "a");
|
||||
observer.observe({ entryTypes: ["measure"] });
|
||||
performance.mark("c");
|
||||
performance.measure("d", "c");
|
||||
const entries = list.getEntries();
|
||||
observer.disconnect();
|
||||
expect(entries).to.have.lengthOf(2);
|
||||
expect(entries[0]).to.be.an("object");
|
||||
expect(entries[0].name).to.equal("a");
|
||||
expect(entries[0].entryType).to.equal("mark");
|
||||
expect(entries[1]).to.be.an("object");
|
||||
expect(entries[1].name).to.equal("d");
|
||||
expect(entries[1].entryType).to.equal("measure");
|
||||
});
|
||||
it("mark tracks current time", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["mark"] });
|
||||
const ts1 = timestamp;
|
||||
performance.mark("a");
|
||||
timestamp++;
|
||||
const ts2 = timestamp;
|
||||
performance.mark("b");
|
||||
const entries = list.getEntries();
|
||||
observer.disconnect();
|
||||
expect(entries[0].startTime).to.equal(ts1);
|
||||
expect(entries[0].duration).to.equal(0);
|
||||
expect(entries[1].startTime).to.equal(ts2);
|
||||
expect(entries[1].duration).to.equal(0);
|
||||
});
|
||||
it("measure tracks time between marks", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["mark", "measure"] });
|
||||
const ts1 = timestamp;
|
||||
performance.mark("a");
|
||||
timestamp++;
|
||||
const ts2 = timestamp;
|
||||
performance.mark("b");
|
||||
performance.measure("c", "a", "b");
|
||||
const entries = list.getEntriesByType("measure");
|
||||
observer.disconnect();
|
||||
expect(entries[0].startTime).to.equal(ts1);
|
||||
expect(entries[0].duration).to.equal(ts2 - ts1);
|
||||
});
|
||||
it("measure tracks time between unobserved marks", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["measure"] });
|
||||
const ts1 = timestamp;
|
||||
performance.mark("a");
|
||||
timestamp++;
|
||||
const ts2 = timestamp;
|
||||
performance.mark("b");
|
||||
performance.measure("c", "a", "b");
|
||||
const entries = list.getEntries();
|
||||
observer.disconnect();
|
||||
expect(entries[0].startTime).to.equal(ts1);
|
||||
expect(entries[0].duration).to.equal(ts2 - ts1);
|
||||
});
|
||||
it("marks can be counted", () => {
|
||||
let timestamp = 0;
|
||||
const now = () => timestamp++;
|
||||
const { performance, PerformanceObserver } = ShimPerformance.createPerformanceHooksShim(now);
|
||||
let list!: PerformanceObserverEntryList;
|
||||
const observer = new PerformanceObserver(_list => list = _list);
|
||||
observer.observe({ entryTypes: ["mark"] });
|
||||
performance.mark("a");
|
||||
performance.mark("a");
|
||||
performance.mark("a");
|
||||
const entries = list.getEntries();
|
||||
observer.disconnect();
|
||||
expect(entries).to.have.lengthOf(3);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -43,7 +43,7 @@ namespace ts.tscWatch {
|
||||
return createWatchProgram(compilerHost);
|
||||
}
|
||||
|
||||
const elapsedRegex = /^Elapsed:: [0-9]+(?:\.\d+)?ms/;
|
||||
const elapsedRegex = /^Elapsed:: \d+(?:\.\d+)?ms/;
|
||||
const buildVerboseLogRegEx = /^.+ \- /;
|
||||
export enum HostOutputKind {
|
||||
Log,
|
||||
|
||||
Reference in New Issue
Block a user