From bde4cc70bd4eaf2c55e3fdbd3da479a8f9481ad8 Mon Sep 17 00:00:00 2001 From: Lily Skye Date: Mon, 12 Aug 2024 16:51:27 -0600 Subject: [PATCH] more wip, pulling inspect out of libc --- examples/logging.js | 5 +++ src/archives/core.ninja.js | 2 + src/archives/quickjs-full-init.c | 12 ++++-- src/archives/quickjs-full-init.h | 2 + src/inspect/inspect.ninja.js | 26 ------------ src/qjsbootstrap/qjsbootstrap.c | 1 + src/qjsc/qjsc.c | 8 ++-- src/qjsc/qjsc.js | 10 ++--- src/{inspect => quickjs-inspect}/inspect.js | 0 src/quickjs-inspect/quickjs-inspect.c | 10 +++++ .../quickjs-inspect.d.ts} | 0 src/quickjs-inspect/quickjs-inspect.h | 9 ++++ src/quickjs-inspect/quickjs-inspect.ninja.js | 41 +++++++++++++++++++ src/quickjs-libc/quickjs-libc.c | 21 +++------- src/quickjs-libc/quickjs-libc.h | 6 +-- src/quickjs-libcontext/quickjs-libcontext.c | 3 +- tests/inspect.test.ts | 31 ++++++++++++++ tests/print.test.ts | 20 +++++++++ 18 files changed, 148 insertions(+), 59 deletions(-) create mode 100644 examples/logging.js delete mode 100644 src/inspect/inspect.ninja.js rename src/{inspect => quickjs-inspect}/inspect.js (100%) create mode 100644 src/quickjs-inspect/quickjs-inspect.c rename src/{inspect/inspect.d.ts => quickjs-inspect/quickjs-inspect.d.ts} (100%) create mode 100644 src/quickjs-inspect/quickjs-inspect.h create mode 100644 src/quickjs-inspect/quickjs-inspect.ninja.js create mode 100644 tests/inspect.test.ts create mode 100644 tests/print.test.ts diff --git a/examples/logging.js b/examples/logging.js new file mode 100644 index 000000000..7b63f32b4 --- /dev/null +++ b/examples/logging.js @@ -0,0 +1,5 @@ +print("print", 1, {}); +console.log("console.log", 2, {}); +console.warn("console.warn", 3, {}); +console.error("console.error", 4, {}); +console.info("console.info", 5, {}); diff --git a/src/archives/core.ninja.js b/src/archives/core.ninja.js index c92d24078..175b0e65b 100644 --- a/src/archives/core.ninja.js +++ b/src/archives/core.ninja.js @@ -8,6 +8,7 @@ const deps_host = [ builddir("intermediate/quickjs-utils.host.o"), builddir("intermediate/quickjs-modulesys.host.o"), builddir("intermediate/quickjs-print.host.o"), + builddir("intermediate/quickjs-inspect.host.o"), ]; const deps_target = [ @@ -20,6 +21,7 @@ const deps_target = [ builddir("intermediate/quickjs-utils.target.o"), builddir("intermediate/quickjs-modulesys.target.o"), builddir("intermediate/quickjs-print.target.o"), + builddir("intermediate/quickjs-inspect.target.o"), ]; const core_host = build({ diff --git a/src/archives/quickjs-full-init.c b/src/archives/quickjs-full-init.c index 6c301f984..c40d37990 100644 --- a/src/archives/quickjs-full-init.c +++ b/src/archives/quickjs-full-init.c @@ -1,8 +1,5 @@ #include "quickjs-full-init.h" -extern const uint8_t qjsc_inspect[]; -extern const uint32_t qjsc_inspect_size; - /* returns 0 on success, nonzero on failure */ static int quickjs_full_init_modules(JSContext *ctx) { @@ -33,7 +30,14 @@ static int quickjs_full_init_modules(JSContext *ctx) static int quickjs_full_init_globals(JSContext *ctx) { - return QJMS_EvalBinary(ctx, qjsc_inspect, qjsc_inspect_size, 0); + if (js_inspect_add_inspect_global(ctx)) { + return -1; + } + + js_print_add_print_global(ctx); + js_print_add_console_global(ctx); + + return 0; } int quickjs_full_init(JSContext *ctx) diff --git a/src/archives/quickjs-full-init.h b/src/archives/quickjs-full-init.h index 1e71df94f..a41a4a0ad 100644 --- a/src/archives/quickjs-full-init.h +++ b/src/archives/quickjs-full-init.h @@ -2,6 +2,8 @@ #define QUICKJS_FULL_INIT_H #include "quickjs.h" +#include "quickjs-print.h" +#include "quickjs-inspect.h" #include "quickjs-libc.h" #include "quickjs-libbytecode.h" #include "quickjs-libcontext.h" diff --git a/src/inspect/inspect.ninja.js b/src/inspect/inspect.ninja.js deleted file mode 100644 index d3785f966..000000000 --- a/src/inspect/inspect.ninja.js +++ /dev/null @@ -1,26 +0,0 @@ -const inspect_c = build({ - output: builddir("intermediate/inspect.c"), - rule: "qjsc", - inputs: [rel("inspect.js")], - ruleVariables: { - qjsc_args: `-c -m`, - }, -}); - -build({ - output: builddir("intermediate/inspect.target.o"), - rule: "cc_target", - inputs: [inspect_c], -}); - -build({ - output: builddir("intermediate/inspect.host.o"), - rule: "cc_host", - inputs: [inspect_c], -}); - -build({ - output: builddir("dts/inspect.d.ts"), - rule: "copy", - inputs: [rel("inspect.d.ts")], -}); diff --git a/src/qjsbootstrap/qjsbootstrap.c b/src/qjsbootstrap/qjsbootstrap.c index 38306335e..0ae83f728 100644 --- a/src/qjsbootstrap/qjsbootstrap.c +++ b/src/qjsbootstrap/qjsbootstrap.c @@ -37,6 +37,7 @@ __static_yoink("blink_xnu_aarch64"); #include "execpath.h" #include "cutils.h" #include "quickjs-utils.h" +#include "quickjs-print.h" #include "quickjs-modulesys.h" #include "quickjs-full-init.h" diff --git a/src/qjsc/qjsc.c b/src/qjsc/qjsc.c index c6df8088f..985a029aa 100644 --- a/src/qjsc/qjsc.c +++ b/src/qjsc/qjsc.c @@ -43,6 +43,7 @@ __static_yoink("blink_xnu_aarch64"); #include "quickjs-modulesys.h" #include "debugprint.h" +// TODO: clean this up // Stub out inspect, intervals, and string-dedent, which we can't rely on in // qjsc, because those are built with qjsc const uint32_t qjsc_inspect_size = 0; @@ -687,6 +688,7 @@ int main(int argc, char **argv) if (output_type != OUTPUT_C) { fprintf(fo, "#include \"quickjs-libc.h\"\n" "#include \"quickjs-utils.h\"\n" + "#include \"quickjs-print.h\"\n" "#include \"quickjs-modulesys.h\"\n" "\n" ); @@ -753,9 +755,7 @@ int main(int argc, char **argv) fprintf(fo, " {\n" - " extern const uint8_t qjsc_inspect[];\n" - " extern const uint32_t qjsc_inspect_size;\n" - " QJMS_EvalBinary(ctx, qjsc_inspect, qjsc_inspect_size, 0);\n" + " \n" " }\n"); for(i = 0; i < cname_list.count; i++) { @@ -784,6 +784,8 @@ int main(int argc, char **argv) fprintf(fo, " ctx = JS_NewCustomContext(rt);\n" " js_std_add_helpers(ctx, argc, argv);\n" + " js_print_add_print_global(ctx);\n" + " js_print_add_console_global(ctx);\n" " QJMS_InitContext(ctx);\n"); for(i = 0; i < cname_list.count; i++) { diff --git a/src/qjsc/qjsc.js b/src/qjsc/qjsc.js index ff1874af2..7de806002 100644 --- a/src/qjsc/qjsc.js +++ b/src/qjsc/qjsc.js @@ -161,6 +161,8 @@ function main(args) { case "programSource": { out += '#include "quickjs-libc.h"\n'; out += '#include "quickjs-utils.h"\n'; + out += '#include "quickjs-print.h"\n'; + out += '#include "quickjs-inspect.h"\n'; out += '#include "quickjs-modulesys.h"\n'; out += "\n\n"; @@ -202,11 +204,7 @@ function main(args) { out += " }\n"; } - out += " {\n"; - out += " extern const uint8_t qjsc_inspect[];\n"; - out += " extern const uint32_t qjsc_inspect_size;\n"; - out += " QJMS_EvalBinary(ctx, qjsc_inspect, qjsc_inspect_size, 0);\n"; - out += " }\n"; + out += " js_inspect_add_inspect_global(ctx);\n"; out += " return ctx;\n"; out += "}\n\n"; @@ -227,6 +225,8 @@ function main(args) { out += " QJMS_InitState(rt);\n"; out += " ctx = JS_NewCustomContext(rt);\n"; out += " js_std_add_helpers(ctx, argc, argv);\n"; + out += " js_print_add_print_global(ctx);\n"; + out += " js_print_add_console_global(ctx);\n"; out += " QJMS_InitContext(ctx);\n"; // This is where we actually load the compiled bytecode diff --git a/src/inspect/inspect.js b/src/quickjs-inspect/inspect.js similarity index 100% rename from src/inspect/inspect.js rename to src/quickjs-inspect/inspect.js diff --git a/src/quickjs-inspect/quickjs-inspect.c b/src/quickjs-inspect/quickjs-inspect.c new file mode 100644 index 000000000..7373928a2 --- /dev/null +++ b/src/quickjs-inspect/quickjs-inspect.c @@ -0,0 +1,10 @@ +#include "quickjs-inspect.h" +#include "quickjs-modulesys.h" + +extern const uint8_t qjsc_inspect[]; +extern const uint32_t qjsc_inspect_size; + +int js_inspect_add_inspect_global(JSContext *ctx) +{ + return QJMS_EvalBinary(ctx, qjsc_inspect, qjsc_inspect_size, 0); +} diff --git a/src/inspect/inspect.d.ts b/src/quickjs-inspect/quickjs-inspect.d.ts similarity index 100% rename from src/inspect/inspect.d.ts rename to src/quickjs-inspect/quickjs-inspect.d.ts diff --git a/src/quickjs-inspect/quickjs-inspect.h b/src/quickjs-inspect/quickjs-inspect.h new file mode 100644 index 000000000..1e7ad131c --- /dev/null +++ b/src/quickjs-inspect/quickjs-inspect.h @@ -0,0 +1,9 @@ +#ifndef QUICKJS_INSPECT_H +#define QUICKJS_INSPECT_H + +#include "quickjs.h" + +/* Adds 'inspect' global */ +int js_inspect_add_inspect_global(JSContext *ctx); + +#endif /* ifndef QUICKJS_INSPECT_H */ diff --git a/src/quickjs-inspect/quickjs-inspect.ninja.js b/src/quickjs-inspect/quickjs-inspect.ninja.js new file mode 100644 index 000000000..9d163f64b --- /dev/null +++ b/src/quickjs-inspect/quickjs-inspect.ninja.js @@ -0,0 +1,41 @@ +// The C helper function for adding the global +build({ + output: builddir("intermediate/quickjs-inspect.host.o"), + rule: "cc_host", + inputs: [rel("quickjs-inspect.c")], +}); + +build({ + output: builddir("intermediate/quickjs-inspect.target.o"), + rule: "cc_target", + inputs: [rel("quickjs-inspect.c")], +}); + +// C bytecode file generated from js +const inspect_c = build({ + output: builddir("intermediate/inspect.c"), + rule: "qjsc", + inputs: [rel("inspect.js")], + ruleVariables: { + qjsc_args: `-c -m`, + }, +}); + +// The compiled objects containing the bytecode +build({ + output: builddir("intermediate/inspect.host.o"), + rule: "cc_host", + inputs: [inspect_c], +}); + +build({ + output: builddir("intermediate/inspect.target.o"), + rule: "cc_target", + inputs: [inspect_c], +}); + +build({ + output: builddir("dts/quickjs-inspect.d.ts"), + rule: "copy", + inputs: [rel("quickjs-inspect.d.ts")], +}); diff --git a/src/quickjs-libc/quickjs-libc.c b/src/quickjs-libc/quickjs-libc.c index 6715ffeef..3fd111627 100644 --- a/src/quickjs-libc/quickjs-libc.c +++ b/src/quickjs-libc/quickjs-libc.c @@ -75,9 +75,6 @@ sighandler_t signal(int signum, sighandler_t handler); #include #endif -extern const uint8_t qjsc_inspect[]; -extern const uint32_t qjsc_inspect_size; - extern const uint8_t qjsc_intervals[]; extern const uint32_t qjsc_intervals_size; @@ -89,7 +86,6 @@ extern const uint32_t qjsc_string_dedent_size; #include "quickjs-libc.h" #include "quickjs-utils.h" #include "quickjs-modulesys.h" -#include "quickjs-print.h" #include "debugprint.h" #include "execpath.h" @@ -3914,6 +3910,12 @@ static void *worker_func(void *opaque) JS_SetCanBlock(rt, TRUE); js_std_add_helpers(ctx, -1, NULL); + // TODO: print and console should go here, but I want to untangle libc from + // the rest, so I don't want libc to depend on print right now + // + // js_print_add_print_global(ctx); + // js_print_add_console_global(ctx); + // js_inspect_add_inspect_global(ctx); QJMS_InitContext(ctx); if (!JS_RunModule(ctx, args->basename, args->filename)) @@ -4371,11 +4373,6 @@ JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name) /**********************************************************/ -void js_std_add_inspect(JSContext *ctx) -{ - QJMS_EvalBinary(ctx, qjsc_inspect, qjsc_inspect_size, 0); -} - void js_std_add_scriptArgs(JSContext *ctx, int argc, char **argv) { JSValue global_obj, args; @@ -4426,13 +4423,7 @@ void js_std_add_string_dedent(JSContext *ctx) /**/ void js_std_add_helpers(JSContext *ctx, int argc, char **argv) { - js_std_add_inspect(ctx); - js_print_add_console_global(ctx); - - /* scriptArgs and print are the same as in the mozilla JS shell */ - js_print_add_print_global(ctx); js_std_add_scriptArgs(ctx, argc, argv); - js_std_add_timeout(ctx); js_std_add_intervals(ctx); js_std_add_string_dedent(ctx); diff --git a/src/quickjs-libc/quickjs-libc.h b/src/quickjs-libc/quickjs-libc.h index af34d0aaf..f6416baae 100644 --- a/src/quickjs-libc/quickjs-libc.h +++ b/src/quickjs-libc/quickjs-libc.h @@ -38,14 +38,10 @@ extern "C" JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); /* - Creates 'inspect', 'console', 'print', 'scriptArgs', 'setTimeout', - 'setInterval', and 'String.dedent'. + Creates 'scriptArgs', 'setTimeout', 'setInterval', and 'String.dedent'. */ void js_std_add_helpers(JSContext *ctx, int argc, char **argv); - /* Creates 'inspect' global */ - void js_std_add_inspect(JSContext *ctx); - /* Creates 'scriptArgs' global */ void js_std_add_scriptArgs(JSContext *ctx, int argc, char **argv); diff --git a/src/quickjs-libcontext/quickjs-libcontext.c b/src/quickjs-libcontext/quickjs-libcontext.c index 0da5565b4..583e84d77 100644 --- a/src/quickjs-libcontext/quickjs-libcontext.c +++ b/src/quickjs-libcontext/quickjs-libcontext.c @@ -7,6 +7,7 @@ #include "quickjs-libengine.h" #include "quickjs-libcontext.h" #include "quickjs-print.h" +#include "quickjs-inspect.h" static JSClassID js_context_class_id; @@ -260,7 +261,7 @@ static JSValue js_context_ctor(JSContext *ctx, JSValueConst this_val, } if (inspect) { - js_std_add_inspect(target_ctx); + js_inspect_add_inspect_global(target_ctx); } if (console) { js_print_add_console_global(target_ctx); diff --git a/tests/inspect.test.ts b/tests/inspect.test.ts new file mode 100644 index 000000000..e9a17714d --- /dev/null +++ b/tests/inspect.test.ts @@ -0,0 +1,31 @@ +import { spawn } from "first-base"; +import { binDir, rootDir } from "./_utils"; + +test("inspect", async () => { + const run = spawn(binDir("qjs"), [ + "-e", + ` + const obj = { + something: { + theSomething: true, + } + } + + print(inspect(obj)); + `, + ]); + await run.completion; + expect(run.result).toMatchInlineSnapshot(` + { + "code": 0, + "error": false, + "stderr": "", + "stdout": "{ + something: { + theSomething: true + } + } + ", + } + `); +}); diff --git a/tests/print.test.ts b/tests/print.test.ts new file mode 100644 index 000000000..12ed9b250 --- /dev/null +++ b/tests/print.test.ts @@ -0,0 +1,20 @@ +import { spawn } from "first-base"; +import { binDir, rootDir } from "./_utils"; + +test("quickjs-print", async () => { + const run = spawn(binDir("qjs"), [rootDir("examples/logging.js")]); + await run.completion; + expect(run.result).toMatchInlineSnapshot(` + { + "code": 0, + "error": false, + "stderr": "console.warn 3 [object Object] + console.error 4 [object Object] + ", + "stdout": "print 1 [object Object] + console.log 2 [object Object] + console.info 5 [object Object] + ", + } + `); +});