From 4e9e1291c381fa2c2ba5b8304cdb9d30531a7b32 Mon Sep 17 00:00:00 2001 From: theMackabu Date: Tue, 10 Mar 2026 19:04:19 -0700 Subject: [PATCH] improve CommonJS function compilation with parameter handling --- examples/results.txt | 2 +- include/silver/compiler.h | 14 +++++-- src/esm/commonjs.c | 14 +++++-- src/silver/compiler.c | 81 +++++++++++++++++++++++++++------------ 4 files changed, 79 insertions(+), 32 deletions(-) diff --git a/examples/results.txt b/examples/results.txt index 6143b8f..c24c044 100644 --- a/examples/results.txt +++ b/examples/results.txt @@ -1323,7 +1323,7 @@ compat-table/es2023/Array.prototype.with.js: OK compat-table/es2023/TypedArray.prototype.toReversed.js: OK compat-table/es2023/TypedArray.prototype.toSorted.js: OK compat-table/es2023/TypedArray.prototype.with.js: OK -compat-table/es2023/hashbang.js: SyntaxError: private field name expected +compat-table/es2023/hashbang.js: OK compat-table/es2024/ArrayBuffer.prototype.detached.js: OK compat-table/es2024/ArrayBuffer.prototype.transferToFixedLength.js: OK compat-table/es2024/ArrayBuffer.prototype.transfer.js: OK diff --git a/include/silver/compiler.h b/include/silver/compiler.h index 3cbc36d..906f049 100644 --- a/include/silver/compiler.h +++ b/include/silver/compiler.h @@ -11,6 +11,14 @@ typedef enum { SV_COMPILE_REPL = 3, } sv_compile_mode_t; +typedef struct { + const char *name; + size_t len; +} sv_param_t; + +#define SV_PARAM(name_literal) \ + ((sv_param_t){ (name_literal), sizeof(name_literal) - 1 }) + sv_func_t *sv_compile( ant_t *js, sv_ast_t *program, sv_compile_mode_t mode, @@ -22,9 +30,9 @@ sv_func_t *sv_compile_function( size_t len, bool is_async ); -sv_func_t *sv_compile_function_parts( - ant_t *js, const char *params, - size_t params_len, const char *body, +sv_func_t *sv_compile_function_with_params( + ant_t *js, const sv_param_t *params, + int param_count, const char *body, size_t body_len, bool is_async ); diff --git a/src/esm/commonjs.c b/src/esm/commonjs.c index a53ce5c..1957c52 100644 --- a/src/esm/commonjs.c +++ b/src/esm/commonjs.c @@ -105,11 +105,17 @@ static ant_value_t esm_eval_commonjs_function( ant_value_t filename_val, ant_value_t dirname_val ) { - static const char *cjs_params = "require,module,exports,__filename,__dirname"; - - sv_func_t *compiled = sv_compile_function_parts( + static const sv_param_t cjs_params[] = { + SV_PARAM("require"), + SV_PARAM("module"), + SV_PARAM("exports"), + SV_PARAM("__filename"), + SV_PARAM("__dirname"), + }; + + sv_func_t *compiled = sv_compile_function_with_params( js, cjs_params, - strlen(cjs_params), + (int)(sizeof(cjs_params) / sizeof(cjs_params[0])), code, code_len, false ); diff --git a/src/silver/compiler.c b/src/silver/compiler.c index 7fb0434..fc403e5 100644 --- a/src/silver/compiler.c +++ b/src/silver/compiler.c @@ -4186,34 +4186,67 @@ sv_func_t *sv_compile_function(ant_t *js, const char *source, size_t len, bool i return func; } -sv_func_t *sv_compile_function_parts( +sv_func_t *sv_compile_function_with_params( ant_t *js, - const char *params, - size_t params_len, + const sv_param_t *params, + int param_count, const char *body, size_t body_len, bool is_async ) { - size_t source_len = params_len + body_len + 3; - char *source = malloc(source_len + 1); - if (!source) return NULL; - - size_t pos = 0; - source[pos++] = '('; - if (params_len > 0 && params) { - memcpy(source + pos, params, params_len); - pos += params_len; - } - source[pos++] = ')'; - source[pos++] = '{'; - if (body_len > 0 && body) { - memcpy(source + pos, body, body_len); - pos += body_len; - } - source[pos++] = '}'; - source[pos] = '\0'; - - sv_func_t *func = sv_compile_function(js, source, pos, is_async); - free(source); + if (!body) { + body = ""; + body_len = 0; + } + + bool parse_strict = sv_vm_is_strict(js->vm); + sv_ast_t *program = sv_parse(js, body, (ant_offset_t)body_len, parse_strict); + if (!program) return NULL; + + static const char *k_top_name_function = ""; + static const char *k_top_name_async_function = ""; + const char *top_name = is_async ? k_top_name_async_function : k_top_name_function; + + sv_ast_t top_fn; + memset(&top_fn, 0, sizeof(top_fn)); + + top_fn.type = N_FUNC; + top_fn.line = 1; + top_fn.str = top_name; + top_fn.len = (uint32_t)strlen(top_name); + top_fn.src_off = 0; + top_fn.src_end = (body_len > 0) ? (uint32_t)body_len : 0; + if (is_async) top_fn.flags |= FN_ASYNC; + + for (int i = 0; i < param_count; i++) { + const char *name = (params && params[i].name) ? params[i].name : ""; + size_t name_len = 0; + if (params && params[i].name) { + name_len = params[i].len ? params[i].len : strlen(name); + } + + sv_ast_t *ident = sv_ast_new(N_IDENT); + if (!ident) return NULL; + + ident->str = name; + ident->len = (uint32_t)name_len; + ident->line = 1; + ident->col = 1; + sv_ast_list_push(&top_fn.args, ident); + } + + top_fn.body = sv_ast_new(N_BLOCK); + if (!top_fn.body) return NULL; + top_fn.body->args = program->args; + + sv_compiler_t root = {0}; + root.js = js; + root.source = pin_source_text(body, (ant_offset_t)body_len); + root.source_len = (ant_offset_t)body_len; + root.mode = SV_COMPILE_SCRIPT; + root.is_strict = ((program->flags & FN_PARSE_STRICT) != 0); + + sv_func_t *func = compile_function_body(&root, &top_fn, SV_COMPILE_SCRIPT); + if (js->thrown_exists || !func) return NULL; return func; } -- 2.51.2