bun_runtime 0.5.4

Bao runtime integration — JS engine + Bun API + event loop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
// @trace REQ-ENG-006 [api:node:constants]
//
// Node.js `constants` module — system constants (O_* flags, S_* permissions,
// signals, errno, priority). Values are sourced from libc on Linux.
//
// # Windows arm (upstream parity: bun runtime/node/os/constants.zig)
//
// Upstream's recipe is "define what the platform defines, omit what it
// doesn't" (its `?constant | null → skip` lookup). Mirrored here:
// - signals: the windows set is libuv `uv/win.h` + the CRT (SIGHUP 1,
//   SIGINT 2, SIGQUIT 3, SIGILL 4, SIGFPE 8, SIGKILL 9, SIGSEGV 11, SIGTERM
//   15, SIGBREAK 21, SIGABRT 22, SIGWINCH 28) — the unix-only signals are
//   simply absent, like upstream's omitted properties
// - O_* flags with no windows semantics read 0, per libuv's UV_FS_O_* table
//   (uv/win.h: O_NOCTTY/O_DIRECTORY/O_NOFOLLOW/O_NONBLOCK/O_SYMLINK = 0;
//   O_DIRECT = 0x02000000 FILE_FLAG_NO_BUFFERING; O_DSYNC = 0x04000000 and
//   O_SYNC = 0x08000000 FILE_FLAG_WRITE_THROUGH)
// - S_* permission bits: POSIX mode-bit values on both platforms (JS-level
//   convention; node's windows face and the node-fallbacks constants table
//   keep 448/256/64/... there too)
// - errno: windows CRT values from libc's windows module; ESTALE has no
//   windows errno and is omitted

use ::std::ptr::NonNull;
use bun_core::ZBox;

use mozjs::jsapi::*;
use mozjs::jsval::{Int32Value, JSVal, ObjectValue, UndefinedValue};
use mozjs::rooted;
use mozjs::rust::wrappers2 as w2;

use crate::require::cache_builtin;

/// Windows `S_*`/`O_*` constants (see the windows-arm note above for the
/// evidence sources). POSIX builds take these from libc instead.
#[cfg(windows)]
mod win {
    pub const S_IRWXU: u32 = 448;
    pub const S_IRUSR: u32 = 256;
    pub const S_IWUSR: u32 = 128;
    pub const S_IXUSR: u32 = 64;
    pub const S_IRWXG: u32 = 56;
    pub const S_IRGRP: u32 = 32;
    pub const S_IWGRP: u32 = 16;
    pub const S_IXGRP: u32 = 8;
    pub const S_IRWXO: u32 = 7;
    pub const S_IROTH: u32 = 4;
    pub const S_IWOTH: u32 = 2;
    pub const S_IXOTH: u32 = 1;
    pub const O_NOCTTY: i32 = 0; // uv/win.h UV_FS_O_NOCTTY
    pub const O_DIRECTORY: i32 = 0; // uv/win.h UV_FS_O_DIRECTORY
    pub const O_NOFOLLOW: i32 = 0; // uv/win.h UV_FS_O_NOFOLLOW
    pub const O_NONBLOCK: i32 = 0; // uv/win.h UV_FS_O_NONBLOCK
    pub const O_DIRECT: i32 = 0x0200_0000; // FILE_FLAG_NO_BUFFERING
    pub const O_DSYNC: i32 = 0x0400_0000; // FILE_FLAG_WRITE_THROUGH
    pub const O_SYNC: i32 = 0x0800_0000; // FILE_FLAG_WRITE_THROUGH
}

/// Windows signal numbers (libuv `uv/win.h` + CRT signal.h — the signal set
/// node exposes on windows).
#[cfg(windows)]
mod win_signals {
    pub const SIGHUP: i32 = 1;
    pub const SIGINT: i32 = 2;
    pub const SIGQUIT: i32 = 3;
    pub const SIGILL: i32 = 4;
    pub const SIGFPE: i32 = 8;
    pub const SIGKILL: i32 = 9;
    pub const SIGSEGV: i32 = 11;
    pub const SIGTERM: i32 = 15;
    pub const SIGBREAK: i32 = 21;
    pub const SIGABRT: i32 = 22;
    pub const SIGWINCH: i32 = 28;
}

