Skip to content

Commit 73eff6f

Browse files
committed
use internal setImmediate/clearImmediate fns for node:timers
1 parent b982f8b commit 73eff6f

File tree

9 files changed

+81
-8
lines changed

9 files changed

+81
-8
lines changed

src/node/internal/internal_timers.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
// USE OR OTHER DEALINGS IN THE SOFTWARE.
2525

2626
import { validateFunction } from 'node-internal:validators';
27+
import { default as timersUtil } from 'node-internal:timers';
2728

2829
let clearTimeoutImpl: (obj: Timeout) => void;
2930

@@ -134,9 +135,9 @@ export function clearTimeout(timer: unknown): void {
134135
}
135136
}
136137

137-
export const setImmediate = globalThis.setImmediate.bind(globalThis);
138+
export const setImmediate = timersUtil.setImmediate.bind(timersUtil);
138139

139-
export const clearImmediate = globalThis.clearImmediate.bind(globalThis);
140+
export const clearImmediate = timersUtil.clearImmediate.bind(timersUtil);
140141

141142
export function setInterval(
142143
callback: (...args: unknown[]) => void,

src/node/internal/internal_timers_promises.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,13 @@ export async function setImmediate<T>(
102102

103103
const { promise, resolve, reject } = Promise.withResolvers<T>();
104104

105-
const timer = globalThis.setImmediate(() => {
105+
const timer = timers.setImmediate(() => {
106106
resolve(value as T);
107107
});
108108

109109
if (signal) {
110110
function onCancel(): void {
111-
globalThis.clearImmediate(timer);
111+
timers.clearImmediate(timer);
112112
signal?.removeEventListener('abort', onCancel);
113113
reject(new AbortError(undefined, { cause: signal?.reason }));
114114
}

src/node/internal/timers.d.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type {
2+
setImmediate as setImmediateImpl,
3+
clearImmediate as clearImmediateImpl,
4+
} from 'node:timers';
5+
6+
export const setImmediate: typeof setImmediateImpl;
7+
export const clearImmediate: typeof clearImmediateImpl;

src/workerd/api/node/BUILD.bazel

+2
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ wd_cc_library(
1010
"crypto-keys.c++",
1111
"diagnostics-channel.c++",
1212
"dns.c++",
13+
"timers.c++",
1314
"zlib-util.c++",
1415
],
1516
hdrs = [
1617
"crypto.h",
1718
"diagnostics-channel.h",
1819
"dns.h",
1920
"node.h",
21+
"timers.h",
2022
"zlib-util.h",
2123
],
2224
implementation_deps = [

src/workerd/api/node/node.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <workerd/api/node/buffer.h>
99
#include <workerd/api/node/dns.h>
1010
#include <workerd/api/node/module.h>
11+
#include <workerd/api/node/timers.h>
1112
#include <workerd/api/node/url.h>
1213
#include <workerd/api/node/util.h>
1314
#include <workerd/io/compatibility-date.h>
@@ -52,7 +53,8 @@ class CompatibilityFlags: public jsg::Object {
5253
V(DiagnosticsChannelModule, "node-internal:diagnostics_channel") \
5354
V(ZlibUtil, "node-internal:zlib") \
5455
V(UrlUtil, "node-internal:url") \
55-
V(DnsUtil, "node-internal:dns")
56+
V(DnsUtil, "node-internal:dns") \
57+
V(TimersUtil, "node-internal:timers")
5658

5759
// Add to the NODEJS_MODULES_EXPERIMENTAL list any currently in-development
5860
// node.js compat C++ modules that should be guarded by the experimental compat
@@ -144,4 +146,4 @@ kj::Own<jsg::modules::ModuleBundle> getExternalNodeJsCompatModuleBundle(auto fea
144146
api::node::CompatibilityFlags, EW_NODE_BUFFER_ISOLATE_TYPES, EW_NODE_CRYPTO_ISOLATE_TYPES, \
145147
EW_NODE_DIAGNOSTICCHANNEL_ISOLATE_TYPES, EW_NODE_ASYNCHOOKS_ISOLATE_TYPES, \
146148
EW_NODE_UTIL_ISOLATE_TYPES, EW_NODE_ZLIB_ISOLATE_TYPES, EW_NODE_URL_ISOLATE_TYPES, \
147-
EW_NODE_MODULE_ISOLATE_TYPES, EW_NODE_DNS_ISOLATE_TYPES\
149+
EW_NODE_MODULE_ISOLATE_TYPES, EW_NODE_DNS_ISOLATE_TYPES, EW_NODE_TIMERS_ISOLATE_TYPES\

src/workerd/api/node/tests/timers-nodejs-test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export const testSetImmediate = {
5353

5454
{
5555
const { promise, resolve } = Promise.withResolvers();
56-
globalThis.setImmediate(
56+
timers.setImmediate(
5757
(...args) => {
5858
deepStrictEqual(args, [1, 2, 3]);
5959
resolve();

src/workerd/api/node/tests/timers-nodejs-test.wd-test

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const unitTests :Workerd.Config = (
88
(name = "worker", esModule = embed "timers-nodejs-test.js")
99
],
1010
compatibilityDate = "2025-01-09",
11-
compatibilityFlags = ["nodejs_compat"],
11+
compatibilityFlags = ["nodejs_compat", "no_nodejs_compat_v2"],
1212
)
1313
),
1414
],

src/workerd/api/node/timers.c++

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include "timers.h"
2+
3+
#include <workerd/api/global-scope.h>
4+
#include <workerd/jsg/jsg.h>
5+
6+
namespace workerd::api::node {
7+
8+
// The setImmediate/clearImmediate methods are only exposed on globalThis if the
9+
// node_compat_v2 flag is set. However, we want them exposed via `node:timers`
10+
// generally when just the original node_compat is enabled. Therefore, we provide
11+
// this alternative route to the implementations on ServiceWorkerGlobalScope.
12+
jsg::Ref<Immediate> TimersUtil::setImmediate(jsg::Lock& js,
13+
jsg::Function<void(jsg::Arguments<jsg::Value>)> function,
14+
jsg::Arguments<jsg::Value> args) {
15+
auto context = js.v8Context();
16+
auto& global =
17+
jsg::extractInternalPointer<ServiceWorkerGlobalScope, true>(context, context->Global());
18+
return global.setImmediate(js, kj::mv(function), kj::mv(args));
19+
}
20+
21+
void TimersUtil::clearImmediate(jsg::Lock& js, kj::Maybe<jsg::Ref<Immediate>> maybeImmediate) {
22+
auto context = js.v8Context();
23+
auto& global =
24+
jsg::extractInternalPointer<ServiceWorkerGlobalScope, true>(context, context->Global());
25+
global.clearImmediate(kj::mv(maybeImmediate));
26+
}
27+
} // namespace workerd::api::node

src/workerd/api/node/timers.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) 2017-2022 Cloudflare, Inc.
2+
// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3+
// https://opensource.org/licenses/Apache-2.0
4+
#pragma once
5+
6+
#include <workerd/jsg/jsg.h>
7+
8+
#include <kj/string.h>
9+
10+
namespace workerd::api {
11+
12+
class Immediate;
13+
14+
namespace node {
15+
class TimersUtil final: public jsg::Object {
16+
public:
17+
TimersUtil() = default;
18+
TimersUtil(jsg::Lock&, const jsg::Url&) {}
19+
20+
jsg::Ref<Immediate> setImmediate(jsg::Lock& js,
21+
jsg::Function<void(jsg::Arguments<jsg::Value>)> function,
22+
jsg::Arguments<jsg::Value> args);
23+
void clearImmediate(jsg::Lock& js, kj::Maybe<jsg::Ref<Immediate>> immediate);
24+
25+
JSG_RESOURCE_TYPE(TimersUtil) {
26+
JSG_METHOD(setImmediate);
27+
JSG_METHOD(clearImmediate);
28+
}
29+
};
30+
31+
#define EW_NODE_TIMERS_ISOLATE_TYPES api::node::TimersUtil
32+
} // namespace node
33+
34+
} // namespace workerd::api

0 commit comments

Comments
 (0)