virtualTimeApi.ts ×7

Frontier kind: Code frontier

unlabeled · c_68b3f1793250

459 tests · 5197 LOC · 31 files · introduces 0 tests · 96 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
13 ranges96 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
673 ranges5197 lines · 31 files · Browse complete extent
All tests (intent)
459 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 96 introduced LOC across 13 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/base/test/common/virtualScheduling/virtualTimeApi.ts 64 introduced LOC · 7 ranges

Open complete file

46 */
47 export function createVirtualTimeApi(
48 > clock: VirtualClock, virtualTimeApi.ts
49 > options?: CreateVirtualTimeApiOptions,
50 > ): TimeApi {
51 >
52 > function virtualSetTimeout(handler: () => void, timeout: number = 0): IDisposable {
53 const stack = new Error().stack;
54 const trace = TraceContext.instance.currentTrace().child(`setTimeout(${timeout}ms)`, stack);
60 });
61 }
63 > function virtualClearTimeout(id: unknown): void {
64 asDisposable(id)?.dispose();
65 }
67 > function virtualSetInterval(handler: () => void, interval: number): IDisposable {
68 const stack = new Error().stack;
69 const baseTrace = TraceContext.instance.currentTrace().child(`setInterval(${interval}ms)`, stack);
96 };
97 }
99 > function virtualClearInterval(id: unknown): void {
100 asDisposable(id)?.dispose();
101 }
103 > // A faux `Date` that returns virtual time from `now()` and uses virtual
104 > // time as the default constructor argument; everything else delegates.
105 > // The `Date` constructor is an exotic object whose call/construct
106 > // signatures aren't expressible without a structural mismatch — we go
107 > // through `unknown` for the tagging mutations rather than widening to
108 > // `any`.
109 > const OriginalDate = realTimeApi.Date;
110 > // `Date` is overloaded (zero-arg, one-arg, multi-arg). `ConstructorParameters`
111 > // only sees the last overload, so we type args as `unknown[]` and forward
112 > // them through a typed cast at the call site.
113 > function VirtualDate(this: unknown, ...args: unknown[]): unknown {
114 if (!(this instanceof VirtualDate)) {
115 return new OriginalDate(clock.now).toString();
120 return new (OriginalDate as new (...a: unknown[]) => Date)(...args);
121 }
122 > // Static-property tagging. Use a typed `Record` view of the function virtualTimeApi.ts
123 > // rather than `any`. We skip non-writable own properties (`length`,
124 > // `name` on a function would throw) and then explicitly set the few
125 > // statics callers reach for.
126 > const dateStatics = VirtualDate as unknown as Record<string, unknown>;
127 > const originalStatics = OriginalDate as unknown as Record<string, unknown>;
128 > for (const key of Object.getOwnPropertyNames(OriginalDate)) {
129 > const desc = Object.getOwnPropertyDescriptor(OriginalDate, key);
130 > if (desc && (desc.writable || desc.set)) {
131 > dateStatics[key] = originalStatics[key];
132 > }
133 > }
134 > dateStatics.now = () => clock.now;
135 > dateStatics.parse = OriginalDate.parse;
136 > dateStatics.UTC = OriginalDate.UTC;
137 > VirtualDate.prototype = OriginalDate.prototype;
138 >
139 > const api: TimeApi = {
140 > setTimeout: virtualSetTimeout as unknown as TimeApi['setTimeout'],
141 > clearTimeout: virtualClearTimeout,
142 > setInterval: virtualSetInterval as unknown as TimeApi['setInterval'],
143 > clearInterval: virtualClearInterval,
144 > Date: VirtualDate as unknown as DateConstructor,
145 > };
146 >
147 > // Expose the real setTimeout as `originalFn` on the virtual one. The
148 > // component-explorer host's polling loop reads this to escape virtual
149 > // time when waiting for renders to settle.
150 > (api.setTimeout as unknown as { originalFn: TimeApi['setTimeout'] }).originalFn = realTimeApi.setTimeout;
151 >
152 > if (options?.fakeRequestAnimationFrame) {
153 let rafIdCounter = 0;
154 const rafDisposables = new Map<number, IDisposable>();
180 }) as TimeApi['cancelAnimationFrame'];
181 }
183 > // Trace defaults: ensure handlers fired inside virtual time get the
184 > // current trace at *schedule* time, not at fire time. The processor
185 > // already wraps execution in `runAsHandler`, so when virtual events
186 > // fire inside the processor the trace is set correctly. This block is
187 > // just a safety net for callers that step the clock manually.
188 > void ROOT_TRACE;
189 >
190 > return api;
191 > }
192
193 // Re-exported for convenience: many tests want to install both at once.
src/vs/base/test/common/virtualScheduling/globalTimeApi.ts 32 introduced LOC · 6 ranges

Open complete file

17 * — which has its own `originalFn` set at module load.
18 */
19 > function ensureSetTimeoutOriginalFn(fn: TimeApi['setTimeout'], previousFn: TimeApi['setTimeout']): TimeApi['setTimeout'] { globalTimeApi.ts
20 > const tagged = fn as TimeApi['setTimeout'] & { originalFn?: TimeApi['setTimeout'] };
21 > if (!tagged.originalFn) {
22 > const previousTagged = previousFn as TimeApi['setTimeout'] & { originalFn?: TimeApi['setTimeout'] };
23 > const realTagged = realTimeApi.setTimeout as TimeApi['setTimeout'] & { originalFn?: TimeApi['setTimeout'] };
24 > tagged.originalFn = previousTagged.originalFn ?? realTagged.originalFn ?? realTimeApi.setTimeout;
25 > }
26 > return tagged;
27 > }
28
29 /**
43 */
44 export function pushGlobalTimeApi(api: TimeApi): IDisposable {
45 > const previous = captureGlobalTimeApi(); globalTimeApi.ts
46 >
47 > globalThis.setTimeout = ensureSetTimeoutOriginalFn(api.setTimeout, previous.setTimeout) as unknown as AsGlobal<'setTimeout'>;
48 > globalThis.clearTimeout = api.clearTimeout as unknown as AsGlobal<'clearTimeout'>;
49 > globalThis.setInterval = api.setInterval as unknown as AsGlobal<'setInterval'>;
50 > globalThis.clearInterval = api.clearInterval as unknown as AsGlobal<'clearInterval'>;
51 > globalThis.Date = api.Date;
52 >
53 > if (api.requestAnimationFrame) {
54 globalThis.requestAnimationFrame = api.requestAnimationFrame as unknown as AsGlobal<'requestAnimationFrame'>;
55 }
56 > if (api.cancelAnimationFrame) { globalTimeApi.ts
57 globalThis.cancelAnimationFrame = api.cancelAnimationFrame as unknown as AsGlobal<'cancelAnimationFrame'>;
58 }
60 > return {
61 > dispose: () => {
62 > globalThis.setTimeout = ensureSetTimeoutOriginalFn(previous.setTimeout, previous.setTimeout) as unknown as AsGlobal<'setTimeout'>;
63 > globalThis.clearTimeout = previous.clearTimeout as unknown as AsGlobal<'clearTimeout'>;
64 > globalThis.setInterval = previous.setInterval as unknown as AsGlobal<'setInterval'>;
65 > globalThis.clearInterval = previous.clearInterval as unknown as AsGlobal<'clearInterval'>;
66 > globalThis.Date = previous.Date;
67 > if (previous.requestAnimationFrame) {
68 globalThis.requestAnimationFrame = previous.requestAnimationFrame as unknown as AsGlobal<'requestAnimationFrame'>;
69 }
70 > if (previous.cancelAnimationFrame) { globalTimeApi.ts
71 globalThis.cancelAnimationFrame = previous.cancelAnimationFrame as unknown as AsGlobal<'cancelAnimationFrame'>;
72 }
74 > };
75 > }
76
77 // One-shot tag on the *real* setTimeout: lets callers (e.g. the