Spaces:
Runtime error
Runtime error
let fastNow = Date.now() | |
let fastNowTimeout | |
const fastTimers = [] | |
function onTimeout () { | |
fastNow = Date.now() | |
let len = fastTimers.length | |
let idx = 0 | |
while (idx < len) { | |
const timer = fastTimers[idx] | |
if (timer.state === 0) { | |
timer.state = fastNow + timer.delay | |
} else if (timer.state > 0 && fastNow >= timer.state) { | |
timer.state = -1 | |
timer.callback(timer.opaque) | |
} | |
if (timer.state === -1) { | |
timer.state = -2 | |
if (idx !== len - 1) { | |
fastTimers[idx] = fastTimers.pop() | |
} else { | |
fastTimers.pop() | |
} | |
len -= 1 | |
} else { | |
idx += 1 | |
} | |
} | |
if (fastTimers.length > 0) { | |
refreshTimeout() | |
} | |
} | |
function refreshTimeout () { | |
if (fastNowTimeout && fastNowTimeout.refresh) { | |
fastNowTimeout.refresh() | |
} else { | |
clearTimeout(fastNowTimeout) | |
fastNowTimeout = setTimeout(onTimeout, 1e3) | |
if (fastNowTimeout.unref) { | |
fastNowTimeout.unref() | |
} | |
} | |
} | |
class Timeout { | |
constructor (callback, delay, opaque) { | |
this.callback = callback | |
this.delay = delay | |
this.opaque = opaque | |
// -2 not in timer list | |
// -1 in timer list but inactive | |
// 0 in timer list waiting for time | |
// > 0 in timer list waiting for time to expire | |
this.state = -2 | |
this.refresh() | |
} | |
refresh () { | |
if (this.state === -2) { | |
fastTimers.push(this) | |
if (!fastNowTimeout || fastTimers.length === 1) { | |
refreshTimeout() | |
} | |
} | |
this.state = 0 | |
} | |
clear () { | |
this.state = -1 | |
} | |
} | |
module.exports = { | |
setTimeout (callback, delay, opaque) { | |
return delay < 1e3 | |
? setTimeout(callback, delay, opaque) | |
: new Timeout(callback, delay, opaque) | |
}, | |
clearTimeout (timeout) { | |
if (timeout instanceof Timeout) { | |
timeout.clear() | |
} else { | |
clearTimeout(timeout) | |
} | |
} | |
} | |