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.

base64 this.btoa, this.atob

+201 -1
+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.31') 77 + version_conf.set('ANT_VERSION', '0.0.7.32') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+112
src/ant.c
··· 363 363 static jsval_t builtin_number_toExponential(struct js *js, jsval_t *args, int nargs); 364 364 static jsval_t builtin_parseInt(struct js *js, jsval_t *args, int nargs); 365 365 static jsval_t builtin_parseFloat(struct js *js, jsval_t *args, int nargs); 366 + static jsval_t builtin_btoa(struct js *js, jsval_t *args, int nargs); 367 + static jsval_t builtin_atob(struct js *js, jsval_t *args, int nargs); 366 368 static jsval_t builtin_Object(struct js *js, jsval_t *args, int nargs); 367 369 static jsval_t builtin_RegExp(struct js *js, jsval_t *args, int nargs); 368 370 static jsval_t builtin_Promise(struct js *js, jsval_t *args, int nargs); ··· 8491 8493 return tov(result); 8492 8494 } 8493 8495 8496 + static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 8497 + 8498 + static jsval_t builtin_btoa(struct js *js, jsval_t *args, int nargs) { 8499 + if (nargs < 1) return js_mkerr(js, "btoa requires 1 argument"); 8500 + 8501 + jsval_t str_val = args[0]; 8502 + if (vtype(str_val) != T_STR) { 8503 + const char *str = js_str(js, str_val); 8504 + str_val = js_mkstr(js, str, strlen(str)); 8505 + } 8506 + 8507 + jsoff_t str_len, str_off = vstr(js, str_val, &str_len); 8508 + const char *str = (char *) &js->mem[str_off]; 8509 + 8510 + for (jsoff_t i = 0; i < str_len; i++) { 8511 + if ((unsigned char)str[i] > 255) { 8512 + return js_mkerr(js, "btoa: character out of range"); 8513 + } 8514 + } 8515 + 8516 + size_t out_len = ((str_len + 2) / 3) * 4; 8517 + char *out = (char *)ANT_GC_MALLOC(out_len + 1); 8518 + if (!out) return js_mkerr(js, "out of memory"); 8519 + 8520 + size_t i = 0, j = 0; 8521 + while (i < str_len) { 8522 + size_t remaining = str_len - i; 8523 + uint32_t a = (unsigned char)str[i++]; 8524 + uint32_t b = (remaining > 1) ? (unsigned char)str[i++] : 0; 8525 + uint32_t c = (remaining > 2) ? (unsigned char)str[i++] : 0; 8526 + uint32_t triple = (a << 16) | (b << 8) | c; 8527 + 8528 + out[j++] = base64_chars[(triple >> 18) & 0x3F]; 8529 + out[j++] = base64_chars[(triple >> 12) & 0x3F]; 8530 + out[j++] = (remaining > 1) ? base64_chars[(triple >> 6) & 0x3F] : '='; 8531 + out[j++] = (remaining > 2) ? base64_chars[triple & 0x3F] : '='; 8532 + } 8533 + out[j] = '\0'; 8534 + 8535 + jsval_t result = js_mkstr(js, out, j); 8536 + ANT_GC_FREE(out); 8537 + return result; 8538 + } 8539 + 8540 + static jsval_t builtin_atob(struct js *js, jsval_t *args, int nargs) { 8541 + if (nargs < 1) return js_mkerr(js, "atob requires 1 argument"); 8542 + 8543 + jsval_t str_val = args[0]; 8544 + if (vtype(str_val) != T_STR) { 8545 + const char *str = js_str(js, str_val); 8546 + str_val = js_mkstr(js, str, strlen(str)); 8547 + } 8548 + 8549 + jsoff_t str_len, str_off = vstr(js, str_val, &str_len); 8550 + const char *str = (char *) &js->mem[str_off]; 8551 + 8552 + if (str_len == 0) return js_mkstr(js, "", 0); 8553 + if (str_len % 4 != 0) return js_mkerr(js, "atob: invalid base64 string"); 8554 + 8555 + size_t out_len = (str_len / 4) * 3; 8556 + if (str_len > 0 && str[str_len - 1] == '=') out_len--; 8557 + if (str_len > 1 && str[str_len - 2] == '=') out_len--; 8558 + 8559 + char *out = (char *)ANT_GC_MALLOC(out_len + 1); 8560 + if (!out) return js_mkerr(js, "out of memory"); 8561 + 8562 + static const int8_t decode_table[256] = { 8563 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 8564 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 8565 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, 8566 + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, 8567 + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 8568 + 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, 8569 + -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, 8570 + 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, 8571 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 8572 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 8573 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 8574 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 8575 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 8576 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 8577 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 8578 + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 8579 + }; 8580 + 8581 + size_t i = 0, j = 0; 8582 + while (i < str_len) { 8583 + int8_t a = decode_table[(unsigned char)str[i++]]; 8584 + int8_t b = decode_table[(unsigned char)str[i++]]; 8585 + int8_t c = (str[i] == '=') ? 0 : decode_table[(unsigned char)str[i]]; i++; 8586 + int8_t d = (str[i] == '=') ? 0 : decode_table[(unsigned char)str[i]]; i++; 8587 + 8588 + if (a < 0 || b < 0 || (str[i-2] != '=' && c < 0) || (str[i-1] != '=' && d < 0)) { 8589 + ANT_GC_FREE(out); 8590 + return js_mkerr(js, "atob: invalid character in base64 string"); 8591 + } 8592 + 8593 + uint32_t triple = ((uint32_t)a << 18) | ((uint32_t)b << 12) | ((uint32_t)c << 6) | (uint32_t)d; 8594 + if (j < out_len) out[j++] = (triple >> 16) & 0xFF; 8595 + if (j < out_len) out[j++] = (triple >> 8) & 0xFF; 8596 + if (j < out_len) out[j++] = triple & 0xFF; 8597 + } 8598 + 8599 + jsval_t result = js_mkstr(js, out, out_len); 8600 + ANT_GC_FREE(out); 8601 + return result; 8602 + } 8603 + 8494 8604 static jsval_t builtin_resolve_internal(struct js *js, jsval_t *args, int nargs); 8495 8605 static jsval_t builtin_reject_internal(struct js *js, jsval_t *args, int nargs); 8496 8606 static void resolve_promise(struct js *js, jsval_t p, jsval_t val); ··· 10325 10435 setprop(js, glob, js_mkstr(js, "eval", 4), js_mkfun(builtin_eval)); 10326 10436 setprop(js, glob, js_mkstr(js, "parseInt", 8), js_mkfun(builtin_parseInt)); 10327 10437 setprop(js, glob, js_mkstr(js, "parseFloat", 10), js_mkfun(builtin_parseFloat)); 10438 + setprop(js, glob, js_mkstr(js, "btoa", 4), js_mkfun(builtin_btoa)); 10439 + setprop(js, glob, js_mkstr(js, "atob", 4), js_mkfun(builtin_atob)); 10328 10440 setprop(js, glob, js_mkstr(js, "NaN", 3), tov(NAN)); 10329 10441 setprop(js, glob, js_mkstr(js, "Infinity", 8), tov(INFINITY)); 10330 10442
+88
tests/test_base64.cjs
··· 1 + // Test btoa() and atob() Base64 encoding/decoding 2 + 3 + console.log("=== Base64 Tests ===\n"); 4 + 5 + // Test 1: Basic btoa encoding 6 + console.log("Test 1: Basic btoa encoding"); 7 + let encoded1 = btoa("Hello, World!"); 8 + console.log(" Input: Hello, World!"); 9 + console.log(" Encoded:", encoded1); 10 + console.log(" Expected: SGVsbG8sIFdvcmxkIQ=="); 11 + console.log(" Pass:", encoded1 === "SGVsbG8sIFdvcmxkIQ=="); 12 + 13 + // Test 2: Basic atob decoding 14 + console.log("\nTest 2: Basic atob decoding"); 15 + let decoded2 = atob("SGVsbG8sIFdvcmxkIQ=="); 16 + console.log(" Input: SGVsbG8sIFdvcmxkIQ=="); 17 + console.log(" Decoded:", decoded2); 18 + console.log(" Expected: Hello, World!"); 19 + console.log(" Pass:", decoded2 === "Hello, World!"); 20 + 21 + // Test 3: Round-trip test 22 + console.log("\nTest 3: Round-trip test"); 23 + let original3 = "The quick brown fox jumps over the lazy dog"; 24 + let encoded3 = btoa(original3); 25 + let decoded3 = atob(encoded3); 26 + console.log(" Original:", original3); 27 + console.log(" Encoded:", encoded3); 28 + console.log(" Decoded:", decoded3); 29 + console.log(" Pass:", original3 === decoded3); 30 + 31 + // Test 4: Empty string 32 + console.log("\nTest 4: Empty string"); 33 + let encoded4 = btoa(""); 34 + let decoded4 = atob(""); 35 + console.log(" btoa(''):", encoded4); 36 + console.log(" atob(''):", decoded4); 37 + console.log(" Pass:", encoded4 === "" && decoded4 === ""); 38 + 39 + // Test 5: Single character 40 + console.log("\nTest 5: Single character"); 41 + let encoded5 = btoa("A"); 42 + console.log(" btoa('A'):", encoded5); 43 + console.log(" Expected: QQ=="); 44 + console.log(" Pass:", encoded5 === "QQ=="); 45 + 46 + // Test 6: Two characters 47 + console.log("\nTest 6: Two characters"); 48 + let encoded6 = btoa("AB"); 49 + console.log(" btoa('AB'):", encoded6); 50 + console.log(" Expected: QUI="); 51 + console.log(" Pass:", encoded6 === "QUI="); 52 + 53 + // Test 7: Three characters (no padding) 54 + console.log("\nTest 7: Three characters"); 55 + let encoded7 = btoa("ABC"); 56 + console.log(" btoa('ABC'):", encoded7); 57 + console.log(" Expected: QUJD"); 58 + console.log(" Pass:", encoded7 === "QUJD"); 59 + 60 + // Test 8: Numbers in string 61 + console.log("\nTest 8: Numbers in string"); 62 + let encoded8 = btoa("12345"); 63 + console.log(" btoa('12345'):", encoded8); 64 + let decoded8 = atob(encoded8); 65 + console.log(" atob result:", decoded8); 66 + console.log(" Pass:", decoded8 === "12345"); 67 + 68 + // Test 9: Special characters 69 + console.log("\nTest 9: Special characters"); 70 + let special = "!@#$%^&*()"; 71 + let encoded9 = btoa(special); 72 + let decoded9 = atob(encoded9); 73 + console.log(" Original:", special); 74 + console.log(" Encoded:", encoded9); 75 + console.log(" Decoded:", decoded9); 76 + console.log(" Pass:", special === decoded9); 77 + 78 + // Test 10: JSON data 79 + console.log("\nTest 10: JSON data"); 80 + let jsonData = '{"name":"test","value":123}'; 81 + let encoded10 = btoa(jsonData); 82 + let decoded10 = atob(encoded10); 83 + console.log(" JSON:", jsonData); 84 + console.log(" Encoded:", encoded10); 85 + console.log(" Decoded:", decoded10); 86 + console.log(" Pass:", jsonData === decoded10); 87 + 88 + console.log("\n=== All Base64 tests completed ===");