Compare commits

...

2 Commits

Author SHA1 Message Date
Claude Bot
c7c14e8e86 test: add plugin URL assertion to require syntax test
Addresses code review feedback to check for plugin documentation URL
consistently across all tests.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 01:09:43 +00:00
Claude Bot
58a3c2c863 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 <noreply@anthropic.com>
2026-01-15 00:58:38 +00:00
2 changed files with 76 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
#include "root.h"
#include "headers-handwritten.h"
#include "NodeModuleModule.h"
#include "BunProcess.h"
#include <JavaScriptCore/JSCInlines.h>
#include <JavaScriptCore/VM.h>
@@ -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());
}

View File

@@ -0,0 +1,68 @@
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");
expect(stderr).toContain("https://bun.sh/docs/bundler/plugins");
// 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);
});