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.

property perf fixes

+73 -70
+1 -1
meson.build
··· 75 75 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 76 76 77 77 version_conf = configuration_data() 78 - version_conf.set('ANT_VERSION', '0.1.3.13') 78 + version_conf.set('ANT_VERSION', '0.1.3.14') 79 79 version_conf.set('ANT_GIT_HASH', git_hash) 80 80 version_conf.set('ANT_BUILD_DATE', build_date) 81 81
+72 -69
src/ant.c
··· 285 285 jsoff_t max_size; // maximum allowed memory size (for dynamic growth) 286 286 bool had_newline; // true if newline was crossed before current token 287 287 jsval_t thrown_value; // stores the actual thrown value for catch blocks 288 + bool has_descriptors; // true if defineProperty has ever been called 288 289 }; 289 290 290 291 enum { ··· 2908 2909 return result; 2909 2910 } 2910 2911 2911 - static jsval_t setprop_immutable(struct js *js, jsval_t obj, const char *key, size_t keylen, jsval_t v) { 2912 - jsval_t k = js_mkstr(js, key, keylen); 2913 - if (is_err(k)) return k; 2914 - jsval_t result = setprop(js, obj, k, v); 2915 - if (is_err(result)) return result; 2916 - 2917 - char desc_key[80]; 2918 - snprintf(desc_key, sizeof(desc_key), "__desc_%.*s", (int)keylen, key); 2919 - jsval_t desc_obj = mkobj(js, 0); 2920 - if (is_err(desc_obj)) return desc_obj; 2921 - setprop(js, desc_obj, js_mkstr(js, "configurable", 12), js_mkfalse()); 2922 - setprop(js, desc_obj, js_mkstr(js, "writable", 8), js_mkfalse()); 2923 - setprop(js, desc_obj, js_mkstr(js, "enumerable", 10), js_mkfalse()); 2924 - setprop(js, obj, js_mkstr(js, desc_key, strlen(desc_key)), desc_obj); 2925 - 2926 - return result; 2927 - } 2912 + 2928 2913 2929 2914 static uint64_t g_symbol_counter = 1; 2930 2915 ··· 4072 4057 return js_truthy(js, writable_val) ? 1 : 0; 4073 4058 } 4074 4059 4075 - static int find_and_check_writable(struct js *js, jsoff_t propoff) { 4076 - for (jsoff_t scan_off = 0; scan_off < js->brk; ) { 4060 + static int find_owner_and_check_writable(struct js *js, jsoff_t propoff, const char *key, jsoff_t klen, jsval_t *out_owner) { 4061 + for (jsoff_t scan_off = 0; scan_off < propoff; ) { 4077 4062 jsoff_t header = loadoff(js, scan_off); 4078 - jsoff_t cleaned = header & ~(GCMASK | CONSTMASK); 4063 + jsoff_t cleaned = header & ~(GCMASK | CONSTMASK | ARRMASK); 4079 4064 4080 4065 if ((cleaned & 3) != T_OBJ) { 4081 4066 scan_off += esize(cleaned); 4082 4067 continue; 4083 4068 } 4084 4069 4085 - jsval_t scan_obj = mkval(T_OBJ, scan_off); 4086 - jsoff_t next = loadoff(js, scan_off) & ~(3U | CONSTMASK | ARRMASK); 4087 - 4070 + jsoff_t next = cleaned & ~3U; 4088 4071 while (next < js->brk && next != 0) { 4089 4072 if (next == propoff) { 4090 - jsoff_t koff = loadoff(js, next + (jsoff_t) sizeof(next)); 4091 - jsoff_t klen = offtolen(loadoff(js, koff)); 4092 - const char *key = (char *) &js->mem[koff + sizeof(koff)]; 4073 + jsval_t obj = mkval(T_OBJ, scan_off); 4074 + *out_owner = obj; 4093 4075 4094 - int writable = check_prop_writable(js, scan_obj, key, klen); 4095 - return (writable == 0) ? 0 : 1; 4076 + char desc_key[128]; 4077 + snprintf(desc_key, sizeof(desc_key), "__desc_%.*s", (int)klen, key); 4078 + jsoff_t desc_off = lkp(js, obj, desc_key, strlen(desc_key)); 4079 + if (desc_off != 0) { 4080 + jsval_t desc_obj = loadval(js, desc_off + sizeof(jsoff_t) * 2); 4081 + if (vtype(desc_obj) == T_OBJ) { 4082 + jsoff_t set_off = lkp(js, desc_obj, "set", 3); 4083 + if (set_off != 0) { 4084 + jsval_t setter = loadval(js, set_off + sizeof(jsoff_t) * 2); 4085 + if (vtype(setter) == T_FUNC || vtype(setter) == T_CFUNC) return 2; 4086 + } 4087 + jsoff_t writable_off = lkp(js, desc_obj, "writable", 8); 4088 + if (writable_off != 0) { 4089 + jsval_t writable_val = resolveprop(js, mkval(T_PROP, writable_off)); 4090 + if (!js_truthy(js, writable_val)) return 0; 4091 + } 4092 + } 4093 + } 4094 + return 1; 4096 4095 } 4097 4096 next = loadoff(js, next) & ~(3U | CONSTMASK | ARRMASK); 4098 4097 } 4099 4098 4100 4099 scan_off += esize(cleaned); 4101 4100 } 4102 - return 1; 4101 + return -1; 4103 4102 } 4104 4103 4105 4104 static bool try_accessor_setter(struct js *js, jsval_t obj, const char *key, size_t key_len, jsval_t val, jsval_t *out) { ··· 4155 4154 jsoff_t klen = offtolen(loadoff(js, koff)); 4156 4155 const char *key = (char *)&js->mem[koff + sizeof(jsoff_t)]; 4157 4156 4158 - for (jsoff_t scan_off = 0; scan_off < propoff; ) { 4159 - jsoff_t header = loadoff(js, scan_off); 4160 - jsoff_t cleaned = header & ~(GCMASK | CONSTMASK | ARRMASK); 4161 - if ((cleaned & 3) == T_OBJ) { 4162 - jsoff_t next = cleaned & ~3U; 4163 - while (next < js->brk && next != 0) { 4164 - if (next == propoff) { 4165 - jsval_t obj = mkval(T_OBJ, scan_off); 4166 - jsval_t setter_result; 4167 - if (try_accessor_setter(js, obj, key, klen, val, &setter_result)) return setter_result; 4168 - break; 4169 - } 4170 - next = loadoff(js, next) & ~(3U | CONSTMASK | ARRMASK); 4171 - } 4172 - } 4173 - scan_off += esize(cleaned); 4174 - } 4175 - 4176 4157 if (is_const_prop(js, propoff)) { 4177 4158 if (js->flags & F_STRICT) return js_mkerr(js, "assignment to constant"); 4178 4159 return mkval(T_PROP, propoff); 4179 4160 } 4180 4161 4181 - if (!find_and_check_writable(js, propoff)) { 4162 + if ((klen == 9 && memcmp(key, "undefined", 9) == 0) || 4163 + (klen == 3 && memcmp(key, "NaN", 3) == 0) || 4164 + (klen == 8 && memcmp(key, "Infinity", 8) == 0)) { 4182 4165 if (js->flags & F_STRICT) return js_mkerr(js, "Cannot assign to read only property"); 4183 4166 return lhs; 4167 + } 4168 + 4169 + if (js->has_descriptors) { 4170 + jsval_t owner = js_mkundef(); 4171 + int check_result = find_owner_and_check_writable(js, propoff, key, klen, &owner); 4172 + 4173 + if (check_result == 2) { 4174 + jsval_t setter_result; 4175 + if (try_accessor_setter(js, owner, key, klen, val, &setter_result)) { 4176 + return setter_result; 4177 + } 4178 + } else if (check_result == 0) { 4179 + if (js->flags & F_STRICT) return js_mkerr(js, "Cannot assign to read only property"); 4180 + return lhs; 4181 + } 4184 4182 } 4185 4183 4186 4184 saveval(js, (jsoff_t) ((vdata(lhs) & ~3U) + sizeof(jsoff_t) * 2), val); ··· 8597 8595 jsval_t v, res = js_mkundef(); 8598 8596 jsoff_t pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; 8599 8597 8600 - if (!label_stack) { 8601 - utarray_new(label_stack, &label_entry_icd); 8598 + bool use_label_stack = label_stack && utarray_len(label_stack) > 0; 8599 + int marker_index = 0; 8600 + if (use_label_stack) { 8601 + label_entry_t marker = { .name = NULL, .name_len = 0, .is_loop = true, .is_block = false }; 8602 + utarray_push_back(label_stack, &marker); 8603 + marker_index = utarray_len(label_stack) - 1; 8602 8604 } 8603 - label_entry_t marker = { .name = NULL, .name_len = 0, .is_loop = true, .is_block = false }; 8604 - utarray_push_back(label_stack, &marker); 8605 - int marker_index = utarray_len(label_stack) - 1; 8606 8605 8607 8606 if (exe) mkscope(js); 8608 8607 if (!expect(js, TOK_FOR, &res)) goto done; ··· 8903 8902 } 8904 8903 js->pos = pos4, js->tok = TOK_SEMICOLON, js->consumed = 0; 8905 8904 done: 8906 - if (label_stack && utarray_len(label_stack) > 0) { 8905 + if (use_label_stack && label_stack && utarray_len(label_stack) > 0) { 8907 8906 utarray_pop_back(label_stack); 8908 8907 } 8909 8908 ··· 8926 8925 uint8_t flags = js->flags, exe = !(flags & F_NOEXEC); 8927 8926 jsval_t res = js_mkundef(), v; 8928 8927 8929 - if (!label_stack) { 8930 - utarray_new(label_stack, &label_entry_icd); 8928 + bool use_label_stack = label_stack && utarray_len(label_stack) > 0; 8929 + int marker_index = 0; 8930 + if (use_label_stack) { 8931 + label_entry_t marker = { .name = NULL, .name_len = 0, .is_loop = true, .is_block = false }; 8932 + utarray_push_back(label_stack, &marker); 8933 + marker_index = utarray_len(label_stack) - 1; 8931 8934 } 8932 - label_entry_t marker = { .name = NULL, .name_len = 0, .is_loop = true, .is_block = false }; 8933 - utarray_push_back(label_stack, &marker); 8934 - int marker_index = utarray_len(label_stack) - 1; 8935 8935 8936 8936 js->consumed = 1; 8937 8937 if (!expect(js, TOK_LPAREN, &res)) goto done; ··· 8996 8996 js->consumed = 0; 8997 8997 8998 8998 done: 8999 - if (label_stack && utarray_len(label_stack) > 0) { 8999 + if (use_label_stack && label_stack && utarray_len(label_stack) > 0) { 9000 9000 utarray_pop_back(label_stack); 9001 9001 } 9002 9002 ··· 9019 9019 uint8_t flags = js->flags, exe = !(flags & F_NOEXEC); 9020 9020 jsval_t res = js_mkundef(), v; 9021 9021 9022 - if (!label_stack) { 9023 - utarray_new(label_stack, &label_entry_icd); 9022 + bool use_label_stack = label_stack && utarray_len(label_stack) > 0; 9023 + int marker_index = 0; 9024 + if (use_label_stack) { 9025 + label_entry_t marker = { .name = NULL, .name_len = 0, .is_loop = true, .is_block = false }; 9026 + utarray_push_back(label_stack, &marker); 9027 + marker_index = utarray_len(label_stack) - 1; 9024 9028 } 9025 - label_entry_t marker = { .name = NULL, .name_len = 0, .is_loop = true, .is_block = false }; 9026 - utarray_push_back(label_stack, &marker); 9027 - int marker_index = utarray_len(label_stack) - 1; 9028 9029 9029 9030 js->consumed = 1; 9030 9031 ··· 9093 9094 js->consumed = 1; 9094 9095 9095 9096 done: 9096 - if (label_stack && utarray_len(label_stack) > 0) { 9097 + if (use_label_stack && label_stack && utarray_len(label_stack) > 0) { 9097 9098 utarray_pop_back(label_stack); 9098 9099 } 9099 9100 ··· 12593 12594 12594 12595 static jsval_t builtin_object_defineProperty(struct js *js, jsval_t *args, int nargs) { 12595 12596 if (nargs < 3) return js_mkerr(js, "Object.defineProperty requires 3 arguments"); 12597 + js->has_descriptors = true; 12596 12598 12597 12599 jsval_t obj = args[0]; 12598 12600 jsval_t prop = args[1]; ··· 19244 19246 js->lwm = js->size; 19245 19247 js->gct = js->size / 2; 19246 19248 js->this_val = js->scope; 19249 + js->has_descriptors = false; 19247 19250 js->errmsg_size = 4096; 19248 19251 js->errmsg = (char *)malloc(js->errmsg_size); 19249 19252 if (js->errmsg) js->errmsg[0] = '\0'; ··· 19685 19688 setprop(js, glob, js_mkstr(js, "isFinite", 8), js_mkfun(builtin_global_isFinite)); 19686 19689 setprop(js, glob, js_mkstr(js, "btoa", 4), js_mkfun(builtin_btoa)); 19687 19690 setprop(js, glob, js_mkstr(js, "atob", 4), js_mkfun(builtin_atob)); 19688 - setprop_immutable(js, glob, "NaN", 3, tov(NAN)); 19689 - setprop_immutable(js, glob, "Infinity", 8, tov(INFINITY)); 19690 - setprop_immutable(js, glob, "undefined", 9, js_mkundef()); 19691 + setprop(js, glob, js_mkstr(js, "NaN", 3), tov(NAN)); 19692 + setprop(js, glob, js_mkstr(js, "Infinity", 8), tov(INFINITY)); 19693 + setprop(js, glob, js_mkstr(js, "undefined", 9), js_mkundef()); 19691 19694 19692 19695 jsval_t math_obj = mkobj(js, 0); 19693 19696 set_proto(js, math_obj, object_proto);