diff options
Diffstat (limited to '')
-rw-r--r-- | src/__global.zig | 8 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 48 | ||||
-rw-r--r-- | src/bun.js/bindings/headers-handwritten.h | 2 | ||||
-rw-r--r-- | test/bun.js/web-globals.test.js | 8 |
4 files changed, 66 insertions, 0 deletions
diff --git a/src/__global.zig b/src/__global.zig index 6695f8a2d..e728d66ac 100644 --- a/src/__global.zig +++ b/src/__global.zig @@ -158,3 +158,11 @@ pub const BunInfo = struct { return try JSON.toAST(allocator, BunInfo, info); } }; + +pub const user_agent = "Bun/" ++ Global.package_json_version; + +pub export const Bun__userAgent: [*:0]const u8 = Global.user_agent; + +comptime { + _ = Bun__userAgent; +} diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index bb1a72767..706d38135 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -163,6 +163,13 @@ using JSBuffer = WebCore::JSBuffer; #include "DOMJITHelpers.h" #include <JavaScriptCore/DFGAbstractHeap.h> +#ifdef __APPLE__ +#include <sys/sysctl.h> +#else +// for sysconf +#include <unistd.h> +#endif + // #include <iostream> static bool has_loaded_jsc = false; @@ -1867,6 +1874,31 @@ void GlobalObject::finishCreation(VM& vm) init.set(JSModuleNamespaceObject::createStructure(init.vm, init.owner, init.owner->objectPrototype())); }); + m_navigatorObject.initLater( + [](const Initializer<JSObject>& init) { + int cpuCount = 0; +#ifdef __APPLE__ + size_t count_len = sizeof(cpuCount); + sysctlbyname("hw.logicalcpu", &cpuCount, &count_len, NULL, 0); +#else + // TODO: windows + cpuCount = sysconf(_SC_NPROCESSORS_ONLN); +#endif + + auto str = WTF::String::fromUTF8(Bun__userAgent); + JSC::Identifier userAgentIdentifier = JSC::Identifier::fromString(init.vm, "userAgent"_s); + JSC::Identifier hardwareConcurrencyIdentifier = JSC::Identifier::fromString(init.vm, "hardwareConcurrency"_s); + + JSC::JSObject* obj = JSC::constructEmptyObject(init.owner, init.owner->objectPrototype(), 3); + obj->putDirect(init.vm, userAgentIdentifier, JSC::jsString(init.vm, str)); + obj->putDirect(init.vm, init.vm.propertyNames->toStringTagSymbol, + jsNontrivialString(init.vm, "Navigator"_s), JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::ReadOnly); + + obj->putDirect(init.vm, hardwareConcurrencyIdentifier, JSC::jsNumber(cpuCount)); + init.set( + obj); + }); + this->m_pendingVirtualModuleResultStructure.initLater( [](const Initializer<Structure>& init) { init.set(Bun::PendingVirtualModuleResult::createStructure(init.vm, init.owner, init.owner->objectPrototype())); @@ -2081,6 +2113,18 @@ EncodedJSValue GlobalObject::assignToStream(JSValue stream, JSValue controller) return JSC::JSValue::encode(result); } +JSC::JSObject* GlobalObject::navigatorObject() +{ + return this->m_navigatorObject.get(this); +} + +JSC_DEFINE_CUSTOM_GETTER(functionLazyNavigatorGetter, + (JSC::JSGlobalObject * globalObject, JSC::EncodedJSValue thisValue, + JSC::PropertyName)) +{ + return JSC::JSValue::encode(reinterpret_cast<Zig::GlobalObject*>(globalObject)->navigatorObject()); +} + void GlobalObject::addBuiltinGlobals(JSC::VM& vm) { m_builtinInternalFunctions.initialize(*this); @@ -2229,6 +2273,9 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm) putDirectCustomAccessor(vm, builtinNames.lazyStreamPrototypeMapPrivateName(), JSC::CustomGetterSetter::create(vm, functionLazyLoadStreamPrototypeMap_getter, nullptr), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | 0); + putDirectCustomAccessor(vm, JSC::Identifier::fromString(vm, "navigator"_s), JSC::CustomGetterSetter::create(vm, functionLazyNavigatorGetter, nullptr), + JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | 0); + putDirect(vm, builtinNames.requireMapPrivateName(), this->requireMap(), JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly | 0); @@ -2533,6 +2580,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) thisObject->m_processEnvObject.visit(visitor); thisObject->m_processObject.visit(visitor); thisObject->m_performanceObject.visit(visitor); + thisObject->m_navigatorObject.visit(visitor); visitor.append(thisObject->m_JSBufferSetterValue); visitor.append(thisObject->m_JSTextEncoderSetterValue); diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index 36678e22e..f1716c7fd 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -206,6 +206,8 @@ enum SyntheticModuleType : uint64_t { Module = 1028, }; +extern "C" const char* Bun__userAgent; + extern "C" ZigErrorCode Zig_ErrorCodeParserError; extern "C" void ZigString__free(const unsigned char* ptr, size_t len, void* allocator); diff --git a/test/bun.js/web-globals.test.js b/test/bun.js/web-globals.test.js index 70c2f01e5..98157a785 100644 --- a/test/bun.js/web-globals.test.js +++ b/test/bun.js/web-globals.test.js @@ -105,3 +105,11 @@ it("URL.prototype.origin", () => { expect(host).toBe("html.spec.whatwg.org"); expect(origin).toBe("https://html.spec.whatwg.org"); }); + +test("navigator", () => { + expect(globalThis.navigator !== undefined).toBe(true); + const { version } = process; + const userAgent = `Bun/${version.substring(1)}`; + expect(navigator.hardwareConcurrency > 0).toBe(true); + expect(navigator.userAgent).toBe(userAgent); +}); |