(function () {
const { core, primordials } = __bootstrap;
const { op_defer } = core.ops;
const {
createTimer,
cancelTimer,
refTimer: coreRefTimer,
unrefTimer: coreUnrefTimer,
getAsyncContext,
setAsyncContext,
} = core;
const {
MapPrototypeDelete,
MapPrototypeGet,
MapPrototypeSet,
PromisePrototypeThen,
ReflectApply,
SafeMap,
TypeError,
indirectEval,
} = primordials;
const webidl = core.loadExtScript("ext:deno_webidl/00_webidl.js");
const activeTimers = new SafeMap();
let timerDepth = 0;
function checkThis(thisArg) {
if (thisArg !== null && thisArg !== undefined && thisArg !== globalThis) {
throw new TypeError("Illegal invocation");
}
}
function setTimeout(callback, timeout = 0, ...args) {
checkThis(this);
if (typeof callback !== "function") {
const unboundCallback = webidl.converters.DOMString(callback);
callback = () => indirectEval(unboundCallback);
}
const unboundCallback = callback;
const asyncContext = getAsyncContext();
const depth = timerDepth;
let id = 0;
const wrappedCallback = function () {
const oldContext = getAsyncContext();
const prevDepth = timerDepth;
try {
setAsyncContext(asyncContext);
timerDepth = depth + 1;
ReflectApply(unboundCallback, globalThis, args);
} finally {
timerDepth = prevDepth;
setAsyncContext(oldContext);
MapPrototypeDelete(activeTimers, id);
}
};
timeout = webidl.converters.long(timeout);
const timer = createTimer(wrappedCallback, timeout, undefined, false, true);
id = timer._timerId;
MapPrototypeSet(activeTimers, id, timer);
return id;
}
function setInterval(callback, timeout = 0, ...args) {
checkThis(this);
if (typeof callback !== "function") {
const unboundCallback = webidl.converters.DOMString(callback);
callback = () => indirectEval(unboundCallback);
}
const unboundCallback = callback;
const asyncContext = getAsyncContext();
const depth = timerDepth;
const wrappedCallback = function () {
const oldContext = getAsyncContext();
const prevDepth = timerDepth;
try {
setAsyncContext(asyncContext);
timerDepth = depth + 1;
ReflectApply(unboundCallback, globalThis, args);
} finally {
timerDepth = prevDepth;
setAsyncContext(oldContext);
}
};
timeout = webidl.converters.long(timeout);
const timer = createTimer(wrappedCallback, timeout, undefined, true, true);
const id = timer._timerId;
MapPrototypeSet(activeTimers, id, timer);
return id;
}
function clearTimeout(id = 0) {
checkThis(this);
id = webidl.converters.long(id);
const timer = MapPrototypeGet(activeTimers, id);
if (timer) {
cancelTimer(timer);
MapPrototypeDelete(activeTimers, id);
}
}
function clearInterval(id = 0) {
checkThis(this);
id = webidl.converters.long(id);
const timer = MapPrototypeGet(activeTimers, id);
if (timer) {
cancelTimer(timer);
MapPrototypeDelete(activeTimers, id);
}
}
function unrefTimer(id) {
if (typeof id !== "number") {
id?.unref?.();
return;
}
const timer = MapPrototypeGet(activeTimers, id);
if (timer) {
coreUnrefTimer(timer);
}
}
function refTimer(id) {
if (typeof id !== "number") {
id?.ref?.();
return;
}
const timer = MapPrototypeGet(activeTimers, id);
if (timer) {
coreRefTimer(timer);
}
}
function defer(go) {
PromisePrototypeThen(op_defer(), () => go());
}
return {
clearInterval,
clearTimeout,
defer,
refTimer,
setInterval,
setTimeout,
unrefTimer,
};
})();