diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index b6dc6d4e96..1c88daabdc 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -171,7 +171,7 @@ static JSValue constructVersions(VM& vm, JSObject* processObject) object->putDirect(vm, JSC::Identifier::fromString(vm, "usockets"_s), JSC::JSValue(JSC::jsString(vm, makeString(Bun__versions_usockets))), 0); - object->putDirect(vm, JSC::Identifier::fromString(vm, "v8"_s), JSValue(JSC::jsString(vm, makeString("11.3.244.8-node.15"_s))), 0); + object->putDirect(vm, JSC::Identifier::fromString(vm, "v8"_s), JSValue(JSC::jsString(vm, String("11.3.244.8-node.15"_s))), 0); #if OS(WINDOWS) object->putDirect(vm, JSC::Identifier::fromString(vm, "uv"_s), JSValue(JSC::jsString(vm, makeString(uv_version_string()))), 0); #else @@ -224,19 +224,6 @@ static void dispatchExitInternal(JSC::JSGlobalObject* globalObject, Process* pro emitter.emit(event, arguments); } -JSC_DEFINE_CUSTOM_SETTER(Process_defaultSetter, - (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, - JSC::EncodedJSValue value, JSC::PropertyName propertyName)) -{ - JSC::VM& vm = globalObject->vm(); - - JSC::JSObject* thisObject = JSC::jsDynamicCast(JSValue::decode(thisValue)); - if (value) - thisObject->putDirect(vm, propertyName, JSValue::decode(value), 0); - - return true; -} - extern "C" bool Bun__resolveEmbeddedNodeFile(void*, BunString*); JSC_DECLARE_HOST_FUNCTION(Process_functionDlopen); @@ -1485,28 +1472,10 @@ static JSValue constructProcessReportObject(VM& vm, JSObject* processObject) static JSValue constructProcessConfigObject(VM& vm, JSObject* processObject) { auto* globalObject = processObject->globalObject(); - // target_defaults: - // { cflags: [], - // default_configuration: 'Release', - // defines: [], - // include_dirs: [], - // libraries: [] }, - // variables: - // { - // host_arch: 'x64', - // napi_build_version: 5, - // node_install_npm: 'true', - // node_prefix: '', - // node_shared_cares: 'false', - // node_shared_http_parser: 'false', - // node_shared_libuv: 'false', - // node_shared_zlib: 'false', - // node_use_openssl: 'true', - // node_shared_openssl: 'false', - // strict_aliasing: 'true', - // target_arch: 'x64', - // v8_use_snapshot: 1 - // } + // target_defaults: {}, + // variables: { + // v8_enable_i18n_support: 1, + // }, // } JSC::JSObject* config = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 2); JSC::JSObject* variables = JSC::constructEmptyObject(globalObject, globalObject->objectPrototype(), 1); @@ -1514,7 +1483,6 @@ static JSValue constructProcessConfigObject(VM& vm, JSObject* processObject) JSC::jsNumber(1), 0); config->putDirect(vm, JSC::Identifier::fromString(vm, "target_defaults"_s), JSC::constructEmptyObject(globalObject), 0); config->putDirect(vm, JSC::Identifier::fromString(vm, "variables"_s), variables, 0); - return config; } @@ -1766,17 +1734,57 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionAssert, (JSGlobalObject * globalObject, return JSValue::encode(jsUndefined()); } -#define PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE(str, issue) \ - { \ - throwScope.throwException(globalObject, createError(globalObject, String("process.binding(\"" str "\") is not implemented in Bun. Track the status & thumbs up the issue: https://github.com/oven-sh/bun/issues/" issue ""_s))); \ - return JSValue::encode(JSValue {}); \ +inline JSC::EncodedJSValue createProcessBindingNotImplementedProxy( + JSC::JSGlobalObject* globalObject, + JSC::VM& vm, + WTF::String handlerGetTrapCode) +{ + auto* nullProtoStruct = globalObject->nullPrototypeObjectStructure(); + auto&& origin = SourceOrigin(WTF::URL()); + auto* target = JSC::constructEmptyObject(vm, nullProtoStruct); + auto* handler = JSC::constructEmptyObject(vm, nullProtoStruct); + SourceCode handlerGetTrapSourceCode + = JSC::makeSource( + handlerGetTrapCode, + origin, + JSC::SourceTaintedOrigin::Untainted); + JSFunction* func + = JSFunction::create( + vm, + JSC::createBuiltinExecutable( + vm, + handlerGetTrapSourceCode, + Identifier(), + ImplementationVisibility::Private, + ConstructorKind::None, + ConstructAbility::CannotConstruct, + InlineAttribute::None) + ->link(vm, nullptr, handlerGetTrapSourceCode), + static_cast(globalObject)); + handler->putDirect(vm, Identifier::fromString(vm, "get"_s), func, 0); + return JSValue::encode(ProxyObject::create(globalObject, target, handler)); +} +#define PROCESS_BINDING_NOT_IMPLEMENTED_1_ARGS(moduleName) \ + { \ + auto handlerGetTrapCode = String( \ + "(function (_target,propertyKey){" \ + "throw new Error(`process.binding(\"" moduleName "\").${propertyKey} is not implemented in Bun. If that breaks something, please file an issue and include a reproducible code sample.`)" \ + "})"_s); \ + return createProcessBindingNotImplementedProxy(globalObject, vm, handlerGetTrapCode); \ } - -#define PROCESS_BINDING_NOT_IMPLEMENTED(str) \ - { \ - throwScope.throwException(globalObject, createError(globalObject, String("process.binding(\"" str "\") is not implemented in Bun. If that breaks something, please file an issue and include a reproducible code sample."_s))); \ - return JSValue::encode(JSValue {}); \ +#define PROCESS_BINDING_NOT_IMPLEMENTED_2_ARGS(moduleName, issue) \ + { \ + auto handlerGetTrapCode = String( \ + "(function (_target,propertyKey){" \ + "throw new Error(`process.binding(\"" moduleName "\").${propertyKey} is not implemented in Bun. Track the status, thumbs up the issue, & report the binding property name: https://github.com/oven-sh/bun/issues/" issue ".`)" \ + "})"_s); \ + return createProcessBindingNotImplementedProxy(globalObject, vm, handlerGetTrapCode); \ } +#define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 +#define PROCESS_BINDING_NOT_IMPLEMENTED_MACRO_CHOOSER(...) \ + GET_3RD_ARG(__VA_ARGS__, PROCESS_BINDING_NOT_IMPLEMENTED_2_ARGS, \ + PROCESS_BINDING_NOT_IMPLEMENTED_1_ARGS) +#define PROCESS_BINDING_NOT_IMPLEMENTED(...) PROCESS_BINDING_NOT_IMPLEMENTED_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__) inline JSValue processBindingUtil(Zig::GlobalObject* globalObject, JSC::VM& vm) { @@ -1796,34 +1804,34 @@ inline JSValue processBindingConfig(Zig::GlobalObject* globalObject, JSC::VM& vm #else config->putDirect(vm, Identifier::fromString(vm, "isDebugBuild"_s), jsBoolean(false), 0); #endif - config->putDirect(vm, Identifier::fromString(vm, "hasOpenSSL"_s), jsBoolean(true), 0); - config->putDirect(vm, Identifier::fromString(vm, "fipsMode"_s), jsBoolean(true), 0); - config->putDirect(vm, Identifier::fromString(vm, "hasIntl"_s), jsBoolean(true), 0); - config->putDirect(vm, Identifier::fromString(vm, "hasTracing"_s), jsBoolean(true), 0); - config->putDirect(vm, Identifier::fromString(vm, "hasNodeOptions"_s), jsBoolean(true), 0); - config->putDirect(vm, Identifier::fromString(vm, "hasInspector"_s), jsBoolean(true), 0); - config->putDirect(vm, Identifier::fromString(vm, "noBrowserGlobals"_s), jsBoolean(false), 0); config->putDirect(vm, Identifier::fromString(vm, "bits"_s), jsNumber(64), 0); + config->putDirect(vm, Identifier::fromString(vm, "fipsMode"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "hasInspector"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "hasIntl"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "hasNodeOptions"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "hasOpenSSL"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "hasTracing"_s), jsBoolean(true), 0); + config->putDirect(vm, Identifier::fromString(vm, "noBrowserGlobals"_s), jsBoolean(false), 0); return config; } -JSC_DEFINE_HOST_FUNCTION(Process_functionBinding, (JSGlobalObject * jsGlobalObject, CallFrame* callFrame)) +JSC_DEFINE_HOST_FUNCTION(Process_functionBinding, (JSGlobalObject * globalObject, CallFrame* callFrame)) { - auto& vm = jsGlobalObject->vm(); + auto lexicalGlobalObject = jsCast(globalObject); + auto& vm = globalObject->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); - auto globalObject = jsCast(jsGlobalObject); - auto process = jsCast(globalObject->processObject()); auto moduleName = callFrame->argument(0).toWTFString(globalObject); + auto process = jsCast(lexicalGlobalObject->processObject()); // clang-format off if (moduleName == "async_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("async_wrap"); - if (moduleName == "buffer"_s) PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE("buffer", "2020"); + if (moduleName == "buffer"_s) PROCESS_BINDING_NOT_IMPLEMENTED("buffer", "2020"); if (moduleName == "cares_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("cares_wrap"); - if (moduleName == "config"_s) return JSValue::encode(processBindingConfig(globalObject, vm)); - if (moduleName == "constants"_s) return JSValue::encode(globalObject->processBindingConstants()); + if (moduleName == "config"_s) return JSValue::encode(processBindingConfig(lexicalGlobalObject, vm)); + if (moduleName == "constants"_s) return JSValue::encode(lexicalGlobalObject->processBindingConstants()); if (moduleName == "contextify"_s) PROCESS_BINDING_NOT_IMPLEMENTED("contextify"); if (moduleName == "crypto"_s) PROCESS_BINDING_NOT_IMPLEMENTED("crypto"); - if (moduleName == "fs"_s) PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE("fs", "3546"); + if (moduleName == "fs"_s) PROCESS_BINDING_NOT_IMPLEMENTED("fs", "3546"); if (moduleName == "fs_event_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("fs_event_wrap"); if (moduleName == "http_parser"_s) PROCESS_BINDING_NOT_IMPLEMENTED("http_parser"); if (moduleName == "icu"_s) PROCESS_BINDING_NOT_IMPLEMENTED("icu"); @@ -1835,13 +1843,13 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionBinding, (JSGlobalObject * jsGlobalObje if (moduleName == "process_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("process_wrap"); if (moduleName == "signal_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("signal_wrap"); if (moduleName == "spawn_sync"_s) PROCESS_BINDING_NOT_IMPLEMENTED("spawn_sync"); - if (moduleName == "stream_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED_ISSUE("stream_wrap", "4957"); + if (moduleName == "stream_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("stream_wrap", "4957"); if (moduleName == "tcp_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("tcp_wrap"); if (moduleName == "tls_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("tls_wrap"); if (moduleName == "tty_wrap"_s) return JSValue::encode(Bun::createNodeTTYWrapObject(globalObject)); if (moduleName == "udp_wrap"_s) PROCESS_BINDING_NOT_IMPLEMENTED("udp_wrap"); if (moduleName == "url"_s) PROCESS_BINDING_NOT_IMPLEMENTED("url"); - if (moduleName == "util"_s) return JSValue::encode(processBindingUtil(globalObject, vm)); + if (moduleName == "util"_s) return JSValue::encode(processBindingUtil(lexicalGlobalObject, vm)); if (moduleName == "uv"_s) return JSValue::encode(process->bindingUV()); if (moduleName == "v8"_s) PROCESS_BINDING_NOT_IMPLEMENTED("v8"); if (moduleName == "zlib"_s) PROCESS_BINDING_NOT_IMPLEMENTED("zlib"); diff --git a/src/bun.js/bindings/InternalModuleRegistry.cpp b/src/bun.js/bindings/InternalModuleRegistry.cpp index d14164b337..fc8ff2013f 100644 --- a/src/bun.js/bindings/InternalModuleRegistry.cpp +++ b/src/bun.js/bindings/InternalModuleRegistry.cpp @@ -33,7 +33,9 @@ static void maybeAddCodeCoverage(JSC::VM& vm, const JSC::SourceCode& code) #define INTERNAL_MODULE_REGISTRY_GENERATE_(globalObject, vm, SOURCE, moduleName, urlString) \ auto throwScope = DECLARE_THROW_SCOPE(vm); \ auto&& origin = SourceOrigin(WTF::URL(urlString)); \ - SourceCode source = JSC::makeSource(SOURCE, origin, \ + SourceCode source = JSC::makeSource( \ + SOURCE, \ + origin, \ JSC::SourceTaintedOrigin::Untainted, \ moduleName); \ maybeAddCodeCoverage(vm, source); \ @@ -41,7 +43,8 @@ static void maybeAddCodeCoverage(JSC::VM& vm, const JSC::SourceCode& code) = JSFunction::create( \ vm, \ createBuiltinExecutable( \ - vm, source, \ + vm, \ + source, \ Identifier(), \ ImplementationVisibility::Public, \ ConstructorKind::None, \ diff --git a/test/js/node/process-binding.test.ts b/test/js/node/process-binding.test.ts index c60a38bae0..b324c39509 100644 --- a/test/js/node/process-binding.test.ts +++ b/test/js/node/process-binding.test.ts @@ -1,4 +1,10 @@ describe("process.binding", () => { + test("process.binding() with unsupported module property access", () => { + /* @ts-ignore */ + const unsupported = process.binding("buffer"); + expect(() => unsupported.kMaxLength).toThrow(); + }); + test("process.binding('constants')", () => { /* @ts-ignore */ const constants = process.binding("constants"); @@ -9,6 +15,7 @@ describe("process.binding", () => { expect(constants).toHaveProperty("trace"); expect(constants).toHaveProperty("zlib"); }); + test("process.binding('uv')", () => { /* @ts-ignore */ const uv = process.binding("uv"); diff --git a/test/js/node/process/process.test.js b/test/js/node/process/process.test.js index ab70485302..6fc798da25 100644 --- a/test/js/node/process/process.test.js +++ b/test/js/node/process/process.test.js @@ -231,10 +231,6 @@ it("process.execArgv", () => { expect(process.execArgv instanceof Array).toBe(true); }); -it("process.binding", () => { - expect(() => process.binding("buffer")).toThrow(); -}); - it("process.argv in testing", () => { expect(process.argv).toBeInstanceOf(Array); expect(process.argv[0]).toBe(bunExe());