From 58a3c2c863e9d860fe9f69e442d755c016819d44 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Thu, 15 Jan 2026 00:58:38 +0000 Subject: [PATCH] fix(node): emit warning for unimplemented module.register() module.register() is used by OpenTelemetry and other tooling to register ESM loader hooks. Since this feature is not yet implemented in Bun, this change emits a process warning to inform users that their loaders will not be invoked, along with a pointer to Bun's plugin API as an alternative. Fixes #3775 Co-Authored-By: Claude Opus 4.5 --- src/bun.js/modules/NodeModuleModule.cpp | 8 +++ test/regression/issue/3775.test.ts | 67 +++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 test/regression/issue/3775.test.ts diff --git a/src/bun.js/modules/NodeModuleModule.cpp b/src/bun.js/modules/NodeModuleModule.cpp index ac72ec7970..cd161fc890 100644 --- a/src/bun.js/modules/NodeModuleModule.cpp +++ b/src/bun.js/modules/NodeModuleModule.cpp @@ -1,6 +1,7 @@ #include "root.h" #include "headers-handwritten.h" #include "NodeModuleModule.h" +#include "BunProcess.h" #include #include @@ -870,6 +871,13 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionSyncBuiltinESMExports, JSC_DEFINE_HOST_FUNCTION(jsFunctionRegister, (JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) { + auto& vm = globalObject->vm(); + Bun::Process::emitWarning( + globalObject, + jsString(vm, String("module.register() is not implemented in Bun. Loaders registered with module.register() will not be invoked. To intercept and transform modules, consider using Bun's plugin API: https://bun.sh/docs/bundler/plugins"_s)), + jsString(vm, String("Warning"_s)), + jsString(vm, String("BUN_UNSUPPORTED_REGISTER"_s)), + jsUndefined()); return JSC::JSValue::encode(JSC::jsUndefined()); } diff --git a/test/regression/issue/3775.test.ts b/test/regression/issue/3775.test.ts new file mode 100644 index 0000000000..baeb6ef697 --- /dev/null +++ b/test/regression/issue/3775.test.ts @@ -0,0 +1,67 @@ +import { expect, test } from "bun:test"; +import { bunEnv, bunExe } from "harness"; + +// https://github.com/oven-sh/bun/issues/3775 +// module.register() should emit a warning since it's not implemented +test("module.register() emits a warning", async () => { + await using proc = Bun.spawn({ + cmd: [bunExe(), "-e", `import { register } from 'node:module'; register('./test.mjs', import.meta.url);`], + env: bunEnv, + stderr: "pipe", + stdout: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + // Check that the warning is emitted + expect(stderr).toContain("module.register() is not implemented in Bun"); + expect(stderr).toContain("BUN_UNSUPPORTED_REGISTER"); + expect(stderr).toContain("https://bun.sh/docs/bundler/plugins"); + + // Exit code should be 0 (warning, not error) + expect(exitCode).toBe(0); +}); + +test("module.register() with require syntax emits a warning", async () => { + await using proc = Bun.spawn({ + cmd: [bunExe(), "-e", `const { register } = require('node:module'); register('./test.mjs');`], + env: bunEnv, + stderr: "pipe", + stdout: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + // Check that the warning is emitted + expect(stderr).toContain("module.register() is not implemented in Bun"); + expect(stderr).toContain("BUN_UNSUPPORTED_REGISTER"); + + // Exit code should be 0 (warning, not error) + expect(exitCode).toBe(0); +}); + +test("module.register() emits warning only once per call", async () => { + await using proc = Bun.spawn({ + cmd: [ + bunExe(), + "-e", + ` + import { register } from 'node:module'; + register('./test1.mjs', import.meta.url); + register('./test2.mjs', import.meta.url); + `, + ], + env: bunEnv, + stderr: "pipe", + stdout: "pipe", + }); + + const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]); + + // The warning should be emitted twice (once per call) + const warningMatches = stderr.match(/module\.register\(\) is not implemented in Bun/g); + expect(warningMatches?.length).toBe(2); + + // Exit code should be 0 + expect(exitCode).toBe(0); +});