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.

spread operator

+166 -42
+2 -1
examples/ffi/basic/printf.js
··· 12 12 } 13 13 14 14 const libc = dlopen(libcName); 15 + const printf = (...args) => libc.call('printf', ...args); 15 16 16 17 libc.define('putchar', { 17 18 args: [FFIType.int], ··· 27 28 libc.call('putchar', 65); // 'A' 28 29 29 30 console.log('\ncalling printf:'); 30 - libc.call('printf', 'Hello FFI! I see %d\n', 42); 31 + printf('Hello FFI! I see %d\n', 42); 31 32 32 33 console.log('calling putchar(66):'); 33 34 libc.call('putchar', 66); // 'B'
+1 -1
meson.build
··· 74 74 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 75 75 76 76 version_conf = configuration_data() 77 - version_conf.set('ANT_VERSION', '0.0.7.16') 77 + version_conf.set('ANT_VERSION', '0.0.7.17') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+104 -40
src/ant.c
··· 1165 1165 return mkobj(js, 0); 1166 1166 } 1167 1167 1168 + static jsoff_t arr_length(struct js *js, jsval_t arr) { 1169 + if (vtype(arr) != T_ARR) return 0; 1170 + jsoff_t scan = loadoff(js, (jsoff_t) vdata(arr)) & ~(3U | CONSTMASK); 1171 + while (scan < js->brk && scan != 0) { 1172 + jsoff_t koff = loadoff(js, scan + (jsoff_t) sizeof(scan)); 1173 + jsoff_t klen = offtolen(loadoff(js, koff)); 1174 + const char *key = (char *) &js->mem[koff + sizeof(koff)]; 1175 + if (streq(key, klen, "length", 6)) { 1176 + jsval_t val = loadval(js, scan + (jsoff_t) (sizeof(scan) + sizeof(koff))); 1177 + if (vtype(val) == T_NUM) return (jsoff_t) tod(val); 1178 + break; 1179 + } 1180 + scan = loadoff(js, scan) & ~(3U | CONSTMASK); 1181 + } 1182 + return 0; 1183 + } 1184 + 1185 + static jsval_t arr_get(struct js *js, jsval_t arr, jsoff_t idx) { 1186 + if (vtype(arr) != T_ARR) return js_mkundef(); 1187 + char idxstr[16]; 1188 + snprintf(idxstr, sizeof(idxstr), "%u", (unsigned) idx); 1189 + jsoff_t idxlen = (jsoff_t) strlen(idxstr); 1190 + jsoff_t prop = loadoff(js, (jsoff_t) vdata(arr)) & ~(3U | CONSTMASK); 1191 + while (prop < js->brk && prop != 0) { 1192 + jsoff_t koff = loadoff(js, prop + (jsoff_t) sizeof(prop)); 1193 + jsoff_t klen = offtolen(loadoff(js, koff)); 1194 + const char *key = (char *) &js->mem[koff + sizeof(koff)]; 1195 + if (streq(key, klen, idxstr, idxlen)) { 1196 + return loadval(js, prop + (jsoff_t) (sizeof(prop) + sizeof(koff))); 1197 + } 1198 + prop = loadoff(js, prop) & ~(3U | CONSTMASK); 1199 + } 1200 + return js_mkundef(); 1201 + } 1202 + 1168 1203 static bool is_const_prop(struct js *js, jsoff_t propoff) { 1169 1204 for (jsoff_t off = 0; off < js->brk;) { 1170 1205 jsoff_t v = loadoff(js, off); ··· 2146 2181 2147 2182 for (bool comma = false; next(js) != TOK_EOF; comma = true) { 2148 2183 if (!comma && next(js) == TOK_RPAREN) break; 2184 + if (next(js) == TOK_REST) js->consumed = 1; 2149 2185 js_expr(js); 2150 2186 if (next(js) == TOK_RPAREN) break; 2151 2187 EXPECT(TOK_COMMA, js->flags = flags); ··· 2170 2206 2171 2207 while (js->pos < js->clen) { 2172 2208 if (next(js) == TOK_RPAREN) break; 2209 + bool is_spread = (next(js) == TOK_REST); 2210 + if (is_spread) js->consumed = 1; 2173 2211 jsval_t arg = resolveprop(js, js_expr(js)); 2174 - if (js->brk + sizeof(arg) > js->size) return js_mkerr(js, "call oom"); 2175 - js->size -= (jsoff_t) sizeof(arg); 2176 - memcpy(&js->mem[js->size], &arg, sizeof(arg)); 2177 - argc++; 2212 + if (is_spread && vtype(arg) == T_ARR) { 2213 + jsoff_t len = arr_length(js, arg); 2214 + for (jsoff_t i = 0; i < len; i++) { 2215 + jsval_t elem = arr_get(js, arg, i); 2216 + if (js->brk + sizeof(elem) > js->size) return js_mkerr(js, "call oom"); 2217 + js->size -= (jsoff_t) sizeof(elem); 2218 + memcpy(&js->mem[js->size], &elem, sizeof(elem)); 2219 + argc++; 2220 + } 2221 + } else { 2222 + if (js->brk + sizeof(arg) > js->size) return js_mkerr(js, "call oom"); 2223 + js->size -= (jsoff_t) sizeof(arg); 2224 + memcpy(&js->mem[js->size], &arg, sizeof(arg)); 2225 + argc++; 2226 + } 2178 2227 if (next(js) == TOK_COMMA) js->consumed = 1; 2179 2228 } 2180 2229 ··· 2252 2301 } 2253 2302 2254 2303 jsval_t function_scope = mkobj(js, parent_scope_offset); 2304 + 2305 + const char *caller_code = js->code; 2306 + jsoff_t caller_clen = js->clen; 2307 + jsoff_t caller_pos = js->pos; 2308 + 2309 + jsval_t args[64]; 2310 + int argc = 0; 2311 + caller_pos = skiptonext(caller_code, caller_clen, caller_pos); 2312 + while (caller_pos < caller_clen && caller_code[caller_pos] != ')' && argc < 64) { 2313 + bool is_spread = (caller_code[caller_pos] == '.' && caller_pos + 2 < caller_clen && 2314 + caller_code[caller_pos + 1] == '.' && caller_code[caller_pos + 2] == '.'); 2315 + if (is_spread) caller_pos += 3; 2316 + js->pos = caller_pos; 2317 + js->consumed = 1; 2318 + jsval_t arg = resolveprop(js, js_expr(js)); 2319 + caller_pos = js->pos; 2320 + if (is_spread && vtype(arg) == T_ARR) { 2321 + jsoff_t len = arr_length(js, arg); 2322 + for (jsoff_t i = 0; i < len && argc < 64; i++) { 2323 + args[argc++] = arr_get(js, arg, i); 2324 + } 2325 + } else { 2326 + args[argc++] = arg; 2327 + } 2328 + caller_pos = skiptonext(caller_code, caller_clen, caller_pos); 2329 + if (caller_pos < caller_clen && caller_code[caller_pos] == ',') caller_pos++; 2330 + caller_pos = skiptonext(caller_code, caller_clen, caller_pos); 2331 + } 2332 + js->pos = caller_pos; 2333 + 2334 + int argi = 0; 2255 2335 bool has_rest = false; 2256 2336 jsoff_t rest_param_start = 0, rest_param_len = 0; 2257 2337 ··· 2282 2362 jsoff_t default_start = 0, default_len = 0; 2283 2363 fnpos = extract_default_param_value(fn, fnlen, fnpos + identlen, &default_start, &default_len); 2284 2364 2285 - js->pos = skiptonext(js->code, js->clen, js->pos); 2286 - js->consumed = 1; 2287 2365 jsval_t v; 2288 - if (js->code[js->pos] == ')' || js->code[js->pos] == ',') { 2289 - if (default_len > 0) { 2290 - const char *saved_code = js->code; 2291 - jsoff_t saved_clen = js->clen, saved_pos = js->pos; 2292 - js->code = &fn[default_start]; 2293 - js->clen = default_len; 2294 - js->pos = 0; 2295 - js->consumed = 1; 2296 - v = js_expr(js); 2297 - js->code = saved_code; 2298 - js->clen = saved_clen; 2299 - js->pos = saved_pos; 2300 - } else { 2301 - v = js_mkundef(); 2302 - } 2303 - } else { 2366 + if (argi < argc) { 2367 + v = args[argi++]; 2368 + } else if (default_len > 0) { 2369 + const char *saved_code = js->code; 2370 + jsoff_t saved_clen = js->clen, saved_pos = js->pos; 2371 + js->code = &fn[default_start]; 2372 + js->clen = default_len; 2373 + js->pos = 0; 2374 + js->consumed = 1; 2304 2375 v = js_expr(js); 2376 + js->code = saved_code; 2377 + js->clen = saved_clen; 2378 + js->pos = saved_pos; 2379 + } else { 2380 + v = js_mkundef(); 2305 2381 } 2306 2382 setprop(js, function_scope, js_mkstr(js, &fn[param_name_pos], identlen), v); 2307 - js->pos = skiptonext(js->code, js->clen, js->pos); 2308 - if (js->pos < js->clen && js->code[js->pos] == ',') js->pos++; 2309 2383 if (fnpos < fnlen && fn[fnpos] == ',') fnpos++; 2310 2384 } 2311 2385 ··· 2313 2387 jsval_t rest_array = mkarr(js); 2314 2388 if (!is_err(rest_array)) { 2315 2389 jsoff_t idx = 0; 2316 - js->pos = skiptonext(js->code, js->clen, js->pos); 2317 - 2318 - while (js->pos < js->clen && js->code[js->pos] != ')') { 2319 - js->consumed = 1; 2320 - jsval_t arg = js_expr(js); 2321 - if (!is_err(arg)) { 2322 - char idxstr[16]; 2323 - snprintf(idxstr, sizeof(idxstr), "%u", (unsigned) idx); 2324 - jsval_t key = js_mkstr(js, idxstr, strlen(idxstr)); 2325 - setprop(js, rest_array, key, resolveprop(js, arg)); 2326 - idx++; 2327 - } 2328 - js->pos = skiptonext(js->code, js->clen, js->pos); 2329 - if (js->pos < js->clen && js->code[js->pos] == ',') js->pos++; 2390 + while (argi < argc) { 2391 + char idxstr[16]; 2392 + snprintf(idxstr, sizeof(idxstr), "%u", (unsigned) idx); 2393 + jsval_t key = js_mkstr(js, idxstr, strlen(idxstr)); 2394 + setprop(js, rest_array, key, args[argi++]); 2395 + idx++; 2330 2396 } 2331 - 2332 2397 jsval_t len_key = js_mkstr(js, "length", 6); 2333 2398 setprop(js, rest_array, len_key, tov((double) idx)); 2334 2399 rest_array = mkval(T_ARR, vdata(rest_array)); 2335 - 2336 2400 setprop(js, function_scope, js_mkstr(js, &fn[rest_param_start], rest_param_len), rest_array); 2337 2401 } 2338 2402 }
+59
tests/test_spread.cjs
··· 1 + // Test spread operator in function calls 2 + 3 + // Test 1: Basic spread into function 4 + function sum(a, b, c) { 5 + return a + b + c; 6 + } 7 + let arr = [1, 2, 3]; 8 + console.log("Test 1 - Basic spread:"); 9 + console.log(sum(...arr)); // Should print 6 10 + 11 + // Test 2: Spread with regular args before 12 + function greet(prefix, a, b) { 13 + return prefix + ": " + a + " and " + b; 14 + } 15 + let names = ["Alice", "Bob"]; 16 + console.log("\nTest 2 - Spread with prefix arg:"); 17 + console.log(greet("Hello", ...names)); // Should print "Hello: Alice and Bob" 18 + 19 + // Test 3: Spread with regular args after 20 + function build(a, b, suffix) { 21 + return a + "-" + b + "-" + suffix; 22 + } 23 + let parts = ["x", "y"]; 24 + console.log("\nTest 3 - Spread with suffix arg:"); 25 + console.log(build(...parts, "z")); // Should print "x-y-z" 26 + 27 + // Test 4: Multiple spreads 28 + function concat(a, b, c, d) { 29 + return a + b + c + d; 30 + } 31 + let first = [1, 2]; 32 + let second = [3, 4]; 33 + console.log("\nTest 4 - Multiple spreads:"); 34 + console.log(concat(...first, ...second)); // Should print 10 35 + 36 + // Test 5: Spread into rest parameter function 37 + function collectAll(...items) { 38 + let total = 0; 39 + for (let i = 0; i < items.length; i++) { 40 + total = total + items[i]; 41 + } 42 + return total; 43 + } 44 + let nums = [10, 20, 30]; 45 + console.log("\nTest 5 - Spread into rest param:"); 46 + console.log(collectAll(...nums)); // Should print 60 47 + 48 + // Test 6: Spread empty array 49 + function countArgs(...args) { 50 + return args.length; 51 + } 52 + let empty = []; 53 + console.log("\nTest 6 - Spread empty array:"); 54 + console.log(countArgs(...empty)); // Should print 0 55 + 56 + // Test 7: Spread with console.log (C function) 57 + let values = ["a", "b", "c"]; 58 + console.log("\nTest 7 - Spread to console.log:"); 59 + console.log(...values); // Should print "a b c"