pub fn install(cx: &mut mozjs::context::JSContext) {
    rooted!(&in(cx) let constants_obj = unsafe { w2::JS_NewPlainObject(cx) });
    if constants_obj.get().is_null() {
        return;
    }

    unsafe {
        // fs sub-object: O_* flags + S_* permissions
        rooted!(&in(cx) let fs_obj = w2::JS_NewPlainObject(cx));
        if !fs_obj.get().is_null() {
            // O_* flags (Linux values from libc)
            define_int_prop(cx, fs_obj.get(), "O_RDONLY", libc::O_RDONLY as i32);
            define_int_prop(cx, fs_obj.get(), "O_WRONLY", libc::O_WRONLY as i32);
            define_int_prop(cx, fs_obj.get(), "O_RDWR", libc::O_RDWR as i32);
            define_int_prop(cx, fs_obj.get(), "O_CREAT", libc::O_CREAT as i32);
            define_int_prop(cx, fs_obj.get(), "O_EXCL", libc::O_EXCL as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "O_NOCTTY", libc::O_NOCTTY as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "O_NOCTTY", win::O_NOCTTY);
            define_int_prop(cx, fs_obj.get(), "O_TRUNC", libc::O_TRUNC as i32);
            define_int_prop(cx, fs_obj.get(), "O_APPEND", libc::O_APPEND as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "O_DIRECTORY", libc::O_DIRECTORY as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "O_DIRECTORY", win::O_DIRECTORY);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "O_NOFOLLOW", libc::O_NOFOLLOW as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "O_NOFOLLOW", win::O_NOFOLLOW);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "O_SYNC", libc::O_SYNC as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "O_SYNC", win::O_SYNC);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "O_DSYNC", libc::O_DSYNC as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "O_DSYNC", win::O_DSYNC);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "O_SYMLINK", libc::O_NOFOLLOW as i32); // No O_SYMLINK on Linux; use O_NOFOLLOW
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "O_SYMLINK", win::O_NOFOLLOW); // windows: no O_SYMLINK (uv UV_FS_O_SYMLINK = 0)
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "O_DIRECT", libc::O_DIRECT as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "O_DIRECT", win::O_DIRECT);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "O_NONBLOCK", libc::O_NONBLOCK as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "O_NONBLOCK", win::O_NONBLOCK);

            // S_* permissions
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IRWXU", libc::S_IRWXU as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IRWXU", win::S_IRWXU as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IRUSR", libc::S_IRUSR as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IRUSR", win::S_IRUSR as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IWUSR", libc::S_IWUSR as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IWUSR", win::S_IWUSR as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IXUSR", libc::S_IXUSR as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IXUSR", win::S_IXUSR as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IRWXG", libc::S_IRWXG as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IRWXG", win::S_IRWXG as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IRGRP", libc::S_IRGRP as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IRGRP", win::S_IRGRP as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IWGRP", libc::S_IWGRP as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IWGRP", win::S_IWGRP as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IXGRP", libc::S_IXGRP as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IXGRP", win::S_IXGRP as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IRWXO", libc::S_IRWXO as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IRWXO", win::S_IRWXO as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IROTH", libc::S_IROTH as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IROTH", win::S_IROTH as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IWOTH", libc::S_IWOTH as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IWOTH", win::S_IWOTH as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, fs_obj.get(), "S_IXOTH", libc::S_IXOTH as i32);
            #[cfg(windows)]
            define_int_prop(cx, fs_obj.get(), "S_IXOTH", win::S_IXOTH as i32);

            // Copy flags
            define_int_prop(cx, fs_obj.get(), "COPYFILE_EXCL", 1);
            define_int_prop(cx, fs_obj.get(), "COPYFILE_FICLONE", 2);
            define_int_prop(cx, fs_obj.get(), "COPYFILE_FICLONE_FORCE", 4);

            rooted!(&in(cx) let fs_val = ObjectValue(fs_obj.get()));
            JS_DefineProperty(
                cx.raw_cx(),
                constants_obj.handle().into(),
                c"fs".as_ptr(),
                fs_val.handle().into(),
                JSPROP_ENUMERATE as u32,
            );
        }

        // os sub-object: signals, errno, priority
        rooted!(&in(cx) let os_obj = w2::JS_NewPlainObject(cx));
        if !os_obj.get().is_null() {
            // errno constants
            define_int_prop(cx, os_obj.get(), "E2BIG", libc::E2BIG as i32);
            define_int_prop(cx, os_obj.get(), "EACCES", libc::EACCES as i32);
            define_int_prop(cx, os_obj.get(), "EADDRINUSE", libc::EADDRINUSE as i32);
            define_int_prop(
                cx,
                os_obj.get(),
                "EADDRNOTAVAIL",
                libc::EADDRNOTAVAIL as i32,
            );
            define_int_prop(cx, os_obj.get(), "EAFNOSUPPORT", libc::EAFNOSUPPORT as i32);
            define_int_prop(cx, os_obj.get(), "EAGAIN", libc::EAGAIN as i32);
            define_int_prop(cx, os_obj.get(), "EALREADY", libc::EALREADY as i32);
            define_int_prop(cx, os_obj.get(), "EBADF", libc::EBADF as i32);
            define_int_prop(cx, os_obj.get(), "EBADMSG", libc::EBADMSG as i32);
            define_int_prop(cx, os_obj.get(), "EBUSY", libc::EBUSY as i32);
            define_int_prop(cx, os_obj.get(), "ECANCELED", libc::ECANCELED as i32);
            define_int_prop(cx, os_obj.get(), "ECHILD", libc::ECHILD as i32);
            define_int_prop(cx, os_obj.get(), "ECONNABORTED", libc::ECONNABORTED as i32);
            define_int_prop(cx, os_obj.get(), "ECONNREFUSED", libc::ECONNREFUSED as i32);
            define_int_prop(cx, os_obj.get(), "ECONNRESET", libc::ECONNRESET as i32);
            define_int_prop(cx, os_obj.get(), "EDEADLK", libc::EDEADLK as i32);
            define_int_prop(cx, os_obj.get(), "EDESTADDRREQ", libc::EDESTADDRREQ as i32);
            define_int_prop(cx, os_obj.get(), "EDOM", libc::EDOM as i32);
            define_int_prop(cx, os_obj.get(), "EEXIST", libc::EEXIST as i32);
            define_int_prop(cx, os_obj.get(), "EFAULT", libc::EFAULT as i32);
            define_int_prop(cx, os_obj.get(), "EFBIG", libc::EFBIG as i32);
            define_int_prop(cx, os_obj.get(), "EHOSTUNREACH", libc::EHOSTUNREACH as i32);
            define_int_prop(cx, os_obj.get(), "EIDRM", libc::EIDRM as i32);
            define_int_prop(cx, os_obj.get(), "EILSEQ", libc::EILSEQ as i32);
            define_int_prop(cx, os_obj.get(), "EINPROGRESS", libc::EINPROGRESS as i32);
            define_int_prop(cx, os_obj.get(), "EINTR", libc::EINTR as i32);
            define_int_prop(cx, os_obj.get(), "EINVAL", libc::EINVAL as i32);
            define_int_prop(cx, os_obj.get(), "EIO", libc::EIO as i32);
            define_int_prop(cx, os_obj.get(), "EISCONN", libc::EISCONN as i32);
            define_int_prop(cx, os_obj.get(), "EISDIR", libc::EISDIR as i32);
            define_int_prop(cx, os_obj.get(), "ELOOP", libc::ELOOP as i32);
            define_int_prop(cx, os_obj.get(), "EMFILE", libc::EMFILE as i32);
            define_int_prop(cx, os_obj.get(), "EMLINK", libc::EMLINK as i32);
            define_int_prop(cx, os_obj.get(), "EMSGSIZE", libc::EMSGSIZE as i32);
            define_int_prop(cx, os_obj.get(), "ENAMETOOLONG", libc::ENAMETOOLONG as i32);
            define_int_prop(cx, os_obj.get(), "ENETDOWN", libc::ENETDOWN as i32);
            define_int_prop(cx, os_obj.get(), "ENETRESET", libc::ENETRESET as i32);
            define_int_prop(cx, os_obj.get(), "ENETUNREACH", libc::ENETUNREACH as i32);
            define_int_prop(cx, os_obj.get(), "ENFILE", libc::ENFILE as i32);
            define_int_prop(cx, os_obj.get(), "ENOBUFS", libc::ENOBUFS as i32);
            define_int_prop(cx, os_obj.get(), "ENODATA", libc::ENODATA as i32);
            define_int_prop(cx, os_obj.get(), "ENODEV", libc::ENODEV as i32);
            define_int_prop(cx, os_obj.get(), "ENOENT", libc::ENOENT as i32);
            define_int_prop(cx, os_obj.get(), "ENOEXEC", libc::ENOEXEC as i32);
            define_int_prop(cx, os_obj.get(), "ENOLCK", libc::ENOLCK as i32);
            define_int_prop(cx, os_obj.get(), "ENOLINK", libc::ENOLINK as i32);
            define_int_prop(cx, os_obj.get(), "ENOMEM", libc::ENOMEM as i32);
            define_int_prop(cx, os_obj.get(), "ENOMSG", libc::ENOMSG as i32);
            define_int_prop(cx, os_obj.get(), "ENOPROTOOPT", libc::ENOPROTOOPT as i32);
            define_int_prop(cx, os_obj.get(), "ENOSPC", libc::ENOSPC as i32);
            define_int_prop(cx, os_obj.get(), "ENOSR", libc::ENOSR as i32);
            define_int_prop(cx, os_obj.get(), "ENOSTR", libc::ENOSTR as i32);
            define_int_prop(cx, os_obj.get(), "ENOSYS", libc::ENOSYS as i32);
            define_int_prop(cx, os_obj.get(), "ENOTCONN", libc::ENOTCONN as i32);
            define_int_prop(cx, os_obj.get(), "ENOTDIR", libc::ENOTDIR as i32);
            define_int_prop(cx, os_obj.get(), "ENOTEMPTY", libc::ENOTEMPTY as i32);
            define_int_prop(cx, os_obj.get(), "ENOTSOCK", libc::ENOTSOCK as i32);
            define_int_prop(cx, os_obj.get(), "ENOTSUP", libc::ENOTSUP as i32);
            define_int_prop(cx, os_obj.get(), "ENOTTY", libc::ENOTTY as i32);
            define_int_prop(cx, os_obj.get(), "ENXIO", libc::ENXIO as i32);
            define_int_prop(cx, os_obj.get(), "EOPNOTSUPP", libc::EOPNOTSUPP as i32);
            define_int_prop(cx, os_obj.get(), "EOVERFLOW", libc::EOVERFLOW as i32);
            define_int_prop(cx, os_obj.get(), "EPERM", libc::EPERM as i32);
            define_int_prop(cx, os_obj.get(), "EPIPE", libc::EPIPE as i32);
            define_int_prop(cx, os_obj.get(), "EPROTO", libc::EPROTO as i32);
            define_int_prop(
                cx,
                os_obj.get(),
                "EPROTONOSUPPORT",
                libc::EPROTONOSUPPORT as i32,
            );
            define_int_prop(cx, os_obj.get(), "EPROTOTYPE", libc::EPROTOTYPE as i32);
            define_int_prop(cx, os_obj.get(), "ERANGE", libc::ERANGE as i32);
            define_int_prop(cx, os_obj.get(), "EROFS", libc::EROFS as i32);
            define_int_prop(cx, os_obj.get(), "ESPIPE", libc::ESPIPE as i32);
            define_int_prop(cx, os_obj.get(), "ESRCH", libc::ESRCH as i32);
            #[cfg(not(windows))]
            define_int_prop(cx, os_obj.get(), "ESTALE", libc::ESTALE as i32); // no windows errno; omitted like upstream
            define_int_prop(cx, os_obj.get(), "ETIME", libc::ETIME as i32);
            define_int_prop(cx, os_obj.get(), "ETIMEDOUT", libc::ETIMEDOUT as i32);
            define_int_prop(cx, os_obj.get(), "ETXTBSY", libc::ETXTBSY as i32);
            define_int_prop(cx, os_obj.get(), "EWOULDBLOCK", libc::EWOULDBLOCK as i32);
            define_int_prop(cx, os_obj.get(), "EXDEV", libc::EXDEV as i32);

            // Priority constants (from sys/resource.h)
            define_int_prop(cx, os_obj.get(), "PRIORITY_LOW", 19);
            define_int_prop(cx, os_obj.get(), "PRIORITY_BELOW_NORMAL", 10);
            define_int_prop(cx, os_obj.get(), "PRIORITY_NORMAL", 0);
            define_int_prop(cx, os_obj.get(), "PRIORITY_ABOVE_NORMAL", -7);
            define_int_prop(cx, os_obj.get(), "PRIORITY_HIGH", -14);
            define_int_prop(cx, os_obj.get(), "PRIORITY_HIGHEST", -20);

            // signals sub-object
            rooted!(&in(cx) let signals_obj = w2::JS_NewPlainObject(cx));
            if !signals_obj.get().is_null() {
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGHUP", libc::SIGHUP as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGINT", libc::SIGINT as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGQUIT", libc::SIGQUIT as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGILL", libc::SIGILL as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGTRAP", libc::SIGTRAP as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGABRT", libc::SIGABRT as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGIOT", libc::SIGIOT as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGBUS", libc::SIGBUS as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGFPE", libc::SIGFPE as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGKILL", libc::SIGKILL as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGUSR1", libc::SIGUSR1 as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGSEGV", libc::SIGSEGV as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGUSR2", libc::SIGUSR2 as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGPIPE", libc::SIGPIPE as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGALRM", libc::SIGALRM as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGTERM", libc::SIGTERM as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGCHLD", libc::SIGCHLD as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGCONT", libc::SIGCONT as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGSTOP", libc::SIGSTOP as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGTSTP", libc::SIGTSTP as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGTTIN", libc::SIGTTIN as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGTTOU", libc::SIGTTOU as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGURG", libc::SIGURG as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGXCPU", libc::SIGXCPU as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGXFSZ", libc::SIGXFSZ as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGVTALRM", libc::SIGVTALRM as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGPROF", libc::SIGPROF as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGWINCH", libc::SIGWINCH as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGIO", libc::SIGIO as i32);
                #[cfg(not(windows))]
                define_int_prop(cx, signals_obj.get(), "SIGSYS", libc::SIGSYS as i32);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGHUP", win_signals::SIGHUP);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGINT", win_signals::SIGINT);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGQUIT", win_signals::SIGQUIT);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGILL", win_signals::SIGILL);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGFPE", win_signals::SIGFPE);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGKILL", win_signals::SIGKILL);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGSEGV", win_signals::SIGSEGV);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGTERM", win_signals::SIGTERM);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGBREAK", win_signals::SIGBREAK);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGABRT", win_signals::SIGABRT);
                #[cfg(windows)]
                define_int_prop(cx, signals_obj.get(), "SIGWINCH", win_signals::SIGWINCH);

                rooted!(&in(cx) let sig_val = ObjectValue(signals_obj.get()));
                JS_DefineProperty(
                    cx.raw_cx(),
                    os_obj.handle().into(),
                    c"signals".as_ptr(),
                    sig_val.handle().into(),
                    JSPROP_ENUMERATE as u32,
                );
            }

            rooted!(&in(cx) let os_val = ObjectValue(os_obj.get()));
            JS_DefineProperty(
                cx.raw_cx(),
                constants_obj.handle().into(),
                c"os".as_ptr(),
                os_val.handle().into(),
                JSPROP_ENUMERATE as u32,
            );
        }

        // crypto sub-object (common constants)
        rooted!(&in(cx) let crypto_obj = w2::JS_NewPlainObject(cx));
        if !crypto_obj.get().is_null() {
            define_int_prop(cx, crypto_obj.get(), "OPENSSL_VERSION_NUMBER", 0);
            define_int_prop(cx, crypto_obj.get(), "SSL_OP_ALL", 0);

            rooted!(&in(cx) let crypto_val = ObjectValue(crypto_obj.get()));
            JS_DefineProperty(
                cx.raw_cx(),
                constants_obj.handle().into(),
                c"crypto".as_ptr(),
                crypto_val.handle().into(),
                JSPROP_ENUMERATE as u32,
            );
        }

        // zlib sub-object
        rooted!(&in(cx) let zlib_obj = w2::JS_NewPlainObject(cx));
        if !zlib_obj.get().is_null() {
            define_int_prop(cx, zlib_obj.get(), "Z_NO_FLUSH", 0);
            define_int_prop(cx, zlib_obj.get(), "Z_PARTIAL_FLUSH", 1);
            define_int_prop(cx, zlib_obj.get(), "Z_SYNC_FLUSH", 2);
            define_int_prop(cx, zlib_obj.get(), "Z_FULL_FLUSH", 3);
            define_int_prop(cx, zlib_obj.get(), "Z_FINISH", 4);
            define_int_prop(cx, zlib_obj.get(), "Z_BLOCK", 5);
            define_int_prop(cx, zlib_obj.get(), "Z_OK", 0);
            define_int_prop(cx, zlib_obj.get(), "Z_STREAM_END", 1);
            define_int_prop(cx, zlib_obj.get(), "Z_NEED_DICT", 2);
            define_int_prop(cx, zlib_obj.get(), "Z_ERRNO", -1);
            define_int_prop(cx, zlib_obj.get(), "Z_STREAM_ERROR", -2);
            define_int_prop(cx, zlib_obj.get(), "Z_DATA_ERROR", -3);
            define_int_prop(cx, zlib_obj.get(), "Z_MEM_ERROR", -4);
            define_int_prop(cx, zlib_obj.get(), "Z_BUF_ERROR", -5);
            define_int_prop(cx, zlib_obj.get(), "Z_VERSION_ERROR", -6);
            define_int_prop(cx, zlib_obj.get(), "Z_NO_COMPRESSION", 0);
            define_int_prop(cx, zlib_obj.get(), "Z_BEST_SPEED", 1);
            define_int_prop(cx, zlib_obj.get(), "Z_BEST_COMPRESSION", 9);
            define_int_prop(cx, zlib_obj.get(), "Z_DEFAULT_COMPRESSION", -1);
            define_int_prop(cx, zlib_obj.get(), "Z_DEFAULT_STRATEGY", 0);
            define_int_prop(cx, zlib_obj.get(), "Z_FILTERED", 1);
            define_int_prop(cx, zlib_obj.get(), "Z_HUFFMAN_ONLY", 2);
            define_int_prop(cx, zlib_obj.get(), "Z_RLE", 3);
            define_int_prop(cx, zlib_obj.get(), "Z_FIXED", 4);

            rooted!(&in(cx) let zlib_val = ObjectValue(zlib_obj.get()));
            JS_DefineProperty(
                cx.raw_cx(),
                constants_obj.handle().into(),
                c"zlib".as_ptr(),
                zlib_val.handle().into(),
                JSPROP_ENUMERATE as u32,
            );
        }
    }

    cache_builtin(cx, "constants", constants_obj.get());
}

/// Define an integer property on a JS object (enumerable).
#[allow(unsafe_op_in_unsafe_fn)]
unsafe fn define_int_prop(
    cx: &mut mozjs::context::JSContext,
    obj_ptr: *mut JSObject,
    name: &str,
    val: i32,
) {
    let c_name = ZBox::from_bytes(name.as_bytes());
    let raw_cx = cx.raw_cx();
    rooted!(&in(cx) let obj = obj_ptr);
    rooted!(&in(cx) let v = Int32Value(val));
    JS_DefineProperty(
        raw_cx,
        obj.handle().into(),
        c_name.as_ptr(),
        v.handle().into(),
        JSPROP_ENUMERATE as u32,
    );
}