Skip to content

Commit c67022a

Browse files
committed
feat: add qbc cli to compileJsToBytecode
1 parent be4149a commit c67022a

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ add_executable(qjs
7373
)
7474
target_link_libraries(qjs quickjs ${LINK_LIBRARIES} mimalloc-static)
7575

76+
# build qbc (new quickjs bytecode compiler)
77+
add_executable(qbc
78+
src/cli/qbc.c
79+
)
80+
target_link_libraries(qbc quickjs ${LINK_LIBRARIES} mimalloc-static)
81+
7682
# build run-test262 (quickjs test262 runner)
7783
add_executable(run-test262
7884
src/cli/run-test262.c

src/cli/qbc.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include "quickjs/quickjs.h"
5+
6+
char *change_extension(const char *path, const char *new_ext) {
7+
char *dot = strrchr(path, '.');
8+
if (dot == NULL) {
9+
dot = path + strlen(path); // append at the end if there's no extension
10+
}
11+
size_t new_path_len = dot - path + strlen(new_ext) + 1; // +1 for null terminator
12+
char *new_path = malloc(new_path_len);
13+
strncpy(new_path, path, dot - path);
14+
strcpy(new_path + (dot - path), new_ext);
15+
return new_path;
16+
}
17+
18+
int main(int argc, char *argv[]) {
19+
if (argc < 2 || argc > 3) {
20+
printf("Usage: %s <source.js> [<output.qbc>]\n", argv[0]);
21+
return 1;
22+
}
23+
24+
const char *source_path = argv[1];
25+
char *output_path;
26+
if (argc == 3) {
27+
output_path = argv[2];
28+
} else {
29+
output_path = change_extension(source_path, ".qbc");
30+
}
31+
32+
FILE *source_file = fopen(source_path, "r");
33+
if (source_file == NULL) {
34+
printf("Cannot open source file: %s\n", source_path);
35+
return 1;
36+
}
37+
38+
// get file length
39+
fseek(source_file, 0, SEEK_END);
40+
long length = ftell(source_file);
41+
fseek(source_file, 0, SEEK_SET);
42+
43+
// read source code into buffer
44+
char *source = malloc(length);
45+
if (source) {
46+
fread(source, 1, length, source_file);
47+
}
48+
fclose(source_file);
49+
50+
JSRuntime *rt;
51+
JSContext *ctx;
52+
53+
rt = JS_NewRuntime();
54+
ctx = JS_NewContext(rt);
55+
56+
// compile source code to bytecode
57+
JSValue bytecode = JS_Eval(ctx, source, length, source_path, JS_EVAL_FLAG_COMPILE_ONLY);
58+
59+
free(source);
60+
61+
if (JS_IsException(bytecode)) {
62+
printf("Compilation failed.\n");
63+
JS_FreeValue(ctx, bytecode);
64+
JS_FreeContext(ctx);
65+
JS_FreeRuntime(rt);
66+
return 1;
67+
}
68+
69+
// write bytecode to buffer
70+
size_t bytecode_length;
71+
uint8_t *buffer = JS_WriteObject(ctx, &bytecode_length, bytecode, JS_WRITE_OBJ_BYTECODE);
72+
73+
JS_FreeValue(ctx, bytecode);
74+
75+
// write buffer to binary file
76+
FILE *output_file = fopen(output_path, "wb");
77+
if (output_file == NULL) {
78+
printf("Cannot open output file: %s\n", output_path);
79+
JS_FreeContext(ctx);
80+
JS_FreeRuntime(rt);
81+
return 1;
82+
}
83+
84+
fwrite(buffer, 1, bytecode_length, output_file);
85+
fclose(output_file);
86+
87+
js_free(ctx, buffer);
88+
JS_FreeContext(ctx);
89+
JS_FreeRuntime(rt);
90+
91+
printf("Bytecode has been written to: %s\n", output_path);
92+
93+
if (argc == 2) {
94+
free(output_path);
95+
}
96+
return 0;
97+
}

0 commit comments

Comments
 (0)