@@ -15,6 +15,8 @@ const {
1515 timerRemoveRef,
1616} = internalBinding ( 'timers' ) ;
1717
18+ const { DOMException } = require ( 'dom-exception' ) ;
19+
1820/**
1921 * Implement Node.js-style `timeoutId` class returned from setTimeout() and setInterval()
2022 * @see https://nodejs.org/api/timers.html#class-timeout
@@ -63,11 +65,16 @@ class Timeout
6365 }
6466
6567 /**
66- * @returns a number that can be used to reference this timeout
68+ * Sets the timer's start time to the current time,
69+ * and reschedules the timer to call its callback at the previously specified duration adjusted to the current time.
70+ *
71+ * Using this on a timer that has already called its callback will reactivate the timer.
6772 */
68- [ Symbol . toPrimitive ] ( )
73+ refresh ( )
6974 {
70- return this . #numericId;
75+ throw new DOMException ( 'Timeout.refresh() method is not supported by PythonMonkey.' , 'NotSupportedError' ) ;
76+ // TODO: Do we really need to closely resemble the Node.js API?
77+ // This one is not easy to implement since we need to memorize the callback function and delay parameters in every `setTimeout`/`setInterval` call.
7178 }
7279
7380 /**
@@ -78,18 +85,23 @@ class Timeout
7885 {
7986 return clearTimeout ( this ) ;
8087 }
88+
89+ /**
90+ * @returns a number that can be used to reference this timeout
91+ */
92+ [ Symbol . toPrimitive ] ( )
93+ {
94+ return this . #numericId;
95+ }
8196}
8297
8398/**
84- * Implement the `setTimeout` global function
85- * @see https://developer.mozilla.org/en-US/docs/Web/API/setTimeout and
86- * @see https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
99+ * Normalize the arguments to `setTimeout` or `setInterval`
87100 * @param {Function | string } handler
88- * @param {number } delayMs timeout milliseconds, use value of 0 if this is omitted
89- * @param {any[] } args additional arguments to be passed to the `handler`
90- * @return {Timeout } timeoutId
101+ * @param {number } delayMs timeout milliseconds
102+ * @param {any[] } additionalArgs additional arguments to be passed to the `handler`
91103 */
92- function setTimeout ( handler , delayMs = 0 , ... args )
104+ function _normalizeTimerArgs ( handler , delayMs , additionalArgs )
93105{
94106 // Ensure the first parameter is a function
95107 // We support passing a `code` string to `setTimeout` as the callback function
@@ -102,7 +114,7 @@ function setTimeout(handler, delayMs = 0, ...args)
102114 // Wrap the job function into a bound function with the given additional arguments
103115 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
104116 /** @type {Function } */
105- const boundHandler = handler . bind ( thisArg , ...args ) ;
117+ const boundHandler = handler . bind ( thisArg , ...additionalArgs ) ;
106118
107119 // Get the delay time in seconds
108120 // JS `setTimeout` takes milliseconds, but Python takes seconds
@@ -111,7 +123,22 @@ function setTimeout(handler, delayMs = 0, ...args)
111123 delayMs = 0 ; // as spec-ed
112124 const delaySeconds = delayMs / 1000 ; // convert ms to s
113125
114- return new Timeout ( enqueueWithDelay ( boundHandler , delaySeconds ) ) ;
126+ return { boundHandler, delaySeconds } ;
127+ }
128+
129+ /**
130+ * Implement the `setTimeout` global function
131+ * @see https://developer.mozilla.org/en-US/docs/Web/API/setTimeout and
132+ * @see https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
133+ * @param {Function | string } handler
134+ * @param {number } delayMs timeout milliseconds, use value of 0 if this is omitted
135+ * @param {any[] } args additional arguments to be passed to the `handler`
136+ * @return {Timeout } timeoutId
137+ */
138+ function setTimeout ( handler , delayMs = 0 , ...args )
139+ {
140+ const { boundHandler, delaySeconds } = _normalizeTimerArgs ( handler , delayMs , args ) ;
141+ return new Timeout ( enqueueWithDelay ( boundHandler , delaySeconds , false ) ) ;
115142}
116143
117144/**
@@ -130,13 +157,43 @@ function clearTimeout(timeoutId)
130157 return cancelByTimeoutId ( Number ( timeoutId ) ) ;
131158}
132159
160+ /**
161+ * Implement the `setInterval` global function
162+ * @see https://developer.mozilla.org/en-US/docs/Web/API/setInterval and
163+ * @see https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
164+ * @param {Function | string } handler
165+ * @param {number } delayMs timeout milliseconds, use value of 0 if this is omitted
166+ * @param {any[] } args additional arguments to be passed to the `handler`
167+ * @return {Timeout } timeoutId
168+ */
169+ function setInterval ( handler , delayMs = 0 , ...args )
170+ {
171+ const { boundHandler, delaySeconds } = _normalizeTimerArgs ( handler , delayMs , args ) ;
172+ return new Timeout ( enqueueWithDelay ( boundHandler , delaySeconds , true ) ) ;
173+ }
174+
175+ /**
176+ * Implement the `clearInterval` global function
177+ * @alias to `clearTimeout`
178+ * @see https://developer.mozilla.org/en-US/docs/Web/API/clearInterval
179+ */
180+ const clearInterval = clearTimeout ;
181+
133182// expose the `Timeout` class
134183setTimeout . Timeout = Timeout ;
184+ setInterval . Timeout = Timeout ;
135185
136186if ( ! globalThis . setTimeout )
137187 globalThis . setTimeout = setTimeout ;
138188if ( ! globalThis . clearTimeout )
139189 globalThis . clearTimeout = clearTimeout ;
140190
191+ if ( ! globalThis . setInterval )
192+ globalThis . setInterval = setInterval ;
193+ if ( ! globalThis . clearInterval )
194+ globalThis . clearInterval = clearInterval ;
195+
141196exports . setTimeout = setTimeout ;
142197exports . clearTimeout = clearTimeout ;
198+ exports . setInterval = setInterval ;
199+ exports . clearInterval = clearInterval ;
0 commit comments