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.

optimize classes

+152 -92
+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.36') 77 + version_conf.set('ANT_VERSION', '0.0.7.37') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+137 -77
src/ant.c
··· 3275 3275 push_this(captured_this); 3276 3276 } 3277 3277 3278 + jsoff_t count_off = lkp(js, func_obj, "__field_count", 13); 3279 + if (count_off == 0 || vtype(target_this) != T_OBJ) goto skip_fields; 3280 + 3281 + jsval_t count_val = resolveprop(js, mkval(T_PROP, count_off)); 3282 + if (vtype(count_val) != T_NUM) goto skip_fields; 3283 + 3284 + int field_count = (int)tod(count_val); 3285 + jsoff_t src_off = lkp(js, func_obj, "__source", 8); 3286 + jsoff_t fields_off = lkp(js, func_obj, "__fields", 8); 3287 + if (src_off == 0 || fields_off == 0) goto skip_fields; 3288 + 3289 + jsval_t src_val = resolveprop(js, mkval(T_PROP, src_off)); 3290 + jsval_t fields_meta = resolveprop(js, mkval(T_PROP, fields_off)); 3291 + if (vtype(src_val) != T_STR || vtype(fields_meta) != T_STR) goto skip_fields; 3292 + 3293 + jsoff_t src_len, src_ptr_off = vstr(js, src_val, &src_len); 3294 + const char *source = (const char *)(&js->mem[src_ptr_off]); 3295 + 3296 + jsoff_t meta_len, meta_ptr_off = vstr(js, fields_meta, &meta_len); 3297 + const jsoff_t *metadata = (const jsoff_t *)(&js->mem[meta_ptr_off]); 3298 + 3299 + for (int i = 0; i < field_count; i++) { 3300 + jsoff_t name_off = metadata[i * 4 + 0]; 3301 + jsoff_t name_len = metadata[i * 4 + 1]; 3302 + jsoff_t init_start = metadata[i * 4 + 2]; 3303 + jsoff_t init_end = metadata[i * 4 + 3]; 3304 + 3305 + jsval_t fname = js_mkstr(js, &source[name_off], name_len); 3306 + if (is_err(fname)) { 3307 + js->current_func = saved_func; 3308 + pop_call_frame(); 3309 + return fname; 3310 + } 3311 + 3312 + jsval_t field_val = js_mkundef(); 3313 + if (init_start > 0 && init_end > init_start) { 3314 + jsoff_t init_len = init_end - init_start; 3315 + const char *init_code = &source[init_start]; 3316 + 3317 + const char *saved_code = js->code; 3318 + jsoff_t saved_clen = js->clen; 3319 + jsoff_t saved_pos = js->pos; 3320 + uint8_t saved_tok = js->tok; 3321 + uint8_t saved_consumed = js->consumed; 3322 + 3323 + js->code = init_code; 3324 + js->clen = init_len; 3325 + js->pos = 0; 3326 + js->consumed = 1; 3327 + 3328 + field_val = js_expr(js); 3329 + field_val = resolveprop(js, field_val); 3330 + 3331 + js->code = saved_code; 3332 + js->clen = saved_clen; 3333 + js->pos = saved_pos; 3334 + js->tok = saved_tok; 3335 + js->consumed = saved_consumed; 3336 + } 3337 + 3338 + jsval_t set_res = setprop(js, target_this, fname, field_val); 3339 + if (is_err(set_res)) { 3340 + js->current_func = saved_func; 3341 + pop_call_frame(); 3342 + return set_res; 3343 + } 3344 + } 3345 + skip_fields: 3278 3346 if (is_async) { 3279 3347 res = start_async_in_coroutine(js, code_str, fnlen, closure_scope, NULL, 0); 3280 3348 pop_call_frame(); ··· 6181 6249 6182 6250 EXPECT(TOK_LBRACE, ); 6183 6251 jsoff_t class_body_start = js->pos; 6184 - jsoff_t constructor_params_start = 0, constructor_params_end = 0; 6252 + jsoff_t constructor_params_start = 0; 6185 6253 jsoff_t constructor_body_start = 0, constructor_body_end = 0; 6186 6254 uint8_t save_flags = js->flags; 6187 6255 js->flags |= F_NOEXEC; ··· 6305 6373 EXPECT(TOK_COMMA, js->flags = save_flags); 6306 6374 } 6307 6375 EXPECT(TOK_RPAREN, js->flags = save_flags); 6308 - jsoff_t method_params_end = js->pos; 6309 6376 EXPECT(TOK_LBRACE, js->flags = save_flags); 6310 6377 jsoff_t method_body_start = js->pos - 1; 6311 6378 js->consumed = 0; ··· 6317 6384 jsoff_t method_body_end = js->pos; 6318 6385 if (streq(&js->code[method_name_off], method_name_len, "constructor", 11)) { 6319 6386 constructor_params_start = method_params_start; 6320 - constructor_params_end = method_params_end; 6321 6387 constructor_body_start = method_body_start + 1; 6322 - constructor_body_end = method_body_end - 1; 6388 + constructor_body_end = method_body_end; 6323 6389 } else { 6324 6390 methods[method_count].name_off = method_name_off; 6325 6391 methods[method_count].name_len = method_name_len; ··· 6390 6456 6391 6457 jsval_t mcode_key = js_mkstr(js, "__code", 6); 6392 6458 if (is_err(mcode_key)) return mcode_key; 6459 + jsval_t mres = setprop(js, method_obj, mcode_key, method_code); 6460 + if (is_err(mres)) return mres; 6393 6461 6394 6462 if (methods[i].is_async) { 6395 - char *async_code = malloc(mlen + 7); 6396 - if (!async_code) return js_mkerr(js, "oom"); 6397 - memcpy(async_code, "async ", 6); 6398 - memcpy(async_code + 6, &js->code[methods[i].fn_start], mlen); 6399 - method_code = js_mkstr(js, async_code, mlen + 6); 6400 - free(async_code); 6401 - if (is_err(method_code)) return method_code; 6463 + jsval_t async_key = js_mkstr(js, "__async", 7); 6464 + if (is_err(async_key)) return async_key; 6465 + jsval_t async_val = mkval(T_BOOL, 1); 6466 + jsval_t res_async = setprop(js, method_obj, async_key, async_val); 6467 + if (is_err(res_async)) return res_async; 6402 6468 } 6403 6469 6404 - jsval_t mres = setprop(js, method_obj, mcode_key, method_code); 6405 - if (is_err(mres)) return mres; 6406 - 6407 6470 jsval_t mscope_key = js_mkstr(js, "__scope", 7); 6408 6471 if (is_err(mscope_key)) return mscope_key; 6409 6472 jsval_t mscope_res = setprop(js, method_obj, mscope_key, func_scope); ··· 6414 6477 if (is_err(set_res)) return set_res; 6415 6478 } 6416 6479 6417 - jsoff_t wrapper_size = 256; 6418 - if (constructor_body_start > 0) { 6419 - wrapper_size += constructor_body_end - constructor_body_start; 6420 - } 6480 + jsval_t func_obj = mkobj(js, 0); 6481 + if (is_err(func_obj)) return func_obj; 6421 6482 6422 - for (int i = 0; i < method_count; i++) { 6423 - if (methods[i].is_static) continue; 6424 - if (!methods[i].is_field) continue; 6425 - wrapper_size += methods[i].name_len + 20; 6426 - wrapper_size += methods[i].field_end - methods[i].field_start; 6427 - } 6428 - 6429 - char *wrapper = (char *) malloc(wrapper_size); 6430 - if (!wrapper) return js_mkerr(js, "oom"); 6431 - jsoff_t wp = 0; 6432 - 6433 - if (constructor_params_start > 0) { 6434 - jsoff_t plen = constructor_params_end - constructor_params_start; 6435 - memcpy(wrapper + wp, &js->code[constructor_params_start], plen); 6436 - wp += plen; 6483 + if (constructor_params_start > 0 && constructor_body_start > 0) { 6484 + jsoff_t code_len = constructor_body_end - constructor_params_start; 6485 + 6486 + jsval_t code_key = js_mkstr(js, "__code", 6); 6487 + if (is_err(code_key)) return code_key; 6488 + jsval_t ctor_str = js_mkstr(js, &js->code[constructor_params_start], code_len); 6489 + if (is_err(ctor_str)) return ctor_str; 6490 + 6491 + jsval_t res2 = setprop(js, func_obj, code_key, ctor_str); 6492 + if (is_err(res2)) return res2; 6437 6493 } else { 6438 - memcpy(wrapper + wp, "()", 2); 6439 - wp += 2; 6494 + jsval_t code_key = js_mkstr(js, "__code", 6); 6495 + if (is_err(code_key)) return code_key; 6496 + jsval_t default_ctor = js_mkstr(js, "(){}", 4); 6497 + if (is_err(default_ctor)) return default_ctor; 6498 + jsval_t res2 = setprop(js, func_obj, code_key, default_ctor); 6499 + if (is_err(res2)) return res2; 6440 6500 } 6441 - wrapper[wp++] = '{'; 6442 6501 6502 + int field_count = 0; 6443 6503 for (int i = 0; i < method_count; i++) { 6444 6504 if (methods[i].is_static) continue; 6445 - if (!methods[i].is_field) continue; 6446 - 6447 - if (wp > 0 && wrapper[wp - 1] != ';' && wrapper[wp - 1] != '{') { 6448 - wrapper[wp++] = ';'; 6449 - } 6450 - memcpy(wrapper + wp, "this.", 5); 6451 - wp += 5; 6452 - memcpy(wrapper + wp, &js->code[methods[i].name_off], methods[i].name_len); 6453 - wp += methods[i].name_len; 6454 - wrapper[wp++] = '='; 6455 - if (methods[i].field_start > 0 && methods[i].field_end > methods[i].field_start) { 6456 - jsoff_t flen = methods[i].field_end - methods[i].field_start; 6457 - memcpy(wrapper + wp, &js->code[methods[i].field_start], flen); 6458 - wp += flen; 6459 - } else { 6460 - memcpy(wrapper + wp, "undefined", 9); 6461 - wp += 9; 6462 - } 6463 - wrapper[wp++] = ';'; 6505 + if (methods[i].is_field) field_count++; 6464 6506 } 6465 6507 6466 - if (constructor_body_start > 0) { 6467 - jsoff_t blen = constructor_body_end - constructor_body_start; 6468 - memcpy(wrapper + wp, &js->code[constructor_body_start], blen); 6469 - wp += blen; 6470 - while (wp > 0 && (wrapper[wp - 1] == ' ' || wrapper[wp - 1] == '\t' || 6471 - wrapper[wp - 1] == '\n' || wrapper[wp - 1] == '\r')) { 6472 - wp--; 6508 + if (field_count > 0) { 6509 + size_t metadata_size = field_count * sizeof(jsoff_t) * 4; 6510 + jsoff_t meta_len = (jsoff_t) (metadata_size + 1); 6511 + jsoff_t meta_header = (jsoff_t) ((meta_len << 2) | T_STR); 6512 + jsoff_t meta_off = js_alloc(js, meta_len + sizeof(meta_header)); 6513 + if (meta_off == (jsoff_t) ~0) return js_mkerr(js, "oom"); 6514 + 6515 + memcpy(&js->mem[meta_off], &meta_header, sizeof(meta_header)); 6516 + jsoff_t *metadata = (jsoff_t *)(&js->mem[meta_off + sizeof(meta_header)]); 6517 + 6518 + int meta_idx = 0; 6519 + for (int i = 0; i < method_count; i++) { 6520 + if (methods[i].is_static) continue; 6521 + if (!methods[i].is_field) continue; 6522 + 6523 + metadata[meta_idx * 4 + 0] = methods[i].name_off; 6524 + metadata[meta_idx * 4 + 1] = methods[i].name_len; 6525 + metadata[meta_idx * 4 + 2] = methods[i].field_start; 6526 + metadata[meta_idx * 4 + 3] = methods[i].field_end; 6527 + meta_idx++; 6473 6528 } 6474 - if (wp > 0 && wrapper[wp - 1] != ';' && wrapper[wp - 1] != '}') { 6475 - wrapper[wp++] = ';'; 6476 - } 6529 + 6530 + js->mem[meta_off + sizeof(meta_header) + metadata_size] = 0; 6531 + jsval_t fields_meta = mkval(T_STR, meta_off); 6532 + 6533 + jsval_t fields_key = js_mkstr(js, "__fields", 8); 6534 + if (is_err(fields_key)) return fields_key; 6535 + jsval_t res_fields = setprop(js, func_obj, fields_key, fields_meta); 6536 + if (is_err(res_fields)) return res_fields; 6537 + 6538 + jsval_t count_key = js_mkstr(js, "__field_count", 13); 6539 + if (is_err(count_key)) return count_key; 6540 + jsval_t res_count = setprop(js, func_obj, count_key, tov((double)field_count)); 6541 + if (is_err(res_count)) return res_count; 6542 + 6543 + jsval_t src_key = js_mkstr(js, "__source", 8); 6544 + if (is_err(src_key)) return src_key; 6545 + jsval_t src_ref = js_mkstr(js, js->code, js->clen); 6546 + if (is_err(src_ref)) return src_ref; 6547 + jsval_t res_src = setprop(js, func_obj, src_key, src_ref); 6548 + if (is_err(res_src)) return res_src; 6477 6549 } 6478 - 6479 - wrapper[wp++] = '}'; 6480 - jsval_t code_str = js_mkstr(js, wrapper, wp); 6481 - free(wrapper); 6482 - if (is_err(code_str)) return code_str; 6483 - 6484 - jsval_t func_obj = mkobj(js, 0); 6485 - if (is_err(func_obj)) return func_obj; 6486 - jsval_t code_key = js_mkstr(js, "__code", 6); 6487 - if (is_err(code_key)) return code_key; 6488 - jsval_t res2 = setprop(js, func_obj, code_key, code_str); 6489 - if (is_err(res2)) return res2; 6490 6550 6491 6551 jsval_t scope_key = js_mkstr(js, "__scope", 7); 6492 6552 if (is_err(scope_key)) return scope_key;
+10 -11
tests/test_async_class_methods.cjs
··· 5 5 this.name = 'AsyncTestClass'; 6 6 this.value = 42; 7 7 } 8 - 8 + 9 9 // Regular method 10 10 regularMethod() { 11 11 console.log('regularMethod: this.name = ' + this.name); 12 12 return this.value; 13 13 } 14 - 14 + 15 15 // Async method 16 16 async asyncMethod() { 17 17 console.log('asyncMethod: this.name = ' + this.name); 18 18 return Promise.resolve(this.value * 2); 19 19 } 20 - 20 + 21 21 // Async method with argument 22 22 async asyncWithArg(multiplier) { 23 23 console.log('asyncWithArg: this.name = ' + this.name + ', multiplier = ' + multiplier); 24 24 return Promise.resolve(this.value * multiplier); 25 25 } 26 - 26 + 27 27 // Async method that calls helper 28 28 async asyncWithHelper() { 29 29 function helper() { ··· 43 43 44 44 console.log('\n=== Test 2: Async method ==='); 45 45 const promise2 = obj.asyncMethod(); 46 - console.log('Returned: ' + (typeof promise2)); 47 - promise2.then((val) => { 46 + console.log('Returned: ' + typeof promise2); 47 + promise2.then(function (val) { 48 48 console.log('Resolved value: ' + val); 49 - console.log('Inside .then(), this.name: ' + this.name); 50 49 }); 51 50 52 51 console.log('\n=== Test 3: Async method with argument ==='); 53 52 const promise3 = obj.asyncWithArg(5); 54 - console.log('Returned: ' + (typeof promise3)); 55 - promise3.then((val) => { 53 + console.log('Returned: ' + typeof promise3); 54 + promise3.then(function (val) { 56 55 console.log('Resolved value: ' + val); 57 56 }); 58 57 59 58 console.log('\n=== Test 4: Async method with helper function ==='); 60 59 const promise4 = obj.asyncWithHelper(); 61 - console.log('Returned: ' + (typeof promise4)); 62 - promise4.then((val) => { 60 + console.log('Returned: ' + typeof promise4); 61 + promise4.then(function (val) { 63 62 console.log('Resolved value: ' + val); 64 63 }); 65 64
+4 -3
tests/test_async_this.cjs
··· 17 17 methodWithPromise() { 18 18 console.log('methodWithPromise called:'); 19 19 console.log(' this.name: ' + this.name); 20 + const self = this; 20 21 21 - return Promise.resolve(this.value).then((v) => { 22 - console.log(' Inside .then(), this.name: ' + this.name); 23 - console.log(' Inside .then(), this.value: ' + this.value); 22 + return Promise.resolve(this.value).then(function(v) { 23 + console.log(' Inside .then(), this.name: ' + self.name); 24 + console.log(' Inside .then(), this.value: ' + self.value); 24 25 return v * 2; 25 26 }); 26 27 }