bun
bun copied to clipboard
Node.js process.on compatibility
Repro:
process.on(
"unhandledRejection",
(err) => {
console.log('error' + err);
});
const foo = new Promise((resolve,reject) => {
setTimeout(() => {
reject('foo');
}, 300);
});
Error:
$ bun run /tmp/process.js
[1.16ms] "node_modules.bun" - 105 modules, 46 packages
1 | process.on("unhandledRejection", (err) => {
console.log("error" + err);
});
^
TypeError: process.on is not a function. (In 'process.on("unhandledRejection", (err) => {
console.log("error" + err);
})', 'process.on' is undefined)
at /private/tmp/process.js:1:0
hello sir, I want to work on this issue. Can you please guide me to where I can find this code inside the project?
Small update
process.on technically works but it does not monitor the events as expected, it just extends from EventEmitter. I am keeping this issue open because that doesn't fully address the intended issue
Thanks! At least nbb doesn't trip over that anymore: https://twitter.com/borkdude/status/1581582447661449216
The remaining issues in nbb to have a REPL are "readline" and "vm" support.
I'm interested in gracefully handling process exit. Right now, I noticed that some SQLite data fails to persist unless the database is gracefully closed. I'd like to do something like this:
process.on('beforeExit', () => db.close());
The SQL behavior probably warrants its own top-level issue, I suppose.
This feature is much needed; any progress on this?
Would really love if this got implemented!
I'm interested in gracefully handling process exit. Right now, I noticed that some SQLite data fails to persist unless the database is gracefully closed. I'd like to do something like this:
process.on('beforeExit', () => db.close());The SQL behavior probably warrants its own top-level issue, I suppose.
This has been fixed in canary (and will land in Bun v0.6.14)
beforeExit, exit have both landed in canary as well and tomorrow signal handlers will too.
unhandledRejection will not land in this canary
Hello,
// @ts-ignore
process.on('beforeExit', () => console.log('beforeExit'));
// @ts-ignore
process.on('exit', () => console.log('exit'));
// without ts-ignore, we get "Property 'on' does not exist on type 'Process'.ts(2339)"
None of them are called in 0.7.0 after pressing CTRL+C, is that expected?
None of them are called in 0.7.0 after pressing CTRL+C, is that expected?
Yes, that is consistent with Node.js:
@baptistecs normally CTRL+C is intercepted by your terminal tty driver and it usually sends an interrupt signal (SIGINT). You could do something like:
process.on('SIGINT', ...);
I often use it for closing a database connection when exiting the sever process like so (as in the better-sqlite3 docs):
process.on('exit', () => db.close());
process.on('SIGHUP', () => process.exit(128 + 1)); // hang up
process.on('SIGINT', () => process.exit(128 + 2)); // ctrl+c
process.on('SIGTERM', () => process.exit(128 + 15)); // kill
Although I'm not sure it works in bun yet. The process.on() handlers should get called, so see if it works for you.
Thank you @maxmilton!
I confirm, this is working:
process.on("SIGINT", () => {
console.log('EXIT');
process.exit(0);
});
Unfortunately, this will not be fixed by bun.js is not suitable for large projects, because without these signals it is impossible to make a normal error handler 😔
Please add unhandledRejection and uncaughtException I'll be waiting. Until then, I will use Bun only as a package manager.
Same issue here. Example:
process.on('uncaughtException', function(err){
console.log("caught2")
})
try {
setTimeout(() => {
throw new Error("error")
}, 1000)
await new Promise((resolve) => setTimeout(resolve, 3000))
console.log("done")
} catch(e) {
console.log("caught")
}
Throws error on Bun, prints caught2 on node.
Multiple event/signal handlers are missing for WinOS.
// t-events-signals.js
// ...works in NodeJS...
// Signal events
[`SIGBREAK`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach((eventType) => {
process.on(eventType, catchSignal.bind(null, eventType));
});
// IPC events
[`disconnect`, `message`].forEach((eventType) => {
process.on(eventType, catchEvent.bind(null, eventType));
});
// Process exceptions and promise rejection events
[`uncaughtException`, `unhandledRejection`, `rejectionHandled`, `warning`].forEach((eventType) => {
process.on(eventType, catchEvent.bind(null, eventType));
});
// Process exit events
[`beforeExit`, `exit`].forEach((eventType) => {
process.on(eventType, catchExit.bind(null, eventType));
});
// Process worker event
[`worker`].forEach((eventType) => {
process.on(eventType, (exitCode) => catchEvent.bind(null, eventType)(exitCode));
});
function catchSignal(eventType) {
// upon a SIGINT, parent/shell may display a '^C'
// * use an initial '\r' to reset line position, allowing overwrite of any initial '^C'
console.log('\r' + 'Caught signal...', { eventType });
}
function catchEvent(eventType) {
console.log('Caught event...', { eventType });
}
function catchExit(eventType, exitCode) {
console.log('Now exiting...', { eventType }, { exitCode });
}
// emit unhandledRejection
const _foo = new Promise((_resolve, reject) => {
setTimeout(() => {
reject('foo');
}, 300);
});
// emit uncaughtException
setTimeout(() => {
throw ('bar');
}, 500);
setTimeout(() => {
console.log('The service is now finished.');
}, 2000);
Note that NodeJS catches all SIGBREAKS and SIGINTS and the uncaught/unhandled errors, ending with an exit code of 0.
> node "t-events-signals.js"
Caught event... { eventType: 'unhandledRejection' }
Caught event... { eventType: 'uncaughtException' }
Caught signal... { eventType: 'SIGINT' }
Caught signal... { eventType: 'SIGINT' }
Caught signal... { eventType: 'SIGBREAK' }
Caught signal... { eventType: 'SIGBREAK' }
Caught signal... { eventType: 'SIGBREAK' }
Caught signal... { eventType: 'SIGBREAK' }
Caught signal... { eventType: 'SIGINT' }
The service is now finished.
Now exiting... { eventType: 'beforeExit' } { exitCode: 0 }
Now exiting... { eventType: 'exit' } { exitCode: 0 }
bun exits with errors and only catches the beforeExit and exit events and ends with a 1 error exit code.
> bun run "t-events-signals.js"
error: foo
Now exiting... {
eventType: "beforeExit",
} {
exitCode: 0,
}
Now exiting... {
eventType: "exit",
} {
exitCode: 1,
}
``
bun --watch just logs all throws, I wonder if it is possible to implement a similar interception of throws by a listener. Such a badly needed feature.
+1, I need this feature for my discord bot shard to not restart on every uncaught thrown exception
+1 for the reason above
+1 because alongside with this issue https://github.com/oven-sh/bun/issues/9629 these features are very needed.
+1 for I'm going to write a game server based on bun. I need to log uncaught exceptions
+1
we'll add this a little after bun v1.1
This will be shipped in Bun v1.1.8, which releases in a couple hours from this comment.
To get it now:
bun upgrade --canary
Thanks for the improvements! Most of the signals are now being caught. For WinOS, 'SIGBREAK' is still being missed and causing process exceptions/panics.