aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-04-01 21:13:27 -0700
committerGravatar GitHub <noreply@github.com> 2023-04-01 21:13:27 -0700
commitfcd8b828644cc3cf2bd46bbfc0f6b90789d5dba2 (patch)
tree075ad9fc3375a56b71da4ce6625419e5dd10cdba
parent63d138b0466765e012aaa216ab684b2d39888e64 (diff)
downloadbun-fcd8b828644cc3cf2bd46bbfc0f6b90789d5dba2.tar.gz
bun-fcd8b828644cc3cf2bd46bbfc0f6b90789d5dba2.tar.zst
bun-fcd8b828644cc3cf2bd46bbfc0f6b90789d5dba2.zip
Add stubs for missing node builtins (#2534)
* Stub `node:v8` * Stub `node:trace_events` * Stub `node:repl` * Stub `node:inspector` * Stub `node:http2` * Stub `node:diagnostics_channel` * Stub `node:dgram` * Stub `node:cluster` * Link stubs * cleanup * Clean up the test * Implement `node:vm` stub * Cleanup `v8` module stub * Add missing `promises` export to node:stream * Implement `node:stream/promise` * Implement `node:assert/strict` * cleanup * better errors * Increaase timeout * Update inspector.exports.js * Make the version consistent * Implement `process.binding("constants")` * Update runner.node.mjs --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
-rw-r--r--packages/bun-internal-test/src/runner.node.mjs2
-rw-r--r--src/bun.js/assert.exports.js43
-rw-r--r--src/bun.js/assert_strict.exports.js48
-rw-r--r--src/bun.js/bindings/Process.cpp18
-rw-r--r--src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp34
-rw-r--r--src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.h9
-rw-r--r--src/bun.js/builtins/js/ProcessObjectInternals.js31
-rw-r--r--src/bun.js/cluster.exports.js57
-rw-r--r--src/bun.js/dgram.exports.js46
-rw-r--r--src/bun.js/diagnostics_channel.exports.js57
-rw-r--r--src/bun.js/http2.exports.js342
-rw-r--r--src/bun.js/inspector.exports.js68
-rw-r--r--src/bun.js/module_loader.zig105
-rw-r--r--src/bun.js/node_streams_promises.exports.js9
-rw-r--r--src/bun.js/repl.exports.js86
-rw-r--r--src/bun.js/streams.exports.js1
-rw-r--r--src/bun.js/trace_events.exports.js33
-rw-r--r--src/bun.js/v8.exports.js166
-rw-r--r--src/bun.js/vm.exports.js94
-rw-r--r--test/js/node/stubs.test.js120
20 files changed, 1327 insertions, 42 deletions
diff --git a/packages/bun-internal-test/src/runner.node.mjs b/packages/bun-internal-test/src/runner.node.mjs
index 508e2e339..c00624d12 100644
--- a/packages/bun-internal-test/src/runner.node.mjs
+++ b/packages/bun-internal-test/src/runner.node.mjs
@@ -58,7 +58,7 @@ async function runTest(path) {
error: timedOut,
} = spawnSync("bun", ["test", path], {
stdio: ["ignore", "pipe", "pipe"],
- timeout: 10_000,
+ timeout: 500_000,
env: {
...process.env,
FORCE_COLOR: "1",
diff --git a/src/bun.js/assert.exports.js b/src/bun.js/assert.exports.js
index 82527610a..8fb283c9f 100644
--- a/src/bun.js/assert.exports.js
+++ b/src/bun.js/assert.exports.js
@@ -1284,23 +1284,30 @@ var require_assert = __commonJS({
});
var assert_module = require_assert();
+function CallTracker() {
+ throw new Error("CallTracker is not supported yet");
+}
+
assert_module[Symbol.for("CommonJS")] = 0;
+assert_module["CallTracker"] = CallTracker;
+export var {
+ AssertionError,
+ assert,
+ deepEqual,
+ deepStrictEqual,
+ doesNotReject,
+ doesNotThrow,
+ equal,
+ fail,
+ ifError,
+ notDeepEqual,
+ notDeepStrictEqual,
+ notEqual,
+ notStrictEqual,
+ ok,
+ rejects,
+ strict,
+ strictEqual,
+ throws,
+} = assert_module;
export default assert_module;
-export var AssertionError = assert_module.AssertionError;
-export var assert = assert_module.assert;
-export var deepEqual = assert_module.deepEqual;
-export var deepStrictEqual = assert_module.deepStrictEqual;
-export var doesNotReject = assert_module.doesNotReject;
-export var doesNotThrow = assert_module.doesNotThrow;
-export var equal = assert_module.equal;
-export var fail = assert_module.fail;
-export var ifError = assert_module.ifError;
-export var notDeepEqual = assert_module.notDeepEqual;
-export var notDeepStrictEqual = assert_module.notDeepStrictEqual;
-export var notEqual = assert_module.notEqual;
-export var notStrictEqual = assert_module.notStrictEqual;
-export var ok = assert_module.ok;
-export var rejects = assert_module.rejects;
-export var strict = assert_module.strict;
-export var strictEqual = assert_module.strictEqual;
-export var throws = assert_module.throws;
diff --git a/src/bun.js/assert_strict.exports.js b/src/bun.js/assert_strict.exports.js
new file mode 100644
index 000000000..619986113
--- /dev/null
+++ b/src/bun.js/assert_strict.exports.js
@@ -0,0 +1,48 @@
+var { strict: strictBase } = import.meta.require("node:assert");
+
+export var {
+ fail,
+ AssertionError,
+ ok,
+ equal,
+ notEqual,
+ deepEqual,
+ notDeepEqual,
+ deepStrictEqual,
+ notDeepStrictEqual,
+ strictEqual,
+ notStrictEqual,
+ throws,
+ rejects,
+ doesNotThrow,
+ doesNotReject,
+ ifError,
+ match,
+ doesNotMatch,
+ CallTracker,
+} = strictBase;
+
+const defaultObject = {
+ fail,
+ AssertionError,
+ ok,
+ equal,
+ notEqual,
+ deepEqual,
+ notDeepEqual,
+ deepStrictEqual,
+ notDeepStrictEqual,
+ strictEqual,
+ notStrictEqual,
+ throws,
+ rejects,
+ doesNotThrow,
+ doesNotReject,
+ ifError,
+ match,
+ doesNotMatch,
+ CallTracker,
+ [Symbol.for("CommonJS")]: 0,
+};
+
+export { defaultObject as default, strictBase as strict };
diff --git a/src/bun.js/bindings/Process.cpp b/src/bun.js/bindings/Process.cpp
index d336d5874..6be74ec6d 100644
--- a/src/bun.js/bindings/Process.cpp
+++ b/src/bun.js/bindings/Process.cpp
@@ -14,7 +14,7 @@ namespace Zig {
using namespace JSC;
-#define REPORTED_NODE_VERSION "18.13.0"
+#define REPORTED_NODE_VERSION "18.15.0"
using JSGlobalObject = JSC::JSGlobalObject;
using Exception = JSC::Exception;
@@ -308,15 +308,6 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionUptime,
return JSC::JSValue::encode(JSC::jsNumber(result));
}
-JSC_DEFINE_HOST_FUNCTION(Process_functionBinding,
- (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
-{
- auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
- auto& vm = globalObject->vm();
- throwTypeError(globalObject, scope, "process.binding is not supported in Bun. If this breaks a library you're using, please file an issue at https://bun.sh/issues and include a reproducible code sample."_s);
- return JSC::JSValue::encode(JSC::JSValue {});
-}
-
JSC_DEFINE_HOST_FUNCTION(Process_functionExit,
(JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))
{
@@ -733,8 +724,9 @@ void Process::finishCreation(JSC::VM& vm)
this->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(this->vm(), "umask"_s),
1, Process_functionUmask, ImplementationVisibility::Public, NoIntrinsic, 0);
- this->putDirectNativeFunction(vm, globalObject, JSC::Identifier::fromString(this->vm(), "binding"_s),
- 1, Process_functionBinding, ImplementationVisibility::Public, NoIntrinsic, PropertyAttribute::DontEnum | 0);
+ this->putDirectBuiltinFunction(vm, globalObject, JSC::Identifier::fromString(this->vm(), "binding"_s),
+ processObjectInternalsBindingCodeGenerator(vm),
+ 0);
this->putDirect(vm, vm.propertyNames->toStringTagSymbol, jsString(vm, String("process"_s)), 0);
@@ -946,4 +938,4 @@ static JSC_DEFINE_HOST_FUNCTION(Process_functionCwd,
return JSC::JSValue::encode(result);
}
-} // namespace Zig \ No newline at end of file
+} // namespace Zig
diff --git a/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp b/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp
index d44656f75..c2276138e 100644
--- a/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp
+++ b/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.cpp
@@ -48,6 +48,40 @@
namespace WebCore {
+const JSC::ConstructAbility s_processObjectInternalsBindingCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
+const JSC::ConstructorKind s_processObjectInternalsBindingCodeConstructorKind = JSC::ConstructorKind::None;
+const JSC::ImplementationVisibility s_processObjectInternalsBindingCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
+const int s_processObjectInternalsBindingCodeLength = 688;
+static const JSC::Intrinsic s_processObjectInternalsBindingCodeIntrinsic = JSC::NoIntrinsic;
+const char* const s_processObjectInternalsBindingCode =
+ "(function (bindingName) {\n" \
+ " \"use strict\";\n" \
+ " bindingName !== \"constants\" &&\n" \
+ " @throwTypeError(\n" \
+ " 'process.binding() is not supported in Bun. If that breaks something, please file an issue and include a reproducible code sample.'\n" \
+ " );\n" \
+ "\n" \
+ " var cache = globalThis.Symbol.for(\"process.bindings.constants\");\n" \
+ " var constants = globalThis[cache];\n" \
+ " if (!constants) {\n" \
+ " const {constants: fs} = globalThis[globalThis.Symbol.for(\"Bun.lazy\")](\n" \
+ " \"createImportMeta\",\n" \
+ " \"node:process\"\n" \
+ " ).require(\n" \
+ " \"node:fs\"\n" \
+ " )\n" \
+ " constants = {\n" \
+ " fs,\n" \
+ " zlib: {},\n" \
+ " crypto: {},\n" \
+ " os: @Bun._Os().constants,\n" \
+ " };\n" \
+ " globalThis[cache] = constants;\n" \
+ " }\n" \
+ " return constants;\n" \
+ "})\n" \
+;
+
const JSC::ConstructAbility s_processObjectInternalsGetStdioWriteStreamCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const JSC::ConstructorKind s_processObjectInternalsGetStdioWriteStreamCodeConstructorKind = JSC::ConstructorKind::None;
const JSC::ImplementationVisibility s_processObjectInternalsGetStdioWriteStreamCodeImplementationVisibility = JSC::ImplementationVisibility::Public;
diff --git a/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.h b/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.h
index c3af84061..a109d2de0 100644
--- a/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.h
+++ b/src/bun.js/builtins/cpp/ProcessObjectInternalsBuiltins.h
@@ -47,6 +47,11 @@ class FunctionExecutable;
namespace WebCore {
/* ProcessObjectInternals */
+extern const char* const s_processObjectInternalsBindingCode;
+extern const int s_processObjectInternalsBindingCodeLength;
+extern const JSC::ConstructAbility s_processObjectInternalsBindingCodeConstructAbility;
+extern const JSC::ConstructorKind s_processObjectInternalsBindingCodeConstructorKind;
+extern const JSC::ImplementationVisibility s_processObjectInternalsBindingCodeImplementationVisibility;
extern const char* const s_processObjectInternalsGetStdioWriteStreamCode;
extern const int s_processObjectInternalsGetStdioWriteStreamCodeLength;
extern const JSC::ConstructAbility s_processObjectInternalsGetStdioWriteStreamCodeConstructAbility;
@@ -59,17 +64,21 @@ extern const JSC::ConstructorKind s_processObjectInternalsGetStdinStreamCodeCons
extern const JSC::ImplementationVisibility s_processObjectInternalsGetStdinStreamCodeImplementationVisibility;
#define WEBCORE_FOREACH_PROCESSOBJECTINTERNALS_BUILTIN_DATA(macro) \
+ macro(binding, processObjectInternalsBinding, 1) \
macro(getStdioWriteStream, processObjectInternalsGetStdioWriteStream, 2) \
macro(getStdinStream, processObjectInternalsGetStdinStream, 3) \
+#define WEBCORE_BUILTIN_PROCESSOBJECTINTERNALS_BINDING 1
#define WEBCORE_BUILTIN_PROCESSOBJECTINTERNALS_GETSTDIOWRITESTREAM 1
#define WEBCORE_BUILTIN_PROCESSOBJECTINTERNALS_GETSTDINSTREAM 1
#define WEBCORE_FOREACH_PROCESSOBJECTINTERNALS_BUILTIN_CODE(macro) \
+ macro(processObjectInternalsBindingCode, binding, ASCIILiteral(), s_processObjectInternalsBindingCodeLength) \
macro(processObjectInternalsGetStdioWriteStreamCode, getStdioWriteStream, ASCIILiteral(), s_processObjectInternalsGetStdioWriteStreamCodeLength) \
macro(processObjectInternalsGetStdinStreamCode, getStdinStream, ASCIILiteral(), s_processObjectInternalsGetStdinStreamCodeLength) \
#define WEBCORE_FOREACH_PROCESSOBJECTINTERNALS_BUILTIN_FUNCTION_NAME(macro) \
+ macro(binding) \
macro(getStdinStream) \
macro(getStdioWriteStream) \
diff --git a/src/bun.js/builtins/js/ProcessObjectInternals.js b/src/bun.js/builtins/js/ProcessObjectInternals.js
index c1898d686..d9ab6d88a 100644
--- a/src/bun.js/builtins/js/ProcessObjectInternals.js
+++ b/src/bun.js/builtins/js/ProcessObjectInternals.js
@@ -23,6 +23,37 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
+function binding(bindingName) {
+ "use strict";
+ bindingName !== "constants" &&
+ @throwTypeError(
+ 'process.binding() is not supported in Bun. If that breaks something, please file an issue and include a reproducible code sample.'
+ );
+
+ var cache = globalThis.Symbol.for("process.bindings.constants");
+ var constants = globalThis[cache];
+ if (!constants) {
+ // TODO: make this less hacky.
+ // This calls require("node:fs").constants
+ // except, outside an ESM module.
+ const {constants: fs} = globalThis[globalThis.Symbol.for("Bun.lazy")](
+ "createImportMeta",
+ "node:process"
+ ).require(
+ "node:fs"
+ )
+ constants = {
+ fs,
+ zlib: {},
+ crypto: {},
+ os: @Bun._Os().constants,
+ };
+ globalThis[cache] = constants;
+ }
+ return constants;
+}
+
function getStdioWriteStream(fd_, rawRequire) {
var module = { path: "node:process", require: rawRequire };
var require = path => module.require(path);
diff --git a/src/bun.js/cluster.exports.js b/src/bun.js/cluster.exports.js
new file mode 100644
index 000000000..201310dd5
--- /dev/null
+++ b/src/bun.js/cluster.exports.js
@@ -0,0 +1,57 @@
+// This is a stub
+// We leave it in here to provide a better error message
+// TODO: implement node cluster
+const { EventEmitter } = import.meta.require("node:events");
+class TODO extends Error {
+ constructor(
+ message = "node:cluster is not implemented yet in Bun. Track the status: https://github.com/oven-sh/bun/issues/2428",
+ ) {
+ super(message);
+ this.name = "TODO";
+ }
+}
+
+export var SCHED_NONE = 0,
+ SCHED_RR = 1,
+ Worker,
+ schedulingPolicy = 2,
+ isWorker = false,
+ isPrimary = true,
+ isMaster = true,
+ cluster;
+
+Worker = function Worker() {
+ throw new TODO("Worker is not implemented yet in Bun");
+};
+
+// TODO: is it okay for this to be a class?
+class Cluster extends EventEmitter {
+ static isWorker = false;
+ static isPrimary = true;
+ static isMaster = true;
+
+ static Worker = Worker;
+
+ fork() {
+ throw new TODO();
+ }
+
+ disconnect() {
+ throw new TODO();
+ }
+
+ setupMaster() {
+ throw new TODO();
+ }
+
+ settings = {};
+ workers = {};
+ SCHED_NONE = 0;
+ SCHED_RR = 1;
+ schedulingPolicy = 2;
+ [Symbol.for("CommonJS")] = 0;
+}
+
+cluster = new Cluster();
+
+export { cluster as default };
diff --git a/src/bun.js/dgram.exports.js b/src/bun.js/dgram.exports.js
new file mode 100644
index 000000000..65b531baa
--- /dev/null
+++ b/src/bun.js/dgram.exports.js
@@ -0,0 +1,46 @@
+// This is a stub! None of this is actually implemented yet.
+
+function hideFromStack(fns) {
+ for (const fn of fns) {
+ Object.defineProperty(fn, "name", {
+ value: "::bunternal::",
+ });
+ }
+}
+
+class TODO extends Error {
+ constructor(messageName) {
+ const message = messageName
+ ? `node:dgram ${messageName} is not implemented yet in Bun. Track the status and thumbs up the issue: https://github.com/oven-sh/bun/issues/1630`
+ : `node:dgram is not implemented yet in Bun. Track the status and thumbs up the issue: https://github.com/oven-sh/bun/issues/1630`;
+ super(message);
+ this.name = "TODO";
+ }
+}
+
+function notimpl(message) {
+ throw new TODO(message);
+}
+
+function createSocket() {
+ notimpl("createSocket");
+}
+
+function Socket() {
+ notimpl("Socket");
+}
+
+function _createSocketHandle() {
+ notimpl("_createSocketHandle");
+}
+
+const defaultObject = {
+ createSocket,
+ Socket,
+ _createSocketHandle,
+ [Symbol.for("CommonJS")]: 0,
+};
+
+export { defaultObject as default, Socket, createSocket, _createSocketHandle };
+
+hideFromStack([TODO.prototype.constructor, notimpl, createSocket, Socket, _createSocketHandle]);
diff --git a/src/bun.js/diagnostics_channel.exports.js b/src/bun.js/diagnostics_channel.exports.js
new file mode 100644
index 000000000..732e8fb73
--- /dev/null
+++ b/src/bun.js/diagnostics_channel.exports.js
@@ -0,0 +1,57 @@
+// This is a stub! None of this is actually implemented yet.
+
+function hideFromStack(fns) {
+ for (const fn of fns) {
+ Object.defineProperty(fn, "name", {
+ value: "::bunternal::",
+ });
+ }
+}
+
+class TODO extends Error {
+ constructor(messageName) {
+ const message = messageName
+ ? `node:diagnostics_channel ${messageName} is not implemented yet in Bun.`
+ : `node:diagnostics_channel is not implemented yet in Bun.`;
+ super(message);
+ this.name = "TODO";
+ }
+}
+
+function notimpl() {
+ throw new TODO();
+}
+
+class Channel {
+ constructor(name) {
+ notimpl();
+ }
+}
+
+function channel() {
+ notimpl();
+}
+
+function hasSubscribers() {
+ notimpl();
+}
+function subscribe() {
+ notimpl();
+}
+
+function unsubscribe() {
+ notimpl();
+}
+
+const defaultObject = {
+ channel,
+ hasSubscribers,
+ subscribe,
+ unsubscribe,
+ Channel,
+ [Symbol.for("CommonJS")]: 0,
+};
+
+export { defaultObject as default, Channel, channel, hasSubscribers, subscribe, unsubscribe };
+
+hideFromStack([TODO.prototype.constructor, notimpl, channel, hasSubscribers, subscribe, unsubscribe, Channel]);
diff --git a/src/bun.js/http2.exports.js b/src/bun.js/http2.exports.js
new file mode 100644
index 000000000..9deafbd3f
--- /dev/null
+++ b/src/bun.js/http2.exports.js
@@ -0,0 +1,342 @@
+// This is a stub! None of this is actually implemented yet.
+
+function hideFromStack(fns) {
+ for (const fn of fns) {
+ Object.defineProperty(fn, "name", {
+ value: "::bunternal::",
+ });
+ }
+}
+
+class TODO extends Error {
+ constructor(messageName) {
+ const message = messageName
+ ? `node:http2 ${messageName} is not implemented yet in Bun. Track the status and thumbs up the issue: https://github.com/oven-sh/bun/issues/887`
+ : `node:http2 is not implemented yet in Bun. Track the status and thumbs up the issue: https://github.com/oven-sh/bun/issues/887`;
+ super(message);
+ this.name = "TODO";
+ }
+}
+
+function notimpl(message) {
+ throw new TODO(message);
+}
+
+function connect() {
+ notimpl("connect");
+}
+const constants = {
+ NGHTTP2_ERR_FRAME_SIZE_ERROR: -522,
+ NGHTTP2_SESSION_SERVER: 0,
+ NGHTTP2_SESSION_CLIENT: 1,
+ NGHTTP2_STREAM_STATE_IDLE: 1,
+ NGHTTP2_STREAM_STATE_OPEN: 2,
+ NGHTTP2_STREAM_STATE_RESERVED_LOCAL: 3,
+ NGHTTP2_STREAM_STATE_RESERVED_REMOTE: 4,
+ NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL: 5,
+ NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE: 6,
+ NGHTTP2_STREAM_STATE_CLOSED: 7,
+ NGHTTP2_FLAG_NONE: 0,
+ NGHTTP2_FLAG_END_STREAM: 1,
+ NGHTTP2_FLAG_END_HEADERS: 4,
+ NGHTTP2_FLAG_ACK: 1,
+ NGHTTP2_FLAG_PADDED: 8,
+ NGHTTP2_FLAG_PRIORITY: 32,
+ DEFAULT_SETTINGS_HEADER_TABLE_SIZE: 4096,
+ DEFAULT_SETTINGS_ENABLE_PUSH: 1,
+ DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS: 4294967295,
+ DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE: 65535,
+ DEFAULT_SETTINGS_MAX_FRAME_SIZE: 16384,
+ DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE: 65535,
+ DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL: 0,
+ MAX_MAX_FRAME_SIZE: 16777215,
+ MIN_MAX_FRAME_SIZE: 16384,
+ MAX_INITIAL_WINDOW_SIZE: 2147483647,
+ NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: 1,
+ NGHTTP2_SETTINGS_ENABLE_PUSH: 2,
+ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: 3,
+ NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: 4,
+ NGHTTP2_SETTINGS_MAX_FRAME_SIZE: 5,
+ NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: 6,
+ NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL: 8,
+ PADDING_STRATEGY_NONE: 0,
+ PADDING_STRATEGY_ALIGNED: 1,
+ PADDING_STRATEGY_MAX: 2,
+ PADDING_STRATEGY_CALLBACK: 1,
+ NGHTTP2_NO_ERROR: 0,
+ NGHTTP2_PROTOCOL_ERROR: 1,
+ NGHTTP2_INTERNAL_ERROR: 2,
+ NGHTTP2_FLOW_CONTROL_ERROR: 3,
+ NGHTTP2_SETTINGS_TIMEOUT: 4,
+ NGHTTP2_STREAM_CLOSED: 5,
+ NGHTTP2_FRAME_SIZE_ERROR: 6,
+ NGHTTP2_REFUSED_STREAM: 7,
+ NGHTTP2_CANCEL: 8,
+ NGHTTP2_COMPRESSION_ERROR: 9,
+ NGHTTP2_CONNECT_ERROR: 10,
+ NGHTTP2_ENHANCE_YOUR_CALM: 11,
+ NGHTTP2_INADEQUATE_SECURITY: 12,
+ NGHTTP2_HTTP_1_1_REQUIRED: 13,
+ NGHTTP2_DEFAULT_WEIGHT: 16,
+ HTTP2_HEADER_STATUS: ":status",
+ HTTP2_HEADER_METHOD: ":method",
+ HTTP2_HEADER_AUTHORITY: ":authority",
+ HTTP2_HEADER_SCHEME: ":scheme",
+ HTTP2_HEADER_PATH: ":path",
+ HTTP2_HEADER_PROTOCOL: ":protocol",
+ HTTP2_HEADER_ACCEPT_ENCODING: "accept-encoding",
+ HTTP2_HEADER_ACCEPT_LANGUAGE: "accept-language",
+ HTTP2_HEADER_ACCEPT_RANGES: "accept-ranges",
+ HTTP2_HEADER_ACCEPT: "accept",
+ HTTP2_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS: "access-control-allow-credentials",
+ HTTP2_HEADER_ACCESS_CONTROL_ALLOW_HEADERS: "access-control-allow-headers",
+ HTTP2_HEADER_ACCESS_CONTROL_ALLOW_METHODS: "access-control-allow-methods",
+ HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN: "access-control-allow-origin",
+ HTTP2_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS: "access-control-expose-headers",
+ HTTP2_HEADER_ACCESS_CONTROL_REQUEST_HEADERS: "access-control-request-headers",
+ HTTP2_HEADER_ACCESS_CONTROL_REQUEST_METHOD: "access-control-request-method",
+ HTTP2_HEADER_AGE: "age",
+ HTTP2_HEADER_AUTHORIZATION: "authorization",
+ HTTP2_HEADER_CACHE_CONTROL: "cache-control",
+ HTTP2_HEADER_CONNECTION: "connection",
+ HTTP2_HEADER_CONTENT_DISPOSITION: "content-disposition",
+ HTTP2_HEADER_CONTENT_ENCODING: "content-encoding",
+ HTTP2_HEADER_CONTENT_LENGTH: "content-length",
+ HTTP2_HEADER_CONTENT_TYPE: "content-type",
+ HTTP2_HEADER_COOKIE: "cookie",
+ HTTP2_HEADER_DATE: "date",
+ HTTP2_HEADER_ETAG: "etag",
+ HTTP2_HEADER_FORWARDED: "forwarded",
+ HTTP2_HEADER_HOST: "host",
+ HTTP2_HEADER_IF_MODIFIED_SINCE: "if-modified-since",
+ HTTP2_HEADER_IF_NONE_MATCH: "if-none-match",
+ HTTP2_HEADER_IF_RANGE: "if-range",
+ HTTP2_HEADER_LAST_MODIFIED: "last-modified",
+ HTTP2_HEADER_LINK: "link",
+ HTTP2_HEADER_LOCATION: "location",
+ HTTP2_HEADER_RANGE: "range",
+ HTTP2_HEADER_REFERER: "referer",
+ HTTP2_HEADER_SERVER: "server",
+ HTTP2_HEADER_SET_COOKIE: "set-cookie",
+ HTTP2_HEADER_STRICT_TRANSPORT_SECURITY: "strict-transport-security",
+ HTTP2_HEADER_TRANSFER_ENCODING: "transfer-encoding",
+ HTTP2_HEADER_TE: "te",
+ HTTP2_HEADER_UPGRADE_INSECURE_REQUESTS: "upgrade-insecure-requests",
+ HTTP2_HEADER_UPGRADE: "upgrade",
+ HTTP2_HEADER_USER_AGENT: "user-agent",
+ HTTP2_HEADER_VARY: "vary",
+ HTTP2_HEADER_X_CONTENT_TYPE_OPTIONS: "x-content-type-options",
+ HTTP2_HEADER_X_FRAME_OPTIONS: "x-frame-options",
+ HTTP2_HEADER_KEEP_ALIVE: "keep-alive",
+ HTTP2_HEADER_PROXY_CONNECTION: "proxy-connection",
+ HTTP2_HEADER_X_XSS_PROTECTION: "x-xss-protection",
+ HTTP2_HEADER_ALT_SVC: "alt-svc",
+ HTTP2_HEADER_CONTENT_SECURITY_POLICY: "content-security-policy",
+ HTTP2_HEADER_EARLY_DATA: "early-data",
+ HTTP2_HEADER_EXPECT_CT: "expect-ct",
+ HTTP2_HEADER_ORIGIN: "origin",
+ HTTP2_HEADER_PURPOSE: "purpose",
+ HTTP2_HEADER_TIMING_ALLOW_ORIGIN: "timing-allow-origin",
+ HTTP2_HEADER_X_FORWARDED_FOR: "x-forwarded-for",
+ HTTP2_HEADER_PRIORITY: "priority",
+ HTTP2_HEADER_ACCEPT_CHARSET: "accept-charset",
+ HTTP2_HEADER_ACCESS_CONTROL_MAX_AGE: "access-control-max-age",
+ HTTP2_HEADER_ALLOW: "allow",
+ HTTP2_HEADER_CONTENT_LANGUAGE: "content-language",
+ HTTP2_HEADER_CONTENT_LOCATION: "content-location",
+ HTTP2_HEADER_CONTENT_MD5: "content-md5",
+ HTTP2_HEADER_CONTENT_RANGE: "content-range",
+ HTTP2_HEADER_DNT: "dnt",
+ HTTP2_HEADER_EXPECT: "expect",
+ HTTP2_HEADER_EXPIRES: "expires",
+ HTTP2_HEADER_FROM: "from",
+ HTTP2_HEADER_IF_MATCH: "if-match",
+ HTTP2_HEADER_IF_UNMODIFIED_SINCE: "if-unmodified-since",
+ HTTP2_HEADER_MAX_FORWARDS: "max-forwards",
+ HTTP2_HEADER_PREFER: "prefer",
+ HTTP2_HEADER_PROXY_AUTHENTICATE: "proxy-authenticate",
+ HTTP2_HEADER_PROXY_AUTHORIZATION: "proxy-authorization",
+ HTTP2_HEADER_REFRESH: "refresh",
+ HTTP2_HEADER_RETRY_AFTER: "retry-after",
+ HTTP2_HEADER_TRAILER: "trailer",
+ HTTP2_HEADER_TK: "tk",
+ HTTP2_HEADER_VIA: "via",
+ HTTP2_HEADER_WARNING: "warning",
+ HTTP2_HEADER_WWW_AUTHENTICATE: "www-authenticate",
+ HTTP2_HEADER_HTTP2_SETTINGS: "http2-settings",
+ HTTP2_METHOD_ACL: "ACL",
+ HTTP2_METHOD_BASELINE_CONTROL: "BASELINE-CONTROL",
+ HTTP2_METHOD_BIND: "BIND",
+ HTTP2_METHOD_CHECKIN: "CHECKIN",
+ HTTP2_METHOD_CHECKOUT: "CHECKOUT",
+ HTTP2_METHOD_CONNECT: "CONNECT",
+ HTTP2_METHOD_COPY: "COPY",
+ HTTP2_METHOD_DELETE: "DELETE",
+ HTTP2_METHOD_GET: "GET",
+ HTTP2_METHOD_HEAD: "HEAD",
+ HTTP2_METHOD_LABEL: "LABEL",
+ HTTP2_METHOD_LINK: "LINK",
+ HTTP2_METHOD_LOCK: "LOCK",
+ HTTP2_METHOD_MERGE: "MERGE",
+ HTTP2_METHOD_MKACTIVITY: "MKACTIVITY",
+ HTTP2_METHOD_MKCALENDAR: "MKCALENDAR",
+ HTTP2_METHOD_MKCOL: "MKCOL",
+ HTTP2_METHOD_MKREDIRECTREF: "MKREDIRECTREF",
+ HTTP2_METHOD_MKWORKSPACE: "MKWORKSPACE",
+ HTTP2_METHOD_MOVE: "MOVE",
+ HTTP2_METHOD_OPTIONS: "OPTIONS",
+ HTTP2_METHOD_ORDERPATCH: "ORDERPATCH",
+ HTTP2_METHOD_PATCH: "PATCH",
+ HTTP2_METHOD_POST: "POST",
+ HTTP2_METHOD_PRI: "PRI",
+ HTTP2_METHOD_PROPFIND: "PROPFIND",
+ HTTP2_METHOD_PROPPATCH: "PROPPATCH",
+ HTTP2_METHOD_PUT: "PUT",
+ HTTP2_METHOD_REBIND: "REBIND",
+ HTTP2_METHOD_REPORT: "REPORT",
+ HTTP2_METHOD_SEARCH: "SEARCH",
+ HTTP2_METHOD_TRACE: "TRACE",
+ HTTP2_METHOD_UNBIND: "UNBIND",
+ HTTP2_METHOD_UNCHECKOUT: "UNCHECKOUT",
+ HTTP2_METHOD_UNLINK: "UNLINK",
+ HTTP2_METHOD_UNLOCK: "UNLOCK",
+ HTTP2_METHOD_UPDATE: "UPDATE",
+ HTTP2_METHOD_UPDATEREDIRECTREF: "UPDATEREDIRECTREF",
+ HTTP2_METHOD_VERSION_CONTROL: "VERSION-CONTROL",
+ HTTP_STATUS_CONTINUE: 100,
+ HTTP_STATUS_SWITCHING_PROTOCOLS: 101,
+ HTTP_STATUS_PROCESSING: 102,
+ HTTP_STATUS_EARLY_HINTS: 103,
+ HTTP_STATUS_OK: 200,
+ HTTP_STATUS_CREATED: 201,
+ HTTP_STATUS_ACCEPTED: 202,
+ HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION: 203,
+ HTTP_STATUS_NO_CONTENT: 204,
+ HTTP_STATUS_RESET_CONTENT: 205,
+ HTTP_STATUS_PARTIAL_CONTENT: 206,
+ HTTP_STATUS_MULTI_STATUS: 207,
+ HTTP_STATUS_ALREADY_REPORTED: 208,
+ HTTP_STATUS_IM_USED: 226,
+ HTTP_STATUS_MULTIPLE_CHOICES: 300,
+ HTTP_STATUS_MOVED_PERMANENTLY: 301,
+ HTTP_STATUS_FOUND: 302,
+ HTTP_STATUS_SEE_OTHER: 303,
+ HTTP_STATUS_NOT_MODIFIED: 304,
+ HTTP_STATUS_USE_PROXY: 305,
+ HTTP_STATUS_TEMPORARY_REDIRECT: 307,
+ HTTP_STATUS_PERMANENT_REDIRECT: 308,
+ HTTP_STATUS_BAD_REQUEST: 400,
+ HTTP_STATUS_UNAUTHORIZED: 401,
+ HTTP_STATUS_PAYMENT_REQUIRED: 402,
+ HTTP_STATUS_FORBIDDEN: 403,
+ HTTP_STATUS_NOT_FOUND: 404,
+ HTTP_STATUS_METHOD_NOT_ALLOWED: 405,
+ HTTP_STATUS_NOT_ACCEPTABLE: 406,
+ HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED: 407,
+ HTTP_STATUS_REQUEST_TIMEOUT: 408,
+ HTTP_STATUS_CONFLICT: 409,
+ HTTP_STATUS_GONE: 410,
+ HTTP_STATUS_LENGTH_REQUIRED: 411,
+ HTTP_STATUS_PRECONDITION_FAILED: 412,
+ HTTP_STATUS_PAYLOAD_TOO_LARGE: 413,
+ HTTP_STATUS_URI_TOO_LONG: 414,
+ HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE: 415,
+ HTTP_STATUS_RANGE_NOT_SATISFIABLE: 416,
+ HTTP_STATUS_EXPECTATION_FAILED: 417,
+ HTTP_STATUS_TEAPOT: 418,
+ HTTP_STATUS_MISDIRECTED_REQUEST: 421,
+ HTTP_STATUS_UNPROCESSABLE_ENTITY: 422,
+ HTTP_STATUS_LOCKED: 423,
+ HTTP_STATUS_FAILED_DEPENDENCY: 424,
+ HTTP_STATUS_TOO_EARLY: 425,
+ HTTP_STATUS_UPGRADE_REQUIRED: 426,
+ HTTP_STATUS_PRECONDITION_REQUIRED: 428,
+ HTTP_STATUS_TOO_MANY_REQUESTS: 429,
+ HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
+ HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS: 451,
+ HTTP_STATUS_INTERNAL_SERVER_ERROR: 500,
+ HTTP_STATUS_NOT_IMPLEMENTED: 501,
+ HTTP_STATUS_BAD_GATEWAY: 502,
+ HTTP_STATUS_SERVICE_UNAVAILABLE: 503,
+ HTTP_STATUS_GATEWAY_TIMEOUT: 504,
+ HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED: 505,
+ HTTP_STATUS_VARIANT_ALSO_NEGOTIATES: 506,
+ HTTP_STATUS_INSUFFICIENT_STORAGE: 507,
+ HTTP_STATUS_LOOP_DETECTED: 508,
+ HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED: 509,
+ HTTP_STATUS_NOT_EXTENDED: 510,
+ HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED: 511,
+};
+
+function createServer() {
+ notimpl("createServer");
+}
+function createSecureServer() {
+ notimpl("createSecureServer");
+}
+function getDefaultSettings() {
+ return {
+ headerTableSize: 4096,
+ enablePush: true,
+ initialWindowSize: 65535,
+ maxFrameSize: 16384,
+ maxConcurrentStreams: 4294967295,
+ maxHeaderSize: 65535,
+ maxHeaderListSize: 65535,
+ enableConnectProtocol: false,
+ };
+}
+function getPackedSettings() {
+ return Buffer.alloc(0);
+}
+function getUnpackedSettings() {
+ return Buffer.alloc(0);
+}
+const sensitiveHeaders = Symbol.for("nodejs.http2.sensitiveHeaders");
+function Http2ServerRequest() {
+ notimpl("Http2ServerRequest");
+}
+function Http2ServerResponse() {
+ notimpl("Http2ServerResponse");
+}
+
+const defaultObject = {
+ constants,
+ createServer,
+ createSecureServer,
+ getDefaultSettings,
+ getPackedSettings,
+ getUnpackedSettings,
+ sensitiveHeaders,
+ Http2ServerRequest,
+ Http2ServerResponse,
+ [Symbol.for("CommonJS")]: 0,
+ connect,
+};
+
+export {
+ constants,
+ createServer,
+ createSecureServer,
+ getDefaultSettings,
+ getPackedSettings,
+ getUnpackedSettings,
+ sensitiveHeaders,
+ Http2ServerRequest,
+ Http2ServerResponse,
+ defaultObject as default,
+ connect,
+};
+
+hideFromStack([
+ TODO.prototype.constructor,
+ Http2ServerRequest,
+ notimpl,
+ Http2ServerResponse,
+ connect,
+ createServer,
+ createSecureServer,
+ getDefaultSettings,
+ getPackedSettings,
+ getUnpackedSettings,
+]);
diff --git a/src/bun.js/inspector.exports.js b/src/bun.js/inspector.exports.js
new file mode 100644
index 000000000..eccb39c10
--- /dev/null
+++ b/src/bun.js/inspector.exports.js
@@ -0,0 +1,68 @@
+// This is a stub! None of this is actually implemented yet.
+
+function hideFromStack(fns) {
+ for (const fn of fns) {
+ Object.defineProperty(fn, "name", {
+ value: "::bunternal::",
+ });
+ }
+}
+
+class TODO extends Error {
+ constructor(messageName) {
+ const message = messageName
+ ? `node:inspector ${messageName} is not implemented yet in Bun. Track the status & thumbs up the issue: https://github.com/oven-sh/bun/issues/2445`
+ : `node:inspector is not implemented yet in Bun. Track the status & thumbs up the issue: https://github.com/oven-sh/bun/issues/2445`;
+ super(message);
+ this.name = "TODO";
+ }
+}
+
+function notimpl(message) {
+ throw new TODO(message);
+}
+
+const { EventEmitter } = import.meta.require("node:events");
+
+function open() {
+ notimpl("open");
+}
+
+function close() {
+ notimpl("close");
+}
+
+function url() {
+ notimpl("url");
+}
+
+function waitForDebugger() {
+ notimpl("waitForDebugger");
+}
+
+class Session extends EventEmitter {
+ constructor() {
+ super();
+ notimpl("Session");
+ }
+}
+
+const console = {
+ ...globalThis.console,
+ context: {
+ console: globalThis.console,
+ },
+};
+
+var defaultObject = {
+ console,
+ open,
+ close,
+ url,
+ waitForDebugger,
+ Session,
+ [Symbol.for("CommonJS")]: 0,
+};
+
+export { console, open, close, url, waitForDebugger, Session, defaultObject as default };
+hideFromStack([notimpl, TODO.prototype.constructor, open, close, url, waitForDebugger, Session.prototype.constructor]);
diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig
index e9a4bb2c2..71990a7ac 100644
--- a/src/bun.js/module_loader.zig
+++ b/src/bun.js/module_loader.zig
@@ -2026,6 +2026,17 @@ pub const ModuleLoader = struct {
.hash = 0,
};
},
+ .@"node:stream/promises" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:stream/promises", "node_streams_promises.exports.js"),
+ .@"node:vm" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:vm", "vm.exports.js"),
+ .@"node:assert/strict" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:assert/strict", "assert_strict.exports.js"),
+ .@"node:v8" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:v8", "v8.exports.js"),
+ .@"node:trace_events" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:trace_events", "trace_events.exports.js"),
+ .@"node:repl" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:repl", "repl.exports.js"),
+ .@"node:inspector" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:inspector", "inspector.exports.js"),
+ .@"node:http2" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:http2", "http2.exports.js"),
+ .@"node:diagnostics_channel" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:diagnostics_channel", "diagnostics_channel.exports.js"),
+ .@"node:dgram" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:dgram", "dgram.exports.js"),
+ .@"node:cluster" => return jsResolvedSource(jsc_vm.load_builtins_from_path, .@"node:cluster", "cluster.exports.js"),
}
} else if (strings.hasPrefixComptime(specifier, js_ast.Macro.namespaceWithColon)) {
if (jsc_vm.macro_entry_points.get(MacroEntryPoint.generateIDFromSpecifier(specifier))) |entry| {
@@ -2147,6 +2158,7 @@ pub const HardcodedModule = enum {
@"bun:sqlite",
@"detect-libc",
@"node:assert",
+ @"node:assert/strict",
@"node:async_hooks",
@"node:buffer",
@"node:child_process",
@@ -2170,6 +2182,7 @@ pub const HardcodedModule = enum {
@"node:readline/promises",
@"node:stream",
@"node:stream/consumers",
+ @"node:stream/promises",
@"node:stream/web",
@"node:string_decoder",
@"node:timers",
@@ -2179,11 +2192,22 @@ pub const HardcodedModule = enum {
@"node:url",
@"node:util",
@"node:util/types",
+ @"node:vm",
+ @"node:wasi",
@"node:zlib",
depd,
undici,
ws,
- @"node:wasi",
+ // These are all not implemented yet, but are stubbed
+ @"node:v8",
+ @"node:trace_events",
+ @"node:repl",
+ @"node:inspector",
+ @"node:http2",
+ @"node:diagnostics_channel",
+ @"node:dgram",
+ @"node:cluster",
+
/// Already resolved modules go in here.
/// This does not remap the module name, it is just a hash table.
/// Do not put modules that have aliases in here
@@ -2199,17 +2223,23 @@ pub const HardcodedModule = enum {
.{ "depd", HardcodedModule.depd },
.{ "detect-libc", HardcodedModule.@"detect-libc" },
.{ "node:assert", HardcodedModule.@"node:assert" },
- .{ "node:buffer", HardcodedModule.@"node:buffer" },
+ .{ "node:assert/strict", HardcodedModule.@"node:assert/strict" },
.{ "node:async_hooks", HardcodedModule.@"node:async_hooks" },
+ .{ "node:buffer", HardcodedModule.@"node:buffer" },
.{ "node:child_process", HardcodedModule.@"node:child_process" },
+ .{ "node:cluster", HardcodedModule.@"node:cluster" },
.{ "node:crypto", HardcodedModule.@"node:crypto" },
+ .{ "node:dgram", HardcodedModule.@"node:dgram" },
+ .{ "node:diagnostics_channel", HardcodedModule.@"node:diagnostics_channel" },
.{ "node:dns", HardcodedModule.@"node:dns" },
.{ "node:dns/promises", HardcodedModule.@"node:dns/promises" },
.{ "node:events", HardcodedModule.@"node:events" },
.{ "node:fs", HardcodedModule.@"node:fs" },
.{ "node:fs/promises", HardcodedModule.@"node:fs/promises" },
.{ "node:http", HardcodedModule.@"node:http" },
+ .{ "node:http2", HardcodedModule.@"node:http2" },
.{ "node:https", HardcodedModule.@"node:https" },
+ .{ "node:inspector", HardcodedModule.@"node:inspector" },
.{ "node:module", HardcodedModule.@"node:module" },
.{ "node:net", HardcodedModule.@"node:net" },
.{ "node:os", HardcodedModule.@"node:os" },
@@ -2220,17 +2250,22 @@ pub const HardcodedModule = enum {
.{ "node:process", HardcodedModule.@"node:process" },
.{ "node:readline", HardcodedModule.@"node:readline" },
.{ "node:readline/promises", HardcodedModule.@"node:readline/promises" },
+ .{ "node:repl", HardcodedModule.@"node:repl" },
.{ "node:stream", HardcodedModule.@"node:stream" },
.{ "node:stream/consumers", HardcodedModule.@"node:stream/consumers" },
+ .{ "node:stream/promises", HardcodedModule.@"node:stream/promises" },
.{ "node:stream/web", HardcodedModule.@"node:stream/web" },
.{ "node:string_decoder", HardcodedModule.@"node:string_decoder" },
.{ "node:timers", HardcodedModule.@"node:timers" },
.{ "node:timers/promises", HardcodedModule.@"node:timers/promises" },
.{ "node:tls", HardcodedModule.@"node:tls" },
+ .{ "node:trace_events", HardcodedModule.@"node:trace_events" },
.{ "node:tty", HardcodedModule.@"node:tty" },
.{ "node:url", HardcodedModule.@"node:url" },
.{ "node:util", HardcodedModule.@"node:util" },
.{ "node:util/types", HardcodedModule.@"node:util/types" },
+ .{ "node:v8", HardcodedModule.@"node:v8" },
+ .{ "node:vm", HardcodedModule.@"node:vm" },
.{ "node:wasi", HardcodedModule.@"node:wasi" },
.{ "node:zlib", HardcodedModule.@"node:zlib" },
.{ "undici", HardcodedModule.undici },
@@ -2245,13 +2280,14 @@ pub const HardcodedModule = enum {
Alias,
.{
.{ "assert", .{ .path = "node:assert" } },
+ .{ "assert/strict", .{ .path = "node:assert/strict" } },
.{ "async_hooks", .{ .path = "node:async_hooks" } },
.{ "buffer", .{ .path = "node:buffer" } },
+ .{ "bun", .{ .path = "bun", .tag = .bun } },
.{ "bun:ffi", .{ .path = "bun:ffi" } },
.{ "bun:jsc", .{ .path = "bun:jsc" } },
.{ "bun:sqlite", .{ .path = "bun:sqlite" } },
.{ "bun:wrap", .{ .path = "bun:wrap" } },
- .{ "bun", .{ .path = "bun", .tag = .bun } },
.{ "child_process", .{ .path = "node:child_process" } },
.{ "crypto", .{ .path = "node:crypto" } },
.{ "depd", .{ .path = "depd" } },
@@ -2268,6 +2304,7 @@ pub const HardcodedModule = enum {
.{ "module", .{ .path = "node:module" } },
.{ "net", .{ .path = "node:net" } },
.{ "node:assert", .{ .path = "node:assert" } },
+ .{ "node:assert/strict", .{ .path = "node:assert/strict" } },
.{ "node:async_hooks", .{ .path = "node:async_hooks" } },
.{ "node:buffer", .{ .path = "node:buffer" } },
.{ "node:child_process", .{ .path = "node:child_process" } },
@@ -2291,6 +2328,7 @@ pub const HardcodedModule = enum {
.{ "node:readline/promises", .{ .path = "node:readline/promises" } },
.{ "node:stream", .{ .path = "node:stream" } },
.{ "node:stream/consumers", .{ .path = "node:stream/consumers" } },
+ .{ "node:stream/promises", .{ .path = "node:stream/promises" } },
.{ "node:stream/web", .{ .path = "node:stream/web" } },
.{ "node:string_decoder", .{ .path = "node:string_decoder" } },
.{ "node:timers", .{ .path = "node:timers" } },
@@ -2316,6 +2354,7 @@ pub const HardcodedModule = enum {
.{ "readline/promises", .{ .path = "node:readline/promises" } },
.{ "stream", .{ .path = "node:stream" } },
.{ "stream/consumers", .{ .path = "node:stream/consumers" } },
+ .{ "stream/promises", .{ .path = "node:stream/promises" } },
.{ "stream/web", .{ .path = "node:stream/web" } },
.{ "string_decoder", .{ .path = "node:string_decoder" } },
.{ "timers", .{ .path = "node:timers" } },
@@ -2332,8 +2371,47 @@ pub const HardcodedModule = enum {
.{ "ws/lib/websocket", .{ .path = "ws" } },
.{ "zlib", .{ .path = "node:zlib" } },
- // // Prisma has an edge build, but has not set it in package.json exports
- // .{ "@prisma/client", .{ .path = "@prisma/client/edge", .tag = .none } },
+ // These are returned in builtinModules, but probably not many packages use them
+ // so we will just alias them.
+ .{ "_http_agent", .{ .path = "node:http" } },
+ .{ "_http_client", .{ .path = "node:http" } },
+ .{ "_http_common", .{ .path = "node:http" } },
+ .{ "_http_incoming", .{ .path = "node:http" } },
+ .{ "_http_outgoing", .{ .path = "node:http" } },
+ .{ "_http_server", .{ .path = "node:http" } },
+ .{ "_stream_duplex", .{ .path = "node:stream" } },
+ .{ "_stream_passthrough", .{ .path = "node:stream" } },
+ .{ "_stream_readable", .{ .path = "node:stream" } },
+ .{ "_stream_transform", .{ .path = "node:stream" } },
+ .{ "_stream_writable", .{ .path = "node:stream" } },
+ .{ "_stream_wrap", .{ .path = "node:stream" } },
+ .{ "_tls_wrap", .{ .path = "node:tls" } },
+ .{ "_tls_common", .{ .path = "node:tls" } },
+
+ // These are not actually implemented, they are stubbed out
+ .{ "cluster", .{ .path = "node:cluster" } },
+ .{ "dgram", .{ .path = "node:dgram" } },
+ .{ "diagnostics_channel", .{ .path = "node:diagnostics_channel" } },
+ .{ "http2", .{ .path = "node:http2" } },
+ .{ "inspector", .{ .path = "node:inspector" } },
+ .{ "repl", .{ .path = "node:repl" } },
+ .{ "trace_events", .{ .path = "node:trace_events" } },
+ .{ "v8", .{ .path = "node:v8" } },
+ .{ "vm", .{ .path = "node:vm" } },
+
+ // It implements the same interface
+ .{ "inspector/promises", .{ .path = "node:inspector" } },
+ .{ "node:inspector/promises", .{ .path = "node:inspector" } },
+
+ .{ "node:cluster", .{ .path = "node:cluster" } },
+ .{ "node:dgram", .{ .path = "node:dgram" } },
+ .{ "node:diagnostics_channel", .{ .path = "node:diagnostics_channel" } },
+ .{ "node:http2", .{ .path = "node:http2" } },
+ .{ "node:inspector", .{ .path = "node:inspector" } },
+ .{ "node:repl", .{ .path = "node:repl" } },
+ .{ "node:trace_events", .{ .path = "node:trace_events" } },
+ .{ "node:v8", .{ .path = "node:v8" } },
+ .{ "node:vm", .{ .path = "node:vm" } },
},
);
};
@@ -2341,11 +2419,18 @@ pub const HardcodedModule = enum {
pub const DisabledModule = bun.ComptimeStringMap(
void,
.{
- .{"async_hooks"},
- .{"node:async_hooks"},
- .{"node:tls"},
- .{"node:worker_threads"},
- .{"tls"},
+ // Stubbing out worker_threads will break esbuild.
.{"worker_threads"},
+ .{"node:worker_threads"},
},
);
+
+fn jsResolvedSource(builtins: []const u8, comptime module: HardcodedModule, comptime input: []const u8) ResolvedSource {
+ return ResolvedSource{
+ .allocator = null,
+ .source_code = ZigString.init(jsModuleFromFile(builtins, input)),
+ .specifier = ZigString.init(@tagName(module)),
+ .source_url = ZigString.init(@tagName(module)),
+ .hash = 0,
+ };
+}
diff --git a/src/bun.js/node_streams_promises.exports.js b/src/bun.js/node_streams_promises.exports.js
new file mode 100644
index 000000000..1755c73eb
--- /dev/null
+++ b/src/bun.js/node_streams_promises.exports.js
@@ -0,0 +1,9 @@
+var { promises } = import.meta.require("node:stream");
+
+export var { pipeline, finished } = promises;
+
+export default {
+ pipeline,
+ finished,
+ [Symbol.for("CommonJS")]: 0,
+};
diff --git a/src/bun.js/repl.exports.js b/src/bun.js/repl.exports.js
new file mode 100644
index 000000000..196891fc6
--- /dev/null
+++ b/src/bun.js/repl.exports.js
@@ -0,0 +1,86 @@
+// This is a stub! None of this is actually implemented yet.
+// It only exists to make some packages which import this module work.
+
+class NotImplementedYet extends Error {
+ constructor(message = "node:repl is not implemented yet in Bun") {
+ super(message);
+ this.name = "NotImplementedYet";
+ }
+}
+
+function REPLServer() {
+ throw new NotImplementedYet("REPLServer is not implemented yet in Bun");
+}
+
+function Recoverable() {
+ throw new NotImplementedYet("Recoverable is not implemented yet in Bun");
+}
+
+var REPL_MODE_SLOPPY = 0,
+ REPL_MODE_STRICT = 1;
+
+function start() {
+ throw new NotImplementedYet();
+}
+
+var repl = {
+ [Symbol.for("CommonJS")]: 0,
+ lines: [],
+ context: globalThis,
+ historyIndex: -1,
+ cursor: 0,
+ historySize: 1000,
+ removeHistoryDuplicates: false,
+ crlfDelay: 100,
+ completer: () => {
+ throw new NotImplementedYet();
+ },
+ history: [],
+ _initialPrompt: "> ",
+ terminal: true,
+ cursor: 0,
+ input: new Proxy(
+ {},
+ {
+ get() {
+ throw new NotImplementedYet();
+ },
+ has: () => false,
+ ownKeys: () => [],
+ getOwnPropertyDescriptor: () => undefined,
+ set() {
+ throw new NotImplementedYet();
+ },
+ },
+ ),
+ line: "",
+ eval: () => {
+ throw new NotImplementedYet();
+ },
+ isCompletionEnabled: true,
+ escapeCodeTimeout: 500,
+ tabSize: 8,
+ breakEvalOnSigint: true,
+ useGlobal: true,
+ underscoreAssigned: false,
+ last: undefined,
+ _domain: undefined,
+ allowBlockingCompletions: false,
+ useColors: true,
+ output: new Proxy(
+ {},
+ {
+ get() {
+ throw new NotImplementedYet();
+ },
+ has: () => false,
+ ownKeys: () => [],
+ getOwnPropertyDescriptor: () => undefined,
+ set() {
+ throw new NotImplementedYet();
+ },
+ },
+ ),
+};
+
+export { repl as default, repl, REPLServer, Recoverable, REPL_MODE_SLOPPY, REPL_MODE_STRICT, start };
diff --git a/src/bun.js/streams.exports.js b/src/bun.js/streams.exports.js
index 90c5c9b24..13b26d475 100644
--- a/src/bun.js/streams.exports.js
+++ b/src/bun.js/streams.exports.js
@@ -5653,3 +5653,4 @@ export var Stream = stream_exports.Stream;
export var eos = (stream_exports["eos"] = require_end_of_stream);
export var _getNativeReadableStreamPrototype = stream_exports._getNativeReadableStreamPrototype;
export var NativeWritable = stream_exports.NativeWritable;
+export var promises = Stream.promise;
diff --git a/src/bun.js/trace_events.exports.js b/src/bun.js/trace_events.exports.js
new file mode 100644
index 000000000..44ee28203
--- /dev/null
+++ b/src/bun.js/trace_events.exports.js
@@ -0,0 +1,33 @@
+// This is a stub! This is not actually implemented yet.
+
+class Tracing {
+ enabled = false;
+ categories = "";
+}
+
+function ERR_INVALID_ARG_TYPE(name, type, value) {
+ const err = new TypeError(`The "${name}" argument must be of type ${type}. Received ${value}`);
+ err.code = "ERR_INVALID_ARG_TYPE";
+ return err;
+}
+
+function createTracing(opts) {
+ if (typeof opts !== "object" || opts == null) {
+ throw new ERR_INVALID_ARG_TYPE("options", "Object", opts);
+ }
+
+ // TODO: validate categories
+ return new Tracing(opts);
+}
+
+function getEnabledCategories() {
+ return "";
+}
+
+var defaultObject = {
+ createTracing,
+ getEnabledCategories,
+ [Symbol.for("CommonJS")]: 0,
+};
+
+export { defaultObject as default, createTracing, getEnabledCategories };
diff --git a/src/bun.js/v8.exports.js b/src/bun.js/v8.exports.js
new file mode 100644
index 000000000..4ac85fd3b
--- /dev/null
+++ b/src/bun.js/v8.exports.js
@@ -0,0 +1,166 @@
+// This is a stub! None of this is actually implemented yet.
+
+class TODO extends Error {
+ constructor(messageName) {
+ const message = messageName
+ ? `node:v8 ${messageName} is not implemented yet in Bun. `
+ : `node:v8 is not implemented yet in Bun`;
+ super(message);
+ this.name = "TODO";
+ }
+}
+
+function hideFromStack(fns) {
+ for (const fn of fns) {
+ Object.defineProperty(fn, "name", {
+ value: "::bunternal::",
+ });
+ }
+}
+
+function notimpl(message) {
+ throw new TODO(message);
+}
+
+class Deserializer {
+ constructor() {
+ notimpl();
+ }
+}
+class Serializer {
+ constructor() {
+ notimpl();
+ }
+}
+class DefaultDeserializer extends Deserializer {}
+class DefaultSerializer extends Serializer {}
+class GCProfiler {
+ constructor() {
+ notimpl();
+ }
+}
+
+function cachedDataVersionTag() {
+ notimpl("cachedDataVersionTag");
+}
+function getHeapSnapshot() {
+ notimpl("getHeapSnapshot");
+}
+function getHeapStatistics() {
+ notimpl("getHeapStatistics");
+}
+function getHeapSpaceStatistics() {
+ notimpl("getHeapSpaceStatistics");
+}
+function getHeapCodeStatistics() {
+ notimpl("getHeapCodeStatistics");
+}
+function setFlagsFromString() {
+ notimpl("setFlagsFromString");
+}
+function deserialize() {
+ notimpl("deserialize");
+}
+function takeCoverage() {
+ notimpl("takeCoverage");
+}
+function stopCoverage() {
+ notimpl("stopCoverage");
+}
+function serialize() {
+ notimpl("serialize");
+}
+function writeHeapSnapshot() {
+ notimpl("writeHeapSnapshot");
+}
+function setHeapSnapshotNearHeapLimit() {
+ notimpl("setHeapSnapshotNearHeapLimit");
+}
+const promiseHooks = {
+ createHook: () => {
+ notimpl("createHook");
+ },
+ onInit: () => {
+ notimpl("onInit");
+ },
+ onBefore: () => {
+ notimpl("onBefore");
+ },
+ onAfter: () => {
+ notimpl("onAfter");
+ },
+ onSettled: () => {
+ notimpl("onSettled");
+ },
+ },
+ startupSnapshot = {
+ addDeserializeCallback: () => notimpl("addDeserializeCallback"),
+ addSerializeCallback: () => notimpl("addSerializeCallback"),
+ setDeserializeMainFunction: () => notimpl("setDeserializeMainFunction"),
+ isBuildingSnapshot: () => notimpl("isBuildingSnapshot"),
+ };
+
+const defaultObject = {
+ cachedDataVersionTag,
+ getHeapSnapshot,
+ getHeapStatistics,
+ getHeapSpaceStatistics,
+ getHeapCodeStatistics,
+ setFlagsFromString,
+ deserialize,
+ takeCoverage,
+ stopCoverage,
+ serialize,
+ writeHeapSnapshot,
+ setHeapSnapshotNearHeapLimit,
+ promiseHooks,
+ startupSnapshot,
+ Deserializer,
+ Serializer,
+ [Symbol.for("CommonJS")]: 0,
+};
+
+export {
+ cachedDataVersionTag,
+ getHeapSnapshot,
+ getHeapStatistics,
+ getHeapSpaceStatistics,
+ getHeapCodeStatistics,
+ setFlagsFromString,
+ deserialize,
+ takeCoverage,
+ stopCoverage,
+ serialize,
+ writeHeapSnapshot,
+ setHeapSnapshotNearHeapLimit,
+ promiseHooks,
+ startupSnapshot,
+ Deserializer,
+ Serializer,
+ DefaultDeserializer,
+ DefaultSerializer,
+ GCProfiler,
+ defaultObject as default,
+};
+
+hideFromStack([
+ TODO.prototype.constructor,
+ notimpl,
+ cachedDataVersionTag,
+ getHeapSnapshot,
+ getHeapStatistics,
+ getHeapSpaceStatistics,
+ getHeapCodeStatistics,
+ setFlagsFromString,
+ deserialize,
+ takeCoverage,
+ stopCoverage,
+ serialize,
+ writeHeapSnapshot,
+ setHeapSnapshotNearHeapLimit,
+ Deserializer,
+ Serializer,
+ DefaultDeserializer,
+ DefaultSerializer,
+ GCProfiler,
+]);
diff --git a/src/bun.js/vm.exports.js b/src/bun.js/vm.exports.js
new file mode 100644
index 000000000..77fa31b01
--- /dev/null
+++ b/src/bun.js/vm.exports.js
@@ -0,0 +1,94 @@
+// TODO: Implement vm module
+
+function hideFromStack(fns) {
+ for (const fn of fns) {
+ Object.defineProperty(fn, "name", {
+ value: "::bunternal::",
+ });
+ }
+}
+
+class TODO extends Error {
+ constructor(messageName) {
+ const message = messageName
+ ? `node:vm ${messageName} is not implemented yet in Bun. Track the status & thumbs up the issue: https://github.com/oven-sh/bun/issues/401`
+ : `node:vm is not implemented yet in Bun. Track the status & thumbs up the issue: https://github.com/oven-sh/bun/issues/401`;
+ super(message);
+ this.name = "TODO";
+ }
+}
+
+function notimpl(message) {
+ throw new TODO(message);
+}
+
+function createContext() {
+ notimpl("createContext");
+}
+function createScript() {
+ notimpl("createScript");
+}
+function runInContext() {
+ notimpl("runInContext");
+}
+function runInNewContext() {
+ notimpl("runInNewContext");
+}
+function runInThisContext() {
+ notimpl("runInThisContext");
+}
+function isContext() {
+ notimpl("isContext");
+}
+function compileFunction() {
+ notimpl("compileFunction");
+}
+function measureMemory() {
+ notimpl("measureMemory");
+}
+
+class Script {
+ constructor() {
+ notimpl("Script");
+ }
+}
+
+const defaultObject = {
+ createContext,
+ createScript,
+ runInContext,
+ runInNewContext,
+ runInThisContext,
+ isContext,
+ compileFunction,
+ measureMemory,
+ Script,
+ [Symbol.for("CommonJS")]: 0,
+};
+
+export {
+ defaultObject as default,
+ createContext,
+ createScript,
+ runInContext,
+ runInNewContext,
+ runInThisContext,
+ isContext,
+ compileFunction,
+ measureMemory,
+ Script,
+};
+
+hideFromStack([
+ TODO.prototype.constructor,
+ notimpl,
+ createContext,
+ createScript,
+ runInContext,
+ runInNewContext,
+ runInThisContext,
+ isContext,
+ compileFunction,
+ measureMemory,
+ Script.prototype.constructor,
+]);
diff --git a/test/js/node/stubs.test.js b/test/js/node/stubs.test.js
new file mode 100644
index 000000000..e6bce8aee
--- /dev/null
+++ b/test/js/node/stubs.test.js
@@ -0,0 +1,120 @@
+import { describe, expect, test } from "bun:test";
+
+const weirdInternalSpecifiers = [
+ "_http_agent",
+ "_http_client",
+ "_http_common",
+ "_http_incoming",
+ "_http_outgoing",
+ "_http_server",
+ "_stream_duplex",
+ "_stream_passthrough",
+ "_stream_readable",
+ "_stream_transform",
+ "_stream_wrap",
+ "_stream_writable",
+ "_tls_common",
+ "_tls_wrap",
+];
+
+// Check that all the node modules comply with the expected interface in bun
+var specifiers = [
+ "assert",
+ "assert/strict",
+ "async_hooks",
+ "buffer",
+ "child_process",
+ "cluster",
+ "console",
+ "constants",
+ "crypto",
+ "dgram",
+ "diagnostics_channel",
+ "dns",
+ "dns/promises",
+ "domain",
+ "events",
+ "fs",
+ "fs/promises",
+ "http",
+ "http2",
+ "https",
+ "inspector",
+ "inspector/promises",
+ "module",
+ "net",
+ "os",
+ "path",
+ "path/posix",
+ "path/win32",
+ "perf_hooks",
+ "process",
+ "punycode",
+ "querystring",
+ "readline",
+ "readline/promises",
+ "repl",
+ "stream",
+ "stream/consumers",
+ "stream/promises",
+ "stream/web",
+ "string_decoder",
+ "sys",
+ "timers",
+ "timers/promises",
+ "tls",
+ "trace_events",
+ "tty",
+ "url",
+ "util",
+ "util/types",
+ "v8",
+ "vm",
+ "worker_threads",
+ "zlib",
+];
+specifiers = [...weirdInternalSpecifiers, ...specifiers.flatMap(a => ["node:" + a, a])];
+
+for (let specifier of specifiers) {
+ test(`stubbed CJS import.meta.require ${specifier}`, async () => {
+ import.meta.require(specifier);
+ });
+
+ test(`stubbed CJS require ${specifier}`, async () => {
+ require(specifier);
+ });
+
+ test(`stubbed import ${specifier}`, async () => {
+ const mod = await import(specifier);
+ if ("default" in mod) {
+ expect(mod).toHaveProperty("default");
+ const cjs = mod.default[Symbol.for("CommonJS")];
+ if (typeof cjs !== "undefined") {
+ if (cjs === 1) {
+ expect(typeof mod.default).toBe("function");
+ } else if (cjs === true) {
+ expect(cjs).toBe(true);
+ if (typeof mod.default !== "undefined") {
+ expect(typeof mod.default).toBe("function");
+ }
+ }
+ }
+ }
+ });
+}
+
+// TODO: when node:vm is implemented, delete this test.
+test("node:vm", () => {
+ const { Script } = import.meta.require("node:vm");
+ try {
+ // **This line should appear in the stack trace**
+ // That way it shows the "real" line causing the issue
+ // Instead of several layers of wrapping
+ new Script("1 + 1");
+ throw new Error("unreacahble");
+ } catch (e) {
+ const msg = Bun.inspect(e);
+ expect(msg).not.toContain("node:vm:");
+ expect(msg).toContain("**This line should appear in the stack trace**");
+ }
+});