Skip to content

Commit 220e49c

Browse files
committed
ref: Move time-related utils to a new file
1 parent 4a11356 commit 220e49c

File tree

3 files changed

+101
-97
lines changed

3 files changed

+101
-97
lines changed

packages/utils/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export * from './async';
22
export * from './browser';
33
export * from './dsn';
44
export * from './error';
5+
export * from './instrument';
56
export * from './is';
67
export * from './logger';
78
export * from './memo';
@@ -14,4 +15,4 @@ export * from './stacktrace';
1415
export * from './string';
1516
export * from './supports';
1617
export * from './syncpromise';
17-
export * from './instrument';
18+
export * from './time';

packages/utils/src/misc.ts

Lines changed: 1 addition & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22
import { Event, Integration, StackFrame, WrappedFunction } from '@sentry/types';
33

4-
import { dynamicRequire, isNodeEnv } from './node';
4+
import { isNodeEnv } from './node';
55
import { snipLine } from './string';
66

77
/** Internal */
@@ -38,13 +38,6 @@ export function getGlobalObject<T>(): T & SentryGlobal {
3838
: fallbackGlobalObject) as T & SentryGlobal;
3939
}
4040

41-
/**
42-
* Determines if running in react native
43-
*/
44-
export function isReactNative(): boolean {
45-
return getGlobalObject<Window>().navigator?.product === 'ReactNative';
46-
}
47-
4841
/**
4942
* Extended Window interface that allows for Crypto API usage in IE browsers
5043
*/
@@ -241,94 +234,6 @@ export function getLocationHref(): string {
241234
}
242235
}
243236

244-
const INITIAL_TIME = Date.now();
245-
let prevNow = 0;
246-
247-
/**
248-
* Cross platform compatible partial performance implementation
249-
*/
250-
interface CrossPlatformPerformance {
251-
timeOrigin: number;
252-
/**
253-
* Returns the current timestamp in ms
254-
*/
255-
now(): number;
256-
}
257-
258-
const performanceFallback: CrossPlatformPerformance = {
259-
now(): number {
260-
let now = Date.now() - INITIAL_TIME;
261-
if (now < prevNow) {
262-
now = prevNow;
263-
}
264-
prevNow = now;
265-
return now;
266-
},
267-
timeOrigin: INITIAL_TIME,
268-
};
269-
270-
/**
271-
* Performance wrapper for react native as performance.now() has been found to start off with an unusual offset.
272-
*/
273-
function getReactNativePerformanceWrapper(): CrossPlatformPerformance {
274-
// Performance only available >= RN 0.63
275-
const { performance } = getGlobalObject<Window>();
276-
if (performance && typeof performance.now === 'function') {
277-
const INITIAL_OFFSET = performance.now();
278-
279-
return {
280-
now(): number {
281-
return performance.now() - INITIAL_OFFSET;
282-
},
283-
timeOrigin: INITIAL_TIME,
284-
};
285-
}
286-
return performanceFallback;
287-
}
288-
289-
export const crossPlatformPerformance: CrossPlatformPerformance = ((): CrossPlatformPerformance => {
290-
// React Native's performance.now() starts with a gigantic offset, so we need to wrap it.
291-
if (isReactNative()) {
292-
return getReactNativePerformanceWrapper();
293-
}
294-
295-
if (isNodeEnv()) {
296-
try {
297-
const perfHooks = dynamicRequire(module, 'perf_hooks') as { performance: CrossPlatformPerformance };
298-
return perfHooks.performance;
299-
} catch (_) {
300-
return performanceFallback;
301-
}
302-
}
303-
304-
const { performance } = getGlobalObject<Window>();
305-
306-
if (!performance || !performance.now) {
307-
return performanceFallback;
308-
}
309-
310-
// Polyfill for performance.timeOrigin.
311-
//
312-
// While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
313-
// is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
314-
if (performance.timeOrigin === undefined) {
315-
// As of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always a
316-
// valid fallback. In the absence of a initial time provided by the browser, fallback to INITIAL_TIME.
317-
// @ts-ignore ignored because timeOrigin is a readonly property but we want to override
318-
// eslint-disable-next-line deprecation/deprecation
319-
performance.timeOrigin = (performance.timing && performance.timing.navigationStart) || INITIAL_TIME;
320-
}
321-
322-
return performance;
323-
})();
324-
325-
/**
326-
* Returns a timestamp in seconds with milliseconds precision since the UNIX epoch calculated with the monotonic clock.
327-
*/
328-
export function timestampWithMs(): number {
329-
return (crossPlatformPerformance.timeOrigin + crossPlatformPerformance.now()) / 1000;
330-
}
331-
332237
// https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
333238
const SEMVER_REGEXP = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
334239

packages/utils/src/time.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { getGlobalObject } from './misc';
2+
import { dynamicRequire, isNodeEnv } from './node';
3+
4+
const INITIAL_TIME = Date.now();
5+
6+
/**
7+
* Cross platform compatible partial performance implementation
8+
*/
9+
interface CrossPlatformPerformance {
10+
timeOrigin: number;
11+
/**
12+
* Returns the current timestamp in ms
13+
*/
14+
now(): number;
15+
}
16+
17+
let prevNow = 0;
18+
19+
const performanceFallback: CrossPlatformPerformance = {
20+
now(): number {
21+
let now = Date.now() - INITIAL_TIME;
22+
if (now < prevNow) {
23+
now = prevNow;
24+
}
25+
prevNow = now;
26+
return now;
27+
},
28+
timeOrigin: INITIAL_TIME,
29+
};
30+
31+
export const crossPlatformPerformance: CrossPlatformPerformance = ((): CrossPlatformPerformance => {
32+
// React Native's performance.now() starts with a gigantic offset, so we need to wrap it.
33+
if (isReactNative()) {
34+
return getReactNativePerformanceWrapper();
35+
}
36+
37+
if (isNodeEnv()) {
38+
try {
39+
const perfHooks = dynamicRequire(module, 'perf_hooks') as { performance: CrossPlatformPerformance };
40+
return perfHooks.performance;
41+
} catch (_) {
42+
return performanceFallback;
43+
}
44+
}
45+
46+
const { performance } = getGlobalObject<Window>();
47+
48+
if (!performance || !performance.now) {
49+
return performanceFallback;
50+
}
51+
52+
// Polyfill for performance.timeOrigin.
53+
//
54+
// While performance.timing.navigationStart is deprecated in favor of performance.timeOrigin, performance.timeOrigin
55+
// is not as widely supported. Namely, performance.timeOrigin is undefined in Safari as of writing.
56+
if (performance.timeOrigin === undefined) {
57+
// As of writing, performance.timing is not available in Web Workers in mainstream browsers, so it is not always a
58+
// valid fallback. In the absence of a initial time provided by the browser, fallback to INITIAL_TIME.
59+
// @ts-ignore ignored because timeOrigin is a readonly property but we want to override
60+
// eslint-disable-next-line deprecation/deprecation
61+
performance.timeOrigin = (performance.timing && performance.timing.navigationStart) || INITIAL_TIME;
62+
}
63+
64+
return performance;
65+
})();
66+
67+
/**
68+
* Returns a timestamp in seconds with milliseconds precision since the UNIX epoch calculated with the monotonic clock.
69+
*/
70+
export function timestampWithMs(): number {
71+
return (crossPlatformPerformance.timeOrigin + crossPlatformPerformance.now()) / 1000;
72+
}
73+
74+
/**
75+
* Determines if running in react native
76+
*/
77+
export function isReactNative(): boolean {
78+
return getGlobalObject<Window>().navigator?.product === 'ReactNative';
79+
}
80+
81+
/**
82+
* Performance wrapper for react native as performance.now() has been found to start off with an unusual offset.
83+
*/
84+
function getReactNativePerformanceWrapper(): CrossPlatformPerformance {
85+
// Performance only available >= RN 0.63
86+
const { performance } = getGlobalObject<Window>();
87+
if (performance && typeof performance.now === 'function') {
88+
const INITIAL_OFFSET = performance.now();
89+
90+
return {
91+
now(): number {
92+
return performance.now() - INITIAL_OFFSET;
93+
},
94+
timeOrigin: INITIAL_TIME,
95+
};
96+
}
97+
return performanceFallback;
98+
}

0 commit comments

Comments
 (0)