MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

handle explicit function length

+64 -7
+2 -2
examples/results.txt
··· 1047 1047 compat-table/es6/regex.flags.y.lastIndex.js: OK 1048 1048 compat-table/es6/rest-params.arguments.js: OK 1049 1049 compat-table/es6/rest-params.basic.js: OK 1050 - compat-table/es6/rest-params.length.js: failed 1050 + compat-table/es6/rest-params.length.js: OK 1051 1051 compat-table/es6/rest-params.new-function.js: OK 1052 - compat-table/es6/rest-params.no-setter.js: failed 1052 + compat-table/es6/rest-params.no-setter.js: OK 1053 1053 compat-table/es6/spread.array-call.js: OK 1054 1054 compat-table/es6/spread.array-literal.js: OK 1055 1055 compat-table/es6/spread.astral-call.js: OK
+10
examples/spec/functions.js
··· 34 34 return first + rest.length; 35 35 } 36 36 test('rest params', restParams(1, 2, 3, 4), 4); 37 + test('rest params length excludes rest', restParams.length, 1); 38 + test('rest-only params length is zero', ((...rest) => rest.length).length, 0); 39 + 40 + let restSetterRejected = false; 41 + try { 42 + eval('({ set value(...rest) {} })'); 43 + } catch (e) { 44 + restSetterRejected = true; 45 + } 46 + test('rest params rejected in setter', restSetterRejected, true); 37 47 38 48 function spreadCall(a, b, c) { 39 49 return a + b + c;
+2 -1
include/silver/engine.h
··· 180 180 int max_locals; 181 181 int max_stack; 182 182 int local_type_count; 183 - int param_count; 184 183 int upvalue_count; 185 184 int srcpos_count; 186 185 int source_line; ··· 190 189 191 190 uint16_t ic_count; 192 191 uint16_t obj_site_count; 192 + uint16_t param_count; 193 + uint16_t function_length; 193 194 194 195 bool is_strict; 195 196 bool is_arrow;
+22
src/silver/ast.c
··· 859 859 return n; 860 860 } 861 861 862 + static bool validate_accessor_params(P, sv_ast_t *fn, uint16_t flags) { 863 + if (!(flags & (FN_GETTER | FN_SETTER)) || !fn) return true; 864 + 865 + if ((flags & FN_GETTER) && fn->args.count != 0) { 866 + SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Getter must not have parameters"); 867 + return false; 868 + } 869 + 870 + if ( 871 + (flags & FN_SETTER) && ( 872 + fn->args.count != 1 || 873 + (fn->args.count == 1 && fn->args.items[0] && fn->args.items[0]->type == N_REST)) 874 + ) { 875 + SV_MKERR_TYPED(JS, JS_ERR_SYNTAX, "Setter must have exactly one non-rest parameter"); 876 + return false; 877 + } 878 + 879 + return true; 880 + } 881 + 862 882 static sv_ast_t *parse_object(P) { 863 883 CONSUME(); 864 884 sv_ast_t *n = mk(N_OBJECT); ··· 939 959 } 940 960 941 961 prop->right = parse_func(p); 962 + if (!validate_accessor_params(p, prop->right, prop->flags)) return n; 942 963 prop->right->flags |= FN_METHOD; 943 964 prop->right->src_off = prop->src_off; 944 965 sv_ast_list_push(&n->args, prop); ··· 1496 1517 1497 1518 if (NEXT() == TOK_LPAREN) { 1498 1519 method->right = parse_func(p); 1520 + if (!validate_accessor_params(p, method->right, method->flags)) return cls; 1499 1521 method->right->flags |= (flags & (FN_ASYNC | FN_GENERATOR)) | FN_METHOD; 1500 1522 method->right->src_off = method_src_off; 1501 1523 } else if (TOK == TOK_ASSIGN) {
+26 -2
src/silver/compiler.c
··· 4757 4757 memcpy(fn->local_types, comp.slot_types, (size_t)ncopy * sizeof(sv_type_info_t)); 4758 4758 } 4759 4759 } 4760 - fn->param_count = comp.param_count; 4760 + 4761 + fn->param_count = (uint16_t)comp.param_count; 4762 + fn->function_length = (uint16_t)comp.param_count; 4761 4763 fn->is_strict = comp.is_strict; 4762 4764 fn->filename = c->js->filename; 4763 4765 fn->source_line = (int)node->line; 4766 + 4764 4767 if (node->str && node->len > 0) { 4765 4768 char *name = code_arena_bump(node->len + 1); 4766 4769 memcpy(name, node->str, node->len); 4767 4770 name[node->len] = '\0'; 4768 4771 fn->name = name; 4769 4772 } 4773 + 4770 4774 sv_compile_ctx_cleanup(&comp); 4771 4775 int idx = add_constant(c, mkval(T_NTARG, (uintptr_t)fn)); 4772 4776 emit_op(c, OP_CLOSURE); ··· 4894 4898 return false; 4895 4899 } 4896 4900 4901 + static uint16_t function_length_from_params(const sv_ast_t *node) { 4902 + if (!node) return 0; 4903 + uint16_t length = 0; 4904 + for (int i = 0; i < node->args.count; i++) { 4905 + sv_ast_t *param = node->args.items[i]; 4906 + if (!param || param->type == N_REST || param->type == N_ASSIGN_PAT) break; 4907 + length++; 4908 + } 4909 + return length; 4910 + } 4911 + 4897 4912 sv_func_t *compile_function_body( 4898 4913 sv_compiler_t *enclosing, 4899 4914 sv_ast_t *node, 4900 4915 sv_compile_mode_t mode 4901 4916 ) { 4917 + if (node->args.count > UINT16_MAX) { 4918 + js_mkerr_typed( 4919 + enclosing->js, JS_ERR_SYNTAX, 4920 + "too many function parameters"); 4921 + return NULL; 4922 + } 4923 + 4902 4924 if ((node->flags & FN_ASYNC) && func_params_contain_await(node)) { 4903 4925 js_mkerr_typed( 4904 4926 enclosing->js, JS_ERR_SYNTAX, ··· 5321 5343 memcpy(func->local_types, comp.slot_types, (size_t)ncopy * sizeof(sv_type_info_t)); 5322 5344 } 5323 5345 } 5324 - func->param_count = comp.param_count; 5346 + 5347 + func->param_count = (uint16_t)comp.param_count; 5348 + func->function_length = function_length_from_params(node); 5325 5349 func->is_strict = comp.is_strict; 5326 5350 func->is_arrow = comp.is_arrow; 5327 5351
+1 -1
src/silver/glue.c
··· 638 638 ant_value_t module_ctx = sv_get_current_closure_module_ctx(js, mkval(T_FUNC, (uintptr_t)parent_closure)); 639 639 640 640 js_mark_constructor(func_obj, !child->is_arrow && !child->is_method && !child->is_generator && !child->is_async); 641 - js_setprop(js, func_obj, js->length_str, tov((double)child->param_count)); 641 + js_setprop(js, func_obj, js->length_str, tov((double)child->function_length)); 642 642 js_set_descriptor(js, func_obj, "length", 6, JS_DESC_C); 643 643 644 644 if (is_object_type(module_ctx))
+1 -1
src/silver/ops/upvalues.h
··· 136 136 ant_value_t module_ctx = sv_get_current_closure_module_ctx(js, frame->callee); 137 137 138 138 js_mark_constructor(func_obj, !child->is_arrow && !child->is_method && !child->is_generator && !child->is_async); 139 - js_setprop(js, func_obj, js->length_str, tov((double)child->param_count)); 139 + js_setprop(js, func_obj, js->length_str, tov((double)child->function_length)); 140 140 js_set_descriptor(js, func_obj, "length", 6, JS_DESC_C); 141 141 142 142 if (is_object_type(module_ctx)) js_set_slot_wb(js, func_obj, SLOT_MODULE_CTX, module_ctx);