Write message instead of crashing when native perf API not found.
This commit is contained in:
parent
a197beef6d
commit
dfa55add5a
|
@ -4719,6 +4719,10 @@
|
|||
"code": 6385,
|
||||
"reportsDeprecated": true
|
||||
},
|
||||
"Performance timings for '--diagnostics' or '--extendedDiagnostics' are not available in this session. A native implementation of the Web Performance API could not be found.": {
|
||||
"category": "Message",
|
||||
"code": 6386
|
||||
},
|
||||
|
||||
"The expected type comes from property '{0}' which is declared here on type '{1}'": {
|
||||
"category": "Message",
|
||||
|
|
|
@ -67,7 +67,17 @@ namespace ts.performance {
|
|||
*/
|
||||
export function measure(measureName: string, startMarkName?: string, endMarkName?: string) {
|
||||
if (perfHooks && enabled) {
|
||||
perfHooks.performance.measure(measureName, startMarkName, endMarkName);
|
||||
// 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) {
|
||||
perfHooks.performance.measure(measureName);
|
||||
}
|
||||
else if (endMarkName === undefined) {
|
||||
perfHooks.performance.measure(measureName, startMarkName);
|
||||
}
|
||||
else {
|
||||
perfHooks.performance.measure(measureName, startMarkName, endMarkName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,15 +110,23 @@ namespace ts.performance {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the performance API is enabled.
|
||||
*/
|
||||
export function isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/** Enables (and resets) performance measurements for the compiler. */
|
||||
export function enable() {
|
||||
if (!enabled) {
|
||||
perfHooks ||= tryGetNativePerformanceHooks() || ShimPerformance?.createPerformanceHooksShim(timestamp);
|
||||
if (!perfHooks) throw new Error("TypeScript requires an environment that provides a compatible native Web Performance API implementation.");
|
||||
if (!perfHooks) return false;
|
||||
perfObserver ||= new perfHooks.PerformanceObserver(list => perfEntryList = list);
|
||||
perfObserver.observe({ entryTypes: ["mark", "measure"] });
|
||||
enabled = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Disables performance measurements for the compiler. */
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
/*@internal*/
|
||||
namespace ts {
|
||||
// The following definitions provide the minimum compatible support for the Web Performance User Timings API
|
||||
// between browsers and NodeJS:
|
||||
|
||||
export interface PerformanceHooks {
|
||||
performance: Performance;
|
||||
PerformanceObserver: PerformanceObserverConstructor;
|
||||
|
@ -34,6 +37,7 @@ namespace ts {
|
|||
export type PerformanceObserverConstructor = new (callback: (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void) => PerformanceObserver;
|
||||
export type PerformanceEntryList = PerformanceEntry[];
|
||||
|
||||
// Browser globals for the Web Performance User Timings API
|
||||
declare const performance: Performance | undefined;
|
||||
declare const PerformanceObserver: PerformanceObserverConstructor | undefined;
|
||||
|
||||
|
@ -55,7 +59,17 @@ namespace ts {
|
|||
function tryGetNodePerformanceHooks(): PerformanceHooks | undefined {
|
||||
if (typeof module === "object" && typeof require === "function") {
|
||||
try {
|
||||
return require("perf_hooks") as typeof import("perf_hooks");
|
||||
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;
|
||||
}
|
||||
}
|
||||
catch {
|
||||
// ignore errors
|
||||
|
@ -63,18 +77,18 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
// Unlike with the native Map/Set 'tryGet' functions in corePublic.ts, we eagerly evaluate these
|
||||
// since we will need them for `timestamp`, below.
|
||||
const nativePerformanceHooks = tryGetWebPerformanceHooks() || tryGetNodePerformanceHooks();
|
||||
const nativePerformance = nativePerformanceHooks?.performance;
|
||||
|
||||
export function tryGetNativePerformanceHooks() {
|
||||
return nativePerformanceHooks;
|
||||
}
|
||||
|
||||
/** Gets a timestamp with (at least) ms resolution */
|
||||
export const timestamp = (() => {
|
||||
if (nativePerformanceHooks) {
|
||||
const performance = nativePerformanceHooks.performance;
|
||||
return () => performance.now();
|
||||
}
|
||||
return Date.now ? Date.now : () => +(new Date());
|
||||
})();
|
||||
export const timestamp =
|
||||
nativePerformance ? () => nativePerformance.now() :
|
||||
Date.now ? Date.now :
|
||||
() => +(new Date());
|
||||
}
|
|
@ -648,19 +648,21 @@ namespace ts {
|
|||
reportStatisticalValue("Memory used", Math.round(memoryUsed / 1000) + "K");
|
||||
}
|
||||
|
||||
const programTime = performance.getDuration("Program");
|
||||
const bindTime = performance.getDuration("Bind");
|
||||
const checkTime = performance.getDuration("Check");
|
||||
const emitTime = performance.getDuration("Emit");
|
||||
const programTime = performance.isEnabled() ? performance.getDuration("Program") : 0;
|
||||
const bindTime = performance.isEnabled() ? performance.getDuration("Bind") : 0;
|
||||
const checkTime = performance.isEnabled() ? performance.getDuration("Check") : 0;
|
||||
const emitTime = performance.isEnabled() ? performance.getDuration("Emit") : 0;
|
||||
if (compilerOptions.extendedDiagnostics) {
|
||||
const caches = program.getRelationCacheSizes();
|
||||
reportCountStatistic("Assignability cache size", caches.assignable);
|
||||
reportCountStatistic("Identity cache size", caches.identity);
|
||||
reportCountStatistic("Subtype cache size", caches.subtype);
|
||||
reportCountStatistic("Strict subtype cache size", caches.strictSubtype);
|
||||
performance.forEachMeasure((name, duration) => reportTimeStatistic(`${name} time`, duration));
|
||||
if (performance.isEnabled()) {
|
||||
performance.forEachMeasure((name, duration) => reportTimeStatistic(`${name} time`, duration));
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (performance.isEnabled()) {
|
||||
// Individual component times.
|
||||
// Note: To match the behavior of previous versions of the compiler, the reported parse time includes
|
||||
// I/O read time and processing time for triple-slash references and module imports, and the reported
|
||||
|
@ -672,10 +674,16 @@ namespace ts {
|
|||
reportTimeStatistic("Check time", checkTime);
|
||||
reportTimeStatistic("Emit time", emitTime);
|
||||
}
|
||||
reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime);
|
||||
if (performance.isEnabled()) {
|
||||
reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime);
|
||||
}
|
||||
reportStatistics();
|
||||
|
||||
performance.disable();
|
||||
if (!performance.isEnabled()) {
|
||||
sys.write(Diagnostics.Performance_timings_for_diagnostics_or_extendedDiagnostics_are_not_available_in_this_session_A_native_implementation_of_the_Web_Performance_API_could_not_be_found.message + "\n");
|
||||
}
|
||||
else {
|
||||
performance.disable();
|
||||
}
|
||||
}
|
||||
|
||||
function reportStatistics() {
|
||||
|
|
Loading…
Reference in a new issue