Skip to content

Commit 9d3cc38

Browse files
retyuimeta-codesync[bot]
authored andcommitted
chore: Clear timer functions do noting when a timer does not exist (#55126)
Summary: Issue: #55104 ## Changelog: [GENERAL] [CHANGED] - `cancelAnimationFrame`, `clearImmediate`, `clearTimeout` and `clearInterval` do nothing If there is no callback associated the given handle Pull Request resolved: #55126 Test Plan: The next code should not throw any errors (runtime and TS) ```tsx const id1 = requestAnimationFrame(()=> {}); cancelAnimationFrame(id1); cancelAnimationFrame(id1); // clear twice the same id cancelAnimationFrame(-1); cancelAnimationFrame(null); cancelAnimationFrame(undefined); const id2 = setImmediate(()=> {}); clearImmediate(id2); clearImmediate(id2); // clear twice the same id clearImmediate(-1); clearImmediate(null); clearImmediate(undefined); const id3 = setTimeout(()=> {}, 1000); clearTimeout(id3); clearTimeout(id3); // clear twice the same id clearTimeout(-1); clearTimeout(null); clearTimeout(undefined); const id4 = setInterval(()=> {}, 1000); clearInterval(id4); clearInterval(id4); // clear twice the same id clearInterval(-1); clearInterval(null); clearInterval(undefined); ``` Reviewed By: cortinico Differential Revision: D90615301 Pulled By: philIip fbshipit-source-id: e5102a137bac6492d0f89bb02ef11eeca9977a9b
1 parent cd3a9c5 commit 9d3cc38

3 files changed

Lines changed: 60 additions & 6 deletions

File tree

packages/react-native/ReactCommon/react/runtime/TimerManager.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,15 @@ TimerHandle TimerManager::createRecurringTimer(
134134

135135
void TimerManager::deleteTimer(jsi::Runtime& runtime, TimerHandle timerHandle) {
136136
if (timerHandle < 0) {
137-
throw jsi::JSError(runtime, "clearTimeout called with an invalid handle");
137+
/**
138+
* Do nothing for negative values to match web spec.
139+
*
140+
* cancelAnimationFrame:
141+
* https://www.w3.org/TR/animation-timing/#Window-interface-extensions
142+
* clearTimeout:
143+
* https://developer.mozilla.org/en-US/docs/Web/API/Window/clearTimeout#notes
144+
*/
145+
return;
138146
}
139147

140148
platformTimerRegistry_->deleteTimer(timerHandle);
@@ -145,7 +153,13 @@ void TimerManager::deleteRecurringTimer(
145153
jsi::Runtime& runtime,
146154
TimerHandle timerHandle) {
147155
if (timerHandle < 0) {
148-
throw jsi::JSError(runtime, "clearInterval called with an invalid handle");
156+
/**
157+
* Do nothing for negative values to match web spec.
158+
*
159+
* clearInterval:
160+
* https://developer.mozilla.org/en-US/docs/Web/API/Window/clearInterval
161+
*/
162+
return;
149163
}
150164

151165
platformTimerRegistry_->deleteTimer(timerHandle);

packages/react-native/src/types/globals.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ declare global {
101101

102102
// #region Timer Functions
103103

104-
function clearInterval(handle: number): void;
105-
function clearTimeout(handle: number): void;
104+
function clearInterval(handle: number | null | undefined): void;
105+
function clearTimeout(handle: number | null | undefined): void;
106106
function setInterval(handler: () => void, timeout: number): number;
107107
function setInterval<Args extends any[]>(
108108
handler: (...args: Args) => void,
@@ -115,14 +115,14 @@ declare global {
115115
timeout?: number,
116116
...args: Args
117117
): number;
118-
function clearImmediate(handle: number): void;
118+
function clearImmediate(handle: number | null | undefined): void;
119119
function setImmediate(handler: () => void): number;
120120
function setImmediate<Args extends any[]>(
121121
handler: (...args: Args) => void,
122122
...args: Args
123123
): number;
124124

125-
function cancelAnimationFrame(handle: number): void;
125+
function cancelAnimationFrame(handle: number | null | undefined): void;
126126
function requestAnimationFrame(callback: (time: number) => void): number;
127127

128128
function fetchBundle(

packages/react-native/types/__typetests__/globals.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
const noop = () => { };
99

1010
function testInterval() {
11+
clearInterval(null);
12+
clearInterval(undefined);
13+
1114
let handle = setInterval(noop, 0);
1215
clearInterval(handle);
1316

@@ -38,6 +41,9 @@ function testInterval() {
3841
}
3942

4043
function testTimeout() {
44+
clearTimeout(null);
45+
clearTimeout(undefined);
46+
4147
let handle = setTimeout(noop, 0);
4248
clearTimeout(handle);
4349

@@ -68,6 +74,9 @@ function testTimeout() {
6874
}
6975

7076
function testImmediate() {
77+
clearImmediate(null);
78+
clearImmediate(undefined);
79+
7180
let handle = setImmediate(noop);
7281
clearImmediate(handle);
7382

@@ -97,6 +106,37 @@ function testImmediate() {
97106
clearImmediate(handle);
98107
}
99108

109+
function testRequestAnimationFrame(){
110+
cancelAnimationFrame(null);
111+
cancelAnimationFrame(undefined);
112+
113+
let handle = requestAnimationFrame((time: number) => {
114+
console.log('time', time);
115+
});
116+
cancelAnimationFrame(handle);
117+
118+
handle = requestAnimationFrame(() => {
119+
console.log('no time');
120+
});
121+
cancelAnimationFrame(handle);
122+
123+
handle = requestAnimationFrame(
124+
// @ts-expect-error
125+
(notTime: string) => {
126+
console.log('argument have to be number', notTime);
127+
});
128+
cancelAnimationFrame(handle);
129+
130+
// @ts-expect-error
131+
const resultHaveToBeNum: string = requestAnimationFrame(() => {
132+
console.log('result have to be number');
133+
});
134+
cancelAnimationFrame(
135+
// @ts-expect-error
136+
resultHaveToBeNum
137+
);
138+
}
139+
100140
const fetchCopy: WindowOrWorkerGlobalScope['fetch'] = fetch;
101141

102142
const myHeaders = new Headers();

0 commit comments

Comments
 (0)