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_point.js
|
||||
./build/qjs tests/test_bjson.js
|
||||
./build/function_source
|
||||
linux-shared:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
@ -213,6 +214,7 @@ jobs:
|
|||
./build/qjs examples/test_fib.js
|
||||
./build/qjs examples/test_point.js
|
||||
./build/qjs tests/test_bjson.js
|
||||
./build/function_source
|
||||
macos-shared:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
|
@ -261,6 +263,7 @@ jobs:
|
|||
run: |
|
||||
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 function_source
|
||||
- name: stats
|
||||
run: |
|
||||
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_worker.js
|
||||
cmd /r build\Debug\qjs.exe tests\test_queue_microtask.js
|
||||
cmd /r build\Debug\function_source.exe
|
||||
|
||||
windows-mingw:
|
||||
runs-on: windows-latest
|
||||
|
|
|
@ -236,6 +236,21 @@ add_executable(unicode_gen EXCLUDE_FROM_ALL
|
|||
)
|
||||
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
|
||||
#
|
||||
|
@ -246,7 +261,7 @@ if(BUILD_EXAMPLES AND NOT WIN32)
|
|||
COMMAND qjsc -e -o hello.c ${CMAKE_CURRENT_SOURCE_DIR}/examples/hello.js
|
||||
DEPENDS qjsc
|
||||
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
|
||||
)
|
||||
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
|
||||
DEPENDS qjsc
|
||||
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
|
||||
)
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
end = offset + len;
|
||||
|
@ -141,7 +141,7 @@ int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len)
|
|||
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 (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_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
|
||||
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_put(DynBuf *s, 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 void *data, 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_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[] =
|
||||
" js_std_loop(ctx);\n"
|
||||
" JS_FreeContext(ctx);\n"
|
||||
" js_std_free_handlers(rt);\n"
|
||||
" JS_FreeRuntime(rt);\n"
|
||||
" return 0;\n"
|
||||
"}\n";
|
||||
|
|
15
quickjs.c
15
quickjs.c
|
@ -32018,7 +32018,7 @@ typedef enum BCTagEnum {
|
|||
BC_TAG_OBJECT_REFERENCE,
|
||||
} BCTagEnum;
|
||||
|
||||
#define BC_VERSION 7
|
||||
#define BC_VERSION 8
|
||||
|
||||
typedef struct BCWriterState {
|
||||
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->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 */
|
||||
dbuf_putc(&s->dbuf, 255);
|
||||
|
@ -33017,7 +33019,7 @@ static int bc_get_leb128_u16(BCReaderState *s, uint16_t *pval)
|
|||
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 (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))
|
||||
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 &&
|
||||
s->ptr[1] == 73 && s->ptr[2] == 67) {
|
||||
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