2024-01-01 14:58:21 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2020-07-19 13:49:44 -04:00
|
|
|
|
2023-12-07 08:21:01 -05:00
|
|
|
import { core, primordials } from "ext:core/mod.js";
|
2024-11-08 17:20:24 -05:00
|
|
|
import { op_defer } from "ext:core/ops";
|
2023-02-07 14:22:46 -05:00
|
|
|
const {
|
|
|
|
PromisePrototypeThen,
|
|
|
|
TypeError,
|
|
|
|
indirectEval,
|
2024-03-01 13:15:18 -05:00
|
|
|
ReflectApply,
|
2023-02-07 14:22:46 -05:00
|
|
|
} = primordials;
|
2024-08-28 22:25:38 -04:00
|
|
|
const {
|
|
|
|
getAsyncContext,
|
|
|
|
setAsyncContext,
|
|
|
|
} = core;
|
2024-01-10 17:37:25 -05:00
|
|
|
|
2023-03-08 06:44:54 -05:00
|
|
|
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
2023-02-07 14:22:46 -05:00
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2024-03-01 13:15:18 -05:00
|
|
|
function checkThis(thisArg) {
|
|
|
|
if (thisArg !== null && thisArg !== undefined && thisArg !== globalThis) {
|
|
|
|
throw new TypeError("Illegal invocation");
|
2023-02-07 14:22:46 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-03-01 13:15:18 -05:00
|
|
|
* Call a callback function immediately.
|
2023-02-07 14:22:46 -05:00
|
|
|
*/
|
2024-03-01 13:15:18 -05:00
|
|
|
function setImmediate(callback, ...args) {
|
2024-08-28 22:25:38 -04:00
|
|
|
const asyncContext = getAsyncContext();
|
|
|
|
return core.queueImmediate(() => {
|
|
|
|
const oldContext = getAsyncContext();
|
|
|
|
try {
|
|
|
|
setAsyncContext(asyncContext);
|
|
|
|
return ReflectApply(callback, globalThis, args);
|
|
|
|
} finally {
|
|
|
|
setAsyncContext(oldContext);
|
|
|
|
}
|
|
|
|
});
|
2023-02-07 14:22:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2024-03-01 13:15:18 -05:00
|
|
|
* Call a callback function after a delay.
|
2023-02-07 14:22:46 -05:00
|
|
|
*/
|
|
|
|
function setTimeout(callback, timeout = 0, ...args) {
|
|
|
|
checkThis(this);
|
2024-03-01 13:15:18 -05:00
|
|
|
// If callback is a string, replace it with a function that evals the string on every timeout
|
2023-02-07 14:22:46 -05:00
|
|
|
if (typeof callback !== "function") {
|
2024-03-01 13:15:18 -05:00
|
|
|
const unboundCallback = webidl.converters.DOMString(callback);
|
|
|
|
callback = () => indirectEval(unboundCallback);
|
|
|
|
}
|
2024-08-28 22:25:38 -04:00
|
|
|
const unboundCallback = callback;
|
|
|
|
const asyncContext = getAsyncContext();
|
|
|
|
callback = () => {
|
|
|
|
const oldContext = getAsyncContext();
|
|
|
|
try {
|
|
|
|
setAsyncContext(asyncContext);
|
|
|
|
ReflectApply(unboundCallback, globalThis, args);
|
|
|
|
} finally {
|
|
|
|
setAsyncContext(oldContext);
|
|
|
|
}
|
|
|
|
};
|
2023-02-07 14:22:46 -05:00
|
|
|
timeout = webidl.converters.long(timeout);
|
2024-03-01 13:15:18 -05:00
|
|
|
return core.queueUserTimer(
|
|
|
|
core.getTimerDepth() + 1,
|
|
|
|
false,
|
|
|
|
timeout,
|
|
|
|
callback,
|
|
|
|
);
|
2023-02-07 14:22:46 -05:00
|
|
|
}
|
2020-07-19 13:49:44 -04:00
|
|
|
|
2024-03-01 13:15:18 -05:00
|
|
|
/**
|
|
|
|
* Call a callback function after a delay.
|
|
|
|
*/
|
2023-02-07 14:22:46 -05:00
|
|
|
function setInterval(callback, timeout = 0, ...args) {
|
|
|
|
checkThis(this);
|
|
|
|
if (typeof callback !== "function") {
|
2024-03-01 13:15:18 -05:00
|
|
|
const unboundCallback = webidl.converters.DOMString(callback);
|
|
|
|
callback = () => indirectEval(unboundCallback);
|
2021-12-09 03:00:55 -05:00
|
|
|
}
|
2024-08-28 22:25:38 -04:00
|
|
|
const unboundCallback = callback;
|
|
|
|
const asyncContext = getAsyncContext();
|
|
|
|
callback = () => {
|
|
|
|
const oldContext = getAsyncContext(asyncContext);
|
|
|
|
try {
|
|
|
|
setAsyncContext(asyncContext);
|
|
|
|
ReflectApply(unboundCallback, globalThis, args);
|
|
|
|
} finally {
|
|
|
|
setAsyncContext(oldContext);
|
|
|
|
}
|
|
|
|
};
|
2023-05-22 18:19:44 -04:00
|
|
|
timeout = webidl.converters.long(timeout);
|
2024-03-01 13:15:18 -05:00
|
|
|
return core.queueUserTimer(
|
|
|
|
core.getTimerDepth() + 1,
|
|
|
|
true,
|
|
|
|
timeout,
|
|
|
|
callback,
|
|
|
|
);
|
2023-05-22 18:19:44 -04:00
|
|
|
}
|
|
|
|
|
2024-03-01 13:15:18 -05:00
|
|
|
/**
|
|
|
|
* Clear a timeout or interval.
|
|
|
|
*/
|
2023-02-07 14:22:46 -05:00
|
|
|
function clearTimeout(id = 0) {
|
|
|
|
checkThis(this);
|
|
|
|
id = webidl.converters.long(id);
|
2024-03-01 13:15:18 -05:00
|
|
|
core.cancelTimer(id);
|
2023-02-07 14:22:46 -05:00
|
|
|
}
|
2021-12-09 03:00:55 -05:00
|
|
|
|
2024-03-01 13:15:18 -05:00
|
|
|
/**
|
|
|
|
* Clear a timeout or interval.
|
|
|
|
*/
|
2023-02-07 14:22:46 -05:00
|
|
|
function clearInterval(id = 0) {
|
|
|
|
checkThis(this);
|
2024-03-01 13:15:18 -05:00
|
|
|
id = webidl.converters.long(id);
|
|
|
|
core.cancelTimer(id);
|
2023-02-07 14:22:46 -05:00
|
|
|
}
|
|
|
|
|
2024-03-01 13:15:18 -05:00
|
|
|
/**
|
|
|
|
* Mark a timer as not blocking event loop exit.
|
|
|
|
*/
|
|
|
|
function unrefTimer(id) {
|
|
|
|
core.unrefTimer(id);
|
2023-02-07 14:22:46 -05:00
|
|
|
}
|
|
|
|
|
2024-03-01 13:15:18 -05:00
|
|
|
/**
|
|
|
|
* Mark a timer as blocking event loop exit.
|
|
|
|
*/
|
|
|
|
function refTimer(id) {
|
|
|
|
core.refTimer(id);
|
2023-02-07 14:22:46 -05:00
|
|
|
}
|
|
|
|
|
2023-12-24 08:04:32 -05:00
|
|
|
// Defer to avoid starving the event loop. Not using queueMicrotask()
|
|
|
|
// for that reason: it lets promises make forward progress but can
|
|
|
|
// still starve other parts of the event loop.
|
|
|
|
function defer(go) {
|
2024-03-01 13:15:18 -05:00
|
|
|
PromisePrototypeThen(op_defer(), () => go());
|
2023-12-24 08:04:32 -05:00
|
|
|
}
|
|
|
|
|
2023-02-07 14:22:46 -05:00
|
|
|
export {
|
|
|
|
clearInterval,
|
|
|
|
clearTimeout,
|
2023-12-24 08:04:32 -05:00
|
|
|
defer,
|
2023-02-07 14:22:46 -05:00
|
|
|
refTimer,
|
2024-03-01 13:15:18 -05:00
|
|
|
setImmediate,
|
2023-02-07 14:22:46 -05:00
|
|
|
setInterval,
|
|
|
|
setTimeout,
|
|
|
|
unrefTimer,
|
|
|
|
};
|