From 1defa63c737e11ac9133152cd085994cf07b4447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Tue, 24 Sep 2024 18:28:14 +0200 Subject: [PATCH] Add version to navigator.userAgent (#542) A la Deno and Bun. --- qjs.c | 18 +++++++++++++++--- quickjs.h | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/qjs.c b/qjs.c index 89aadce..5631543 100644 --- a/qjs.c +++ b/qjs.c @@ -137,13 +137,20 @@ static JSValue js_gc(JSContext *ctx, JSValue this_val, return JS_UNDEFINED; } -static const JSCFunctionListEntry navigator_obj[] = { - JS_PROP_STRING_DEF("userAgent", "quickjs-ng", JS_PROP_ENUMERABLE), +static JSValue js_navigator_get_userAgent(JSContext *ctx, JSValue this_val) +{ + char version[32]; + snprintf(version, sizeof(version), "quickjs-ng/%s", JS_GetVersion()); + return JS_NewString(ctx, version); +} + +static const JSCFunctionListEntry navigator_proto_funcs[] = { + JS_CGETSET_DEF2("userAgent", js_navigator_get_userAgent, NULL, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE), + JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Navigator", JS_PROP_CONFIGURABLE), }; static const JSCFunctionListEntry global_obj[] = { JS_CFUNC_DEF("gc", 0, js_gc), - JS_OBJECT_DEF("navigator", navigator_obj, countof(navigator_obj), JS_PROP_C_W_E), #if defined(__ASAN__) || defined(__UBSAN__) JS_PROP_INT32_DEF("__running_with_sanitizer__", 1, JS_PROP_C_W_E ), #endif @@ -164,7 +171,12 @@ static JSContext *JS_NewCustomContext(JSRuntime *rt) JSValue global = JS_GetGlobalObject(ctx); JS_SetPropertyFunctionList(ctx, global, global_obj, countof(global_obj)); JS_SetPropertyFunctionList(ctx, global, &argv0, 1); + JSValue navigator_proto = JS_NewObject(ctx); + JS_SetPropertyFunctionList(ctx, navigator_proto, navigator_proto_funcs, countof(navigator_proto_funcs)); + JSValue navigator = JS_NewObjectProto(ctx, navigator_proto); + JS_DefinePropertyValueStr(ctx, global, "navigator", navigator, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE); JS_FreeValue(ctx, global); + JS_FreeValue(ctx, navigator_proto); return ctx; } diff --git a/quickjs.h b/quickjs.h index 5c132b0..4954705 100644 --- a/quickjs.h +++ b/quickjs.h @@ -982,6 +982,7 @@ typedef struct JSCFunctionListEntry { #define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } } #define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } } #define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } +#define JS_CGETSET_DEF2(name, fgetter, fsetter, prop_flags) { name, prop_flags, JS_DEF_CGETSET, 0, { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } #define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } } #define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, { .str = cstr } } #define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, { .i32 = val } }