Retain function source code in serialized bytecode (#218)
Also fix a small memory leak in the output from `qjsc -e`. Fixes: https://github.com/quickjs-ng/quickjs/issues/217
This commit is contained in:
parent
7474b28036
commit
5cbf8727a6
7 changed files with 53 additions and 8 deletions
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
@ -109,6 +109,7 @@ jobs:
|
||||||
./build/qjs examples/test_fib.js
|
./build/qjs examples/test_fib.js
|
||||||
./build/qjs examples/test_point.js
|
./build/qjs examples/test_point.js
|
||||||
./build/qjs tests/test_bjson.js
|
./build/qjs tests/test_bjson.js
|
||||||
|
./build/function_source
|
||||||
linux-shared:
|
linux-shared:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
@ -213,6 +214,7 @@ jobs:
|
||||||
./build/qjs examples/test_fib.js
|
./build/qjs examples/test_fib.js
|
||||||
./build/qjs examples/test_point.js
|
./build/qjs examples/test_point.js
|
||||||
./build/qjs tests/test_bjson.js
|
./build/qjs tests/test_bjson.js
|
||||||
|
./build/function_source
|
||||||
macos-shared:
|
macos-shared:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
|
@ -261,6 +263,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
cmake -B build -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -G "Visual Studio 17 2022" -T ClangCL
|
cmake -B build -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -G "Visual Studio 17 2022" -T ClangCL
|
||||||
cmake --build build --target qjs_exe
|
cmake --build build --target qjs_exe
|
||||||
|
cmake --build build --target function_source
|
||||||
- name: stats
|
- name: stats
|
||||||
run: |
|
run: |
|
||||||
cmd /r build\Debug\qjs.exe -qd
|
cmd /r build\Debug\qjs.exe -qd
|
||||||
|
@ -274,6 +277,7 @@ jobs:
|
||||||
cmd /r build\Debug\qjs.exe tests\test_std.js
|
cmd /r build\Debug\qjs.exe tests\test_std.js
|
||||||
cmd /r build\Debug\qjs.exe tests\test_worker.js
|
cmd /r build\Debug\qjs.exe tests\test_worker.js
|
||||||
cmd /r build\Debug\qjs.exe tests\test_queue_microtask.js
|
cmd /r build\Debug\qjs.exe tests\test_queue_microtask.js
|
||||||
|
cmd /r build\Debug\function_source.exe
|
||||||
|
|
||||||
windows-mingw:
|
windows-mingw:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
|
@ -236,6 +236,21 @@ add_executable(unicode_gen EXCLUDE_FROM_ALL
|
||||||
)
|
)
|
||||||
target_compile_definitions(unicode_gen PRIVATE ${qjs_defines})
|
target_compile_definitions(unicode_gen PRIVATE ${qjs_defines})
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT function_source.c
|
||||||
|
COMMAND qjsc -e -o function_source.c ${CMAKE_CURRENT_SOURCE_DIR}/tests/function_source.js
|
||||||
|
DEPENDS qjsc ${CMAKE_CURRENT_SOURCE_DIR}/tests/function_source.js
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
COMMENT "Compile function_source.js to a C file with bytecode embedded"
|
||||||
|
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tests/function_source.js
|
||||||
|
)
|
||||||
|
add_executable(function_source
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/function_source.c
|
||||||
|
quickjs-libc.c
|
||||||
|
)
|
||||||
|
target_include_directories(function_source PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
target_compile_definitions(function_source PRIVATE ${qjs_defines})
|
||||||
|
target_link_libraries(function_source ${qjs_libs})
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
#
|
#
|
||||||
|
@ -246,7 +261,7 @@ if(BUILD_EXAMPLES AND NOT WIN32)
|
||||||
COMMAND qjsc -e -o hello.c ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello.js
|
COMMAND qjsc -e -o hello.c ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello.js
|
||||||
DEPENDS qjsc
|
DEPENDS qjsc
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMENT "Compile hello.js to a C file with bytecode embeddee"
|
COMMENT "Compile hello.js to a C file with bytecode embedded"
|
||||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello.js
|
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello.js
|
||||||
)
|
)
|
||||||
add_executable(hello
|
add_executable(hello
|
||||||
|
@ -262,7 +277,7 @@ if(BUILD_EXAMPLES AND NOT WIN32)
|
||||||
COMMAND qjsc -e -o hello_module.c -m ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello_module.js
|
COMMAND qjsc -e -o hello_module.c -m ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello_module.js
|
||||||
DEPENDS qjsc
|
DEPENDS qjsc
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMENT "Compile hello_module.js to a C file with bytecode embeddee"
|
COMMENT "Compile hello_module.js to a C file with bytecode embedded"
|
||||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello_module.js
|
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello_module.js
|
||||||
)
|
)
|
||||||
add_executable(hello_module
|
add_executable(hello_module
|
||||||
|
|
4
cutils.c
4
cutils.c
|
@ -129,7 +129,7 @@ int dbuf_realloc(DynBuf *s, size_t new_size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
|
int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len)
|
||||||
{
|
{
|
||||||
size_t end;
|
size_t end;
|
||||||
end = offset + len;
|
end = offset + len;
|
||||||
|
@ -141,7 +141,7 @@ int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len)
|
int dbuf_put(DynBuf *s, const void *data, size_t len)
|
||||||
{
|
{
|
||||||
if (unlikely((s->size + len) > s->allocated_size)) {
|
if (unlikely((s->size + len) > s->allocated_size)) {
|
||||||
if (dbuf_realloc(s, s->size + len))
|
if (dbuf_realloc(s, s->size + len))
|
||||||
|
|
4
cutils.h
4
cutils.h
|
@ -277,8 +277,8 @@ typedef struct DynBuf {
|
||||||
void dbuf_init(DynBuf *s);
|
void dbuf_init(DynBuf *s);
|
||||||
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
|
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
|
||||||
int dbuf_realloc(DynBuf *s, size_t new_size);
|
int dbuf_realloc(DynBuf *s, size_t new_size);
|
||||||
int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len);
|
int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len);
|
||||||
int dbuf_put(DynBuf *s, const uint8_t *data, size_t len);
|
int dbuf_put(DynBuf *s, const void *data, size_t len);
|
||||||
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
|
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
|
||||||
int dbuf_putc(DynBuf *s, uint8_t c);
|
int dbuf_putc(DynBuf *s, uint8_t c);
|
||||||
int dbuf_putstr(DynBuf *s, const char *str);
|
int dbuf_putstr(DynBuf *s, const char *str);
|
||||||
|
|
1
qjsc.c
1
qjsc.c
|
@ -305,6 +305,7 @@ static const char main_c_template1[] =
|
||||||
static const char main_c_template2[] =
|
static const char main_c_template2[] =
|
||||||
" js_std_loop(ctx);\n"
|
" js_std_loop(ctx);\n"
|
||||||
" JS_FreeContext(ctx);\n"
|
" JS_FreeContext(ctx);\n"
|
||||||
|
" js_std_free_handlers(rt);\n"
|
||||||
" JS_FreeRuntime(rt);\n"
|
" JS_FreeRuntime(rt);\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
15
quickjs.c
15
quickjs.c
|
@ -32018,7 +32018,7 @@ typedef enum BCTagEnum {
|
||||||
BC_TAG_OBJECT_REFERENCE,
|
BC_TAG_OBJECT_REFERENCE,
|
||||||
} BCTagEnum;
|
} BCTagEnum;
|
||||||
|
|
||||||
#define BC_VERSION 7
|
#define BC_VERSION 8
|
||||||
|
|
||||||
typedef struct BCWriterState {
|
typedef struct BCWriterState {
|
||||||
JSContext *ctx;
|
JSContext *ctx;
|
||||||
|
@ -32440,6 +32440,8 @@ static int JS_WriteFunctionTag(BCWriterState *s, JSValue obj)
|
||||||
bc_put_leb128(s, b->col_num);
|
bc_put_leb128(s, b->col_num);
|
||||||
bc_put_leb128(s, b->pc2line_len);
|
bc_put_leb128(s, b->pc2line_len);
|
||||||
dbuf_put(&s->dbuf, b->pc2line_buf, b->pc2line_len);
|
dbuf_put(&s->dbuf, b->pc2line_buf, b->pc2line_len);
|
||||||
|
bc_put_leb128(s, b->source_len);
|
||||||
|
dbuf_put(&s->dbuf, b->source, b->source_len);
|
||||||
|
|
||||||
/* compatibility */
|
/* compatibility */
|
||||||
dbuf_putc(&s->dbuf, 255);
|
dbuf_putc(&s->dbuf, 255);
|
||||||
|
@ -33017,7 +33019,7 @@ static int bc_get_leb128_u16(BCReaderState *s, uint16_t *pval)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bc_get_buf(BCReaderState *s, uint8_t *buf, uint32_t buf_len)
|
static int bc_get_buf(BCReaderState *s, void *buf, uint32_t buf_len)
|
||||||
{
|
{
|
||||||
if (buf_len != 0) {
|
if (buf_len != 0) {
|
||||||
if (unlikely(!buf || s->buf_end - s->ptr < buf_len))
|
if (unlikely(!buf || s->buf_end - s->ptr < buf_len))
|
||||||
|
@ -33413,6 +33415,15 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
|
||||||
if (bc_get_buf(s, b->pc2line_buf, b->pc2line_len))
|
if (bc_get_buf(s, b->pc2line_buf, b->pc2line_len))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
if (bc_get_leb128_int(s, &b->source_len))
|
||||||
|
goto fail;
|
||||||
|
if (b->source_len) {
|
||||||
|
b->source = js_mallocz(ctx, b->source_len);
|
||||||
|
if (!b->source)
|
||||||
|
goto fail;
|
||||||
|
if (bc_get_buf(s, b->source, b->source_len))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
if (s->buf_end - s->ptr > 3 && s->ptr[0] == 255 &&
|
if (s->buf_end - s->ptr > 3 && s->ptr[0] == 255 &&
|
||||||
s->ptr[1] == 73 && s->ptr[2] == 67) {
|
s->ptr[1] == 73 && s->ptr[2] == 67) {
|
||||||
s->ptr += 3;
|
s->ptr += 3;
|
||||||
|
|
14
tests/function_source.js
Normal file
14
tests/function_source.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
"use strict"
|
||||||
|
const expect = "function f() { return 42 }"
|
||||||
|
function f() { return 42 }
|
||||||
|
|
||||||
|
{
|
||||||
|
const actual = f.toString()
|
||||||
|
if (actual !== expect) throw Error(actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const f = eval(expect + "f")
|
||||||
|
const actual = f.toString()
|
||||||
|
if (actual !== expect) throw Error(actual)
|
||||||
|
}
|
Loading…
Reference in a new issue