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.

add support for non-configurable properties

+143 -126
+2
include/config.h
··· 19 19 #define SLOTMASK ~(((jsoff_t) ~0) >> 1) 20 20 #define CONSTMASK (~(((jsoff_t) ~0) >> 1) >> 1) 21 21 #define ARRMASK (~(((jsoff_t) ~0) >> 1) >> 2) 22 + #define NONCONFIGMASK (~(((jsoff_t) ~0) >> 1) >> 3) 23 + #define FLAGMASK (SLOTMASK | CONSTMASK | ARRMASK | NONCONFIGMASK) 22 24 23 25 typedef enum { 24 26 SLOT_NONE = 0,
+2
include/config.h.in
··· 11 11 #define SLOTMASK ~(((jsoff_t) ~0) >> 1) 12 12 #define CONSTMASK (~(((jsoff_t) ~0) >> 1) >> 1) 13 13 #define ARRMASK (~(((jsoff_t) ~0) >> 1) >> 2) 14 + #define NONCONFIGMASK (~(((jsoff_t) ~0) >> 1) >> 3) 15 + #define FLAGMASK (SLOTMASK | CONSTMASK | ARRMASK | NONCONFIGMASK) 14 16 15 17 typedef enum { 16 18 SLOT_NONE = 0,
+1 -1
meson.build
··· 86 86 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 87 87 88 88 version_conf = configuration_data() 89 - version_conf.set('ANT_VERSION', '0.3.1.11') 89 + version_conf.set('ANT_VERSION', '0.3.1.13') 90 90 version_conf.set('ANT_GIT_HASH', git_hash) 91 91 version_conf.set('ANT_BUILD_DATE', build_date) 92 92
+133 -120
src/ant.c
··· 1147 1147 if (stringify_depth >= MAX_STRINGIFY_DEPTH) return; 1148 1148 stringify_stack[stringify_depth++] = obj; 1149 1149 1150 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1150 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 1151 1151 while (next < js->brk && next != 0) { 1152 1152 jsoff_t header = loadoff(js, next); 1153 1153 if (!is_slot_prop(header)) { ··· 1173 1173 if (stringify_depth >= MAX_STRINGIFY_DEPTH) return; 1174 1174 stringify_stack[stringify_depth++] = obj; 1175 1175 1176 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1176 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 1177 1177 while (next < js->brk && next != 0) { 1178 1178 jsoff_t header = loadoff(js, next); 1179 1179 if (!is_slot_prop(header)) { ··· 1198 1198 if (stringify_depth >= MAX_STRINGIFY_DEPTH) return; 1199 1199 stringify_stack[stringify_depth++] = func_obj; 1200 1200 1201 - jsoff_t next = loadoff(js, (jsoff_t) vdata(func_obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1201 + jsoff_t next = loadoff(js, (jsoff_t) vdata(func_obj)) & ~(3U | FLAGMASK); 1202 1202 while (next < js->brk && next != 0) { 1203 1203 jsoff_t header = loadoff(js, next); 1204 1204 if (!is_slot_prop(header)) { ··· 1263 1263 1264 1264 push_stringify(obj); 1265 1265 size_t n = cpy(buf, len, "[ ", 2); 1266 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1266 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 1267 1267 jsoff_t length = 0; 1268 1268 jsoff_t scan = next; 1269 1269 ··· 1277 1277 if (vtype(val) == T_NUM) length = (jsoff_t) tod(val); 1278 1278 break; 1279 1279 } 1280 - scan = loadoff(js, scan) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1280 + scan = loadoff(js, scan) & ~(3U | FLAGMASK); 1281 1281 } 1282 1282 1283 1283 for (jsoff_t i = 0; i < length; i++) { ··· 1300 1300 found = true; 1301 1301 break; 1302 1302 } 1303 - prop = loadoff(js, prop) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1303 + prop = loadoff(js, prop) & ~(3U | FLAGMASK); 1304 1304 } 1305 1305 1306 1306 if (found) { ··· 1320 1320 1321 1321 push_stringify(obj); 1322 1322 size_t n = 0; 1323 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1323 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 1324 1324 jsoff_t length = 0; 1325 1325 jsoff_t scan = next; 1326 1326 ··· 1334 1334 if (vtype(val) == T_NUM) length = (jsoff_t) tod(val); 1335 1335 break; 1336 1336 } 1337 - scan = loadoff(js, scan) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1337 + scan = loadoff(js, scan) & ~(3U | FLAGMASK); 1338 1338 } 1339 1339 1340 1340 for (jsoff_t i = 0; i < length; i++) { ··· 1357 1357 found = true; 1358 1358 break; 1359 1359 } 1360 - prop = loadoff(js, prop) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1360 + prop = loadoff(js, prop) & ~(3U | FLAGMASK); 1361 1361 } 1362 1362 1363 1363 if (found) { ··· 1451 1451 push_stringify(proto_val); 1452 1452 1453 1453 bool has_proto_props = false; 1454 - jsoff_t proto_next = loadoff(js, (jsoff_t) vdata(proto_val)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1454 + jsoff_t proto_next = loadoff(js, (jsoff_t) vdata(proto_val)) & ~(3U | FLAGMASK); 1455 1455 1456 1456 while (proto_next < js->brk && proto_next != 0) { 1457 1457 jsoff_t pheader = loadoff(js, proto_next); ··· 1479 1479 stringify_indent++; 1480 1480 1481 1481 bool proto_first = true; 1482 - proto_next = loadoff(js, (jsoff_t) vdata(proto_val)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1482 + proto_next = loadoff(js, (jsoff_t) vdata(proto_val)) & ~(3U | FLAGMASK); 1483 1483 while (proto_next < js->brk && proto_next != 0) { 1484 1484 jsoff_t pheader = loadoff(js, proto_next); 1485 1485 if (is_slot_prop(pheader)) { proto_next = next_prop(pheader); continue; } ··· 1636 1636 continue_object_print: 1637 1637 1638 1638 stringify_indent++; 1639 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1639 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 1640 1640 bool first = true; 1641 1641 1642 1642 while (next < js->brk && next != 0) { ··· 1692 1692 next = next_prop(header); 1693 1693 } 1694 1694 1695 - next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1695 + next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 1696 1696 while (next < js->brk && next != 0) { 1697 1697 jsoff_t header = loadoff(js, next); 1698 1698 if (is_slot_prop(header)) { next = next_prop(header); continue; } ··· 1865 1865 stringify_indent++; 1866 1866 bool first = true; 1867 1867 1868 - jsoff_t next = loadoff(js, (jsoff_t) vdata(func_obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 1868 + jsoff_t next = loadoff(js, (jsoff_t) vdata(func_obj)) & ~(3U | FLAGMASK); 1869 1869 while (next < js->brk && next != 0) { 1870 1870 jsoff_t header = loadoff(js, next); 1871 1871 if (is_slot_prop(header)) { next = next_prop(header); continue; } ··· 2756 2756 jsoff_t max_idx = 0; 2757 2757 bool found_length_prop = false; 2758 2758 jsoff_t length_prop_val = 0; 2759 - jsoff_t scan = loadoff(js, (jsoff_t) vdata(arr)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 2759 + jsoff_t scan = loadoff(js, (jsoff_t) vdata(arr)) & ~(3U | FLAGMASK); 2760 2760 while (scan < js->brk && scan != 0) { 2761 2761 jsoff_t koff = loadoff(js, scan + (jsoff_t) sizeof(scan)); 2762 2762 jsoff_t klen = offtolen(loadoff(js, koff)); ··· 2774 2774 max_idx = (jsoff_t)(idx + 1); 2775 2775 } 2776 2776 } 2777 - scan = loadoff(js, scan) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 2777 + scan = loadoff(js, scan) & ~(3U | FLAGMASK); 2778 2778 } 2779 2779 if (found_length_prop) return length_prop_val; 2780 2780 return max_idx; ··· 2784 2784 if (vtype(arr) != T_ARR) return js_mkundef(); 2785 2785 char idxstr[16]; 2786 2786 size_t idxlen = uint_to_str(idxstr, sizeof(idxstr), (unsigned)idx); 2787 - jsoff_t prop = loadoff(js, (jsoff_t) vdata(arr)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 2787 + jsoff_t prop = loadoff(js, (jsoff_t) vdata(arr)) & ~(3U | FLAGMASK); 2788 2788 while (prop < js->brk && prop != 0) { 2789 2789 jsoff_t koff = loadoff(js, prop + (jsoff_t) sizeof(prop)); 2790 2790 jsoff_t klen = offtolen(loadoff(js, koff)); ··· 2792 2792 if (streq(key, klen, idxstr, idxlen)) { 2793 2793 return loadval(js, prop + (jsoff_t) (sizeof(prop) + sizeof(koff))); 2794 2794 } 2795 - prop = loadoff(js, prop) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 2795 + prop = loadoff(js, prop) & ~(3U | FLAGMASK); 2796 2796 } 2797 2797 return js_mkundef(); 2798 2798 } ··· 2800 2800 static inline bool is_const_prop(struct js *js, jsoff_t propoff) { 2801 2801 jsoff_t v = loadoff(js, propoff); 2802 2802 return (v & CONSTMASK) != 0; 2803 + } 2804 + 2805 + static inline bool is_nonconfig_prop(struct js *js, jsoff_t propoff) { 2806 + jsoff_t v = loadoff(js, propoff); 2807 + return (v & NONCONFIGMASK) != 0; 2803 2808 } 2804 2809 2805 2810 static inline uint64_t hash_key(const char *key, size_t len) { ··· 2872 2877 set_slot(js, mkval(T_OBJ, obj_off), SLOT_VERSION, tov((double)new_version)); 2873 2878 } 2874 2879 2875 - static jsval_t mkprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v, bool is_const) { 2880 + static jsval_t mkprop(struct js *js, jsval_t obj, jsval_t k, jsval_t v, jsoff_t flags) { 2876 2881 jsoff_t koff = (jsoff_t) vdata(k); 2877 2882 jsoff_t b, head = (jsoff_t) vdata(obj); 2878 2883 char buf[sizeof(koff) + sizeof(v)]; 2884 + 2879 2885 memcpy(&b, &js->mem[head], sizeof(b)); 2880 2886 memcpy(buf, &koff, sizeof(koff)); 2881 2887 memcpy(buf + sizeof(koff), &v, sizeof(v)); ··· 2886 2892 2887 2893 jsoff_t klen = (loadoff(js, koff) >> 2) - 1; 2888 2894 const char *p = (char *) &js->mem[koff + sizeof(koff)]; 2889 - (void)intern_string(p, klen); /* Ensure key is interned for fast lookup later */ 2895 + (void)intern_string(p, klen); 2890 2896 2891 - jsoff_t prop_header = (b & ~(3U | CONSTMASK | ARRMASK | SLOTMASK)) | T_PROP; 2892 - if (is_const) prop_header |= CONSTMASK; 2897 + jsoff_t prop_header = (b & ~(3U | FLAGMASK)) | T_PROP | flags; 2893 2898 jsval_t result = mkentity(js, prop_header, buf, sizeof(buf)); 2894 2899 2895 2900 increment_version(js, head); 2896 2901 return result; 2897 2902 } 2898 2903 2899 - static inline jsval_t mkprop_fast(struct js *js, jsval_t obj, jsval_t k, jsval_t v, bool is_const) { 2904 + static inline jsval_t mkprop_fast(struct js *js, jsval_t obj, jsval_t k, jsval_t v, jsoff_t flags) { 2900 2905 jsoff_t koff = (jsoff_t) vdata(k); 2901 2906 jsoff_t b, head = (jsoff_t) vdata(obj); 2902 2907 char buf[sizeof(koff) + sizeof(v)]; 2908 + 2903 2909 memcpy(&b, &js->mem[head], sizeof(b)); 2904 2910 memcpy(buf, &koff, sizeof(koff)); 2905 2911 memcpy(buf + sizeof(koff), &v, sizeof(v)); ··· 2908 2914 if (b & ARRMASK) brk |= ARRMASK; 2909 2915 memcpy(&js->mem[head], &brk, sizeof(brk)); 2910 2916 2911 - jsoff_t prop_header = (b & ~(3U | CONSTMASK | ARRMASK | SLOTMASK)) | T_PROP; 2912 - if (is_const) prop_header |= CONSTMASK; 2917 + jsoff_t prop_header = (b & ~(3U | FLAGMASK)) | T_PROP | flags; 2913 2918 return mkentity(js, prop_header, buf, sizeof(buf)); 2914 2919 } 2915 2920 ··· 2924 2929 memcpy(buf, &koff, sizeof(koff)); 2925 2930 memcpy(buf + sizeof(koff), &v, sizeof(v)); 2926 2931 2927 - jsoff_t prop_header = (b & ~(3U | CONSTMASK | ARRMASK | SLOTMASK)) | T_PROP; 2932 + jsoff_t prop_header = (b & ~(3U | FLAGMASK)) | T_PROP; 2928 2933 return mkentity(js, prop_header, buf, sizeof(buf)); 2929 2934 } 2930 2935 ··· 2940 2945 jsoff_t brk = js->brk | T_OBJ; 2941 2946 if (b & ARRMASK) brk |= ARRMASK; 2942 2947 memcpy(&js->mem[head], &brk, sizeof(brk)); 2943 - jsoff_t prop_header = (b & ~(3U | CONSTMASK | ARRMASK | SLOTMASK)) | T_PROP | SLOTMASK; 2948 + jsoff_t prop_header = (b & ~(3U | FLAGMASK)) | T_PROP | SLOTMASK; 2944 2949 2945 2950 return mkentity(js, prop_header, buf, sizeof(buf)); 2946 2951 } ··· 2948 2953 static jsoff_t search_slot(struct js *js, jsval_t obj, internal_slot_t slot) { 2949 2954 jsoff_t off = (jsoff_t) vdata(obj); 2950 2955 if (off >= js->brk) return 0; 2951 - jsoff_t next = loadoff(js, off) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 2956 + jsoff_t next = loadoff(js, off) & ~(3U | FLAGMASK); 2952 2957 jsoff_t header, koff; 2953 2958 2954 2959 check: ··· 2958 2963 koff = loadoff(js, next + sizeof(jsoff_t)); 2959 2964 if (koff == (jsoff_t)slot) return next; 2960 2965 advance: 2961 - next = header & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 2966 + next = header & ~(3U | FLAGMASK); 2962 2967 goto check; 2963 2968 } 2964 2969 ··· 2980 2985 } 2981 2986 2982 2987 static inline jsoff_t next_prop(jsoff_t header) { 2983 - return header & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 2988 + return header & ~(3U | FLAGMASK); 2984 2989 } 2985 2990 2986 2991 static jsval_t setup_func_prototype(struct js *js, jsval_t func) { ··· 2995 3000 jsval_t constructor_key = js_mkstr(js, "constructor", 11); 2996 3001 if (is_err(constructor_key)) return constructor_key; 2997 3002 2998 - jsval_t res = mkprop(js, proto_obj, constructor_key, func, false); 3003 + jsval_t res = mkprop(js, proto_obj, constructor_key, func, 0); 2999 3004 if (is_err(res)) return res; 3000 3005 js_set_descriptor(js, proto_obj, "constructor", 11, JS_DESC_W | JS_DESC_C); 3001 3006 ··· 3117 3122 if (len_off != 0) { 3118 3123 saveval(js, len_off + sizeof(jsoff_t) * 2, new_len); 3119 3124 increment_version(js, (jsoff_t)vdata(obj)); 3120 - } else mkprop(js, obj, len_key, new_len, false); 3125 + } else mkprop(js, obj, len_key, new_len, 0); 3121 3126 3122 3127 done_update: 3123 3128 return mkval(T_PROP, existing); ··· 3156 3161 } 3157 3162 } 3158 3163 3159 - jsval_t result = mkprop(js, obj, k, v, false); 3164 + jsval_t result = mkprop(js, obj, k, v, 0); 3160 3165 3161 3166 if (need_length_update) { 3162 3167 jsoff_t len_off = lkp_interned(js, obj, INTERN_LENGTH, 6); ··· 3165 3170 if (len_off != 0) { 3166 3171 saveval(js, len_off + sizeof(jsoff_t) * 2, new_len); 3167 3172 increment_version(js, (jsoff_t)vdata(obj)); 3168 - } else mkprop(js, obj, len_key, new_len, false); 3173 + } else mkprop(js, obj, len_key, new_len, 0); 3169 3174 } 3170 3175 3171 3176 return result; ··· 3178 3183 static jsval_t setprop_const(struct js *js, jsval_t obj, const char *key, size_t len, jsval_t v) { 3179 3184 jsval_t k = js_mkstr(js, key, len); 3180 3185 if (is_err(k)) return k; 3181 - return mkprop(js, obj, k, v, true); 3186 + return mkprop(js, obj, k, v, CONSTMASK); 3182 3187 } 3183 3188 3184 3189 static inline jsval_t setprop_fast(struct js *js, jsval_t obj, const char *key, size_t len, jsval_t v) { 3185 3190 jsval_t k = js_mkstr(js, key, len); 3186 3191 if (is_err(k)) return k; 3187 - return mkprop(js, obj, k, v, false); 3192 + return mkprop(js, obj, k, v, 0); 3188 3193 } 3189 3194 3190 3195 static jsval_t setprop_interned(struct js *js, jsval_t obj, const char *key, size_t len, jsval_t v) { ··· 3257 3262 } 3258 3263 3259 3264 static inline jsoff_t esize(jsoff_t w) { 3260 - jsoff_t cleaned = w & ~(CONSTMASK | ARRMASK | SLOTMASK); 3265 + jsoff_t cleaned = w & ~FLAGMASK; 3261 3266 switch (cleaned & 3U) { 3262 3267 case T_OBJ: return (jsoff_t) (sizeof(jsoff_t) + sizeof(jsoff_t)); 3263 3268 case T_PROP: return (jsoff_t) (sizeof(jsoff_t) + sizeof(jsoff_t) + sizeof(jsval_t)); ··· 3873 3878 return ce->prop_off; 3874 3879 } 3875 3880 3876 - jsoff_t off = loadoff(js, obj_off) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 3881 + jsoff_t off = loadoff(js, obj_off) & ~(3U | FLAGMASK); 3877 3882 while (off < js->brk && off != 0) { 3878 3883 jsoff_t header = loadoff(js, off); 3879 3884 if (is_slot_prop(header)) { off = next_prop(header); continue; } ··· 3912 3917 if (!search_intern) return 0; 3913 3918 3914 3919 jsoff_t scope_off = (jsoff_t)vdata(scope); 3915 - jsoff_t off = loadoff(js, scope_off) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 3920 + jsoff_t off = loadoff(js, scope_off) & ~(3U | FLAGMASK); 3916 3921 3917 3922 while (off < js->brk && off != 0) { 3918 3923 jsoff_t header = loadoff(js, off); ··· 5201 5206 v = js_mkundef(); 5202 5207 } 5203 5208 jsval_t k = js_mkstr(js, &fn[pp->name_off], pp->name_len); 5204 - if (!is_err(k)) mkprop_fast(js, function_scope, k, v, false); 5209 + if (!is_err(k)) mkprop_fast(js, function_scope, k, v, 0); 5205 5210 } 5206 5211 } 5207 5212 ··· 5245 5250 if (vtype(slot_name) == T_STR && vtype(func_val) == T_FUNC) { 5246 5251 jsoff_t len; 5247 5252 (void)vstr(js, slot_name, &len); 5248 - if (len > 0) mkprop_fast(js, function_scope, slot_name, func_val, true); 5253 + if (len > 0) mkprop_fast(js, function_scope, slot_name, func_val, CONSTMASK); 5249 5254 } 5250 5255 5251 5256 if (func_strict && (vtype(target_this) == T_UNDEF || vtype(target_this) == T_NULL || ··· 5386 5391 jsoff_t len; 5387 5392 (void)vstr(js, slot_name, &len); 5388 5393 if (len > 0) { 5389 - jsval_t prop = mkprop(js, function_scope, slot_name, func_val, true); 5390 - (void)prop; 5391 - } 5394 + jsval_t prop = mkprop(js, function_scope, slot_name, func_val, CONSTMASK); 5395 + (void)prop; 5396 + } 5392 5397 } 5393 5398 5394 5399 jsoff_t fnpos = 1; ··· 6780 6785 if (st != T_OBJ && st != T_ARR && st != T_FUNC) goto spread_next; 6781 6786 6782 6787 jsval_t src_obj = (st == T_OBJ) ? spread_obj : mkval(T_OBJ, vdata(spread_obj)); 6783 - jsoff_t next_prop_off = loadoff(js, (jsoff_t) vdata(src_obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 6788 + jsoff_t next_prop_off = loadoff(js, (jsoff_t) vdata(src_obj)) & ~(3U | FLAGMASK); 6784 6789 6785 6790 while (next_prop_off < js->brk && next_prop_off != 0) { 6786 6791 jsoff_t header = loadoff(js, next_prop_off); ··· 7662 7667 } 7663 7668 7664 7669 static void unlink_prop(struct js *js, jsoff_t obj_off, jsoff_t prop_off, jsoff_t prev_off) { 7665 - jsoff_t deleted_next = loadoff(js, prop_off) & ~(CONSTMASK | ARRMASK | SLOTMASK); 7670 + jsoff_t deleted_next = loadoff(js, prop_off) & ~FLAGMASK; 7666 7671 jsoff_t target = prev_off ? prev_off : obj_off; 7667 7672 jsoff_t current = loadoff(js, target); 7668 - saveoff(js, target, (deleted_next & ~3U) | (current & (CONSTMASK | ARRMASK | SLOTMASK | 3U))); 7673 + saveoff(js, target, (deleted_next & ~3U) | (current & (FLAGMASK | 3U))); 7669 7674 increment_version(js, obj_off); 7670 7675 } 7671 7676 ··· 7843 7848 jsoff_t prop_off = lkp(js, obj, key_str, len); 7844 7849 if (prop_off == 0) return js_mktrue(); 7845 7850 7846 - if (is_const_prop(js, prop_off)) { 7851 + if (is_nonconfig_prop(js, prop_off)) { 7847 7852 if (js->flags & F_STRICT) return js_mkerr_typed(js, JS_ERR_TYPE, "cannot delete non-configurable property"); 7848 7853 return js_mkfalse(); 7849 7854 } ··· 7854 7859 return js_mkfalse(); 7855 7860 } 7856 7861 7857 - jsoff_t first_prop = loadoff(js, obj_off) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 7862 + jsoff_t first_prop = loadoff(js, obj_off) & ~(3U | FLAGMASK); 7858 7863 if (first_prop == prop_off) { 7859 7864 unlink_prop(js, obj_off, prop_off, 0); 7860 7865 return js_mktrue(); 7861 7866 } 7862 7867 for (jsoff_t prev = first_prop; prev != 0; ) { 7863 - jsoff_t next_prop = loadoff(js, prev) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 7868 + jsoff_t next_prop = loadoff(js, prev) & ~(3U | FLAGMASK); 7864 7869 if (next_prop == prop_off) { unlink_prop(js, obj_off, prop_off, prev); return js_mktrue(); } 7865 7870 prev = next_prop; 7866 7871 } ··· 7870 7875 if (vtype(operand) != T_PROP) return js_mktrue(); 7871 7876 7872 7877 jsoff_t prop_off = (jsoff_t)vdata(operand); 7873 - if (is_const_prop(js, prop_off)) { 7874 - if (js->flags & F_STRICT) return js_mkerr(js, "cannot delete constant property"); 7878 + if (is_nonconfig_prop(js, prop_off)) { 7879 + if (js->flags & F_STRICT) return js_mkerr(js, "cannot delete non-configurable property"); 7875 7880 return js_mkfalse(); 7876 7881 } 7877 7882 ··· 7879 7884 bool is_first_prop = false; 7880 7885 for (jsoff_t off = 0; off < js->brk; ) { 7881 7886 jsoff_t v = loadoff(js, off); 7882 - jsoff_t cleaned = v & ~(CONSTMASK | ARRMASK | SLOTMASK); 7887 + jsoff_t cleaned = v & ~FLAGMASK; 7883 7888 jsoff_t n = esize(cleaned); 7884 7889 if ((cleaned & 3) == T_OBJ) { 7885 7890 jsoff_t first_prop = cleaned & ~3U; 7886 7891 if (first_prop == prop_off) { owner_obj_off = off; is_first_prop = true; break; } 7887 7892 for (jsoff_t cur = first_prop; cur != 0 && cur < js->brk; ) { 7888 - jsoff_t nx = loadoff(js, cur) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 7893 + jsoff_t nx = loadoff(js, cur) & ~(3U | FLAGMASK); 7889 7894 if (nx == prop_off) { owner_obj_off = off; prev_prop_off = cur; break; } 7890 7895 cur = nx; 7891 7896 } ··· 8414 8419 obj_destruct_rest:; 8415 8420 jsval_t rest_obj = mkobj(js, 0); 8416 8421 if (is_err(rest_obj)) return rest_obj; 8417 - jsoff_t scan = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 8422 + jsoff_t scan = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 8418 8423 while (scan < js->brk && scan != 0) { 8419 8424 jsoff_t header = loadoff(js, scan); 8420 8425 if (is_slot_prop(header)) { scan = next_prop(header); continue; } ··· 8442 8447 { 8443 8448 const char *vn = &js->code[var_off]; 8444 8449 if (lkp_scope(js, js->scope, vn, var_len) > 0) return js_mkerr(js, "'%.*s' already declared", (int)var_len, vn); 8445 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, vn, var_len), rest_obj, is_const); 8450 + jsval_t x = mkprop(js, js->scope, js_mkstr(js, vn, var_len), rest_obj, is_const ? CONSTMASK : 0); 8446 8451 if (is_err(x)) return x; 8447 8452 } 8448 8453 goto obj_destruct_next; ··· 8485 8490 8486 8491 jsoff_t ipoff = lkp(js, nobj, &js->code[isoff], islen); 8487 8492 jsval_t ival = ipoff > 0 ? resolveprop(js, mkval(T_PROP, ipoff)) : js_mkundef(); 8488 - jsval_t ix = mkprop(js, js->scope, js_mkstr(js, ivn, ivlen), ival, is_const); 8493 + jsval_t ix = mkprop(js, js->scope, js_mkstr(js, ivn, ivlen), ival, is_const ? CONSTMASK : 0); 8489 8494 if (is_err(ix)) return ix; 8490 8495 8491 8496 if (next(js) == TOK_RBRACE) break; ··· 8518 8523 pval = resolveprop(js, pval); 8519 8524 } 8520 8525 8521 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, vn, var_len), pval, is_const); 8526 + jsval_t x = mkprop(js, js->scope, js_mkstr(js, vn, var_len), pval, is_const ? CONSTMASK : 0); 8522 8527 if (is_err(x)) return x; 8523 8528 } 8524 8529 ··· 8641 8646 } 8642 8647 } 8643 8648 8644 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, var_name, var_len), prop_val, is_const); 8649 + jsval_t x = mkprop(js, js->scope, js_mkstr(js, var_name, var_len), prop_val, is_const ? CONSTMASK : 0); 8645 8650 if (is_err(x)) return x; 8646 8651 } 8647 8652 ··· 8677 8682 size_t decoded_len = decode_ident_escapes(name, nlen, decoded_name, sizeof(decoded_name)); 8678 8683 8679 8684 if (lkp_scope(js, js->scope, decoded_name, decoded_len) > 0) return js_mkerr(js, "'%.*s' already declared", (int) decoded_len, decoded_name); 8680 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, decoded_name, decoded_len), resolveprop(js, v), is_const); 8685 + jsval_t x = mkprop(js, js->scope, js_mkstr(js, decoded_name, decoded_len), resolveprop(js, v), is_const ? CONSTMASK : 0); 8681 8686 if (is_err(x)) return x; 8682 8687 } 8683 8688 } ··· 8802 8807 if (existing > 0) { 8803 8808 saveval(js, existing + sizeof(jsoff_t) * 2, func); 8804 8809 } else { 8805 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, name, nlen), func, false); 8810 + jsval_t x = mkprop(js, js->scope, js_mkstr(js, name, nlen), func, 0); 8806 8811 if (is_err(x)) return x; 8807 8812 } 8808 8813 } ··· 8867 8872 if (existing > 0) { 8868 8873 saveval(js, existing + sizeof(jsoff_t) * 2, func); 8869 8874 } else { 8870 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, name, nlen), func, false); 8875 + jsval_t x = mkprop(js, js->scope, js_mkstr(js, name, nlen), func, 0); 8871 8876 if (is_err(x)) return x; 8872 8877 } 8873 8878 } ··· 8953 8958 saveval(js, existing + sizeof(jsoff_t) * 2, value); 8954 8959 return js_mkundef(); 8955 8960 } 8956 - return mkprop(js, js->scope, js_mkstr(js, var_name, ctx->var_name_len), value, ctx->is_const_var); 8961 + return mkprop(js, js->scope, js_mkstr(js, var_name, ctx->var_name_len), value, ctx->is_const_var ? CONSTMASK : 0); 8957 8962 } 8958 8963 8959 8964 static jsval_t for_iter_exec_body(struct js *js, for_iter_ctx_t *ctx) { ··· 8975 8980 8976 8981 static jsval_t for_in_iter_object(struct js *js, for_iter_ctx_t *ctx, jsval_t obj) { 8977 8982 jsval_t iter_obj = (vtype(obj) == T_FUNC) ? mkval(T_OBJ, vdata(obj)) : obj; 8978 - jsoff_t prop_off = loadoff(js, (jsoff_t) vdata(iter_obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 8983 + jsoff_t prop_off = loadoff(js, (jsoff_t) vdata(iter_obj)) & ~(3U | FLAGMASK); 8979 8984 8980 8985 while (prop_off < js->brk && prop_off != 0) { 8981 8986 jsoff_t header = loadoff(js, prop_off); ··· 9005 9010 } 9006 9011 9007 9012 static jsval_t for_of_iter_array(struct js *js, for_iter_ctx_t *ctx, jsval_t iterable) { 9008 - jsoff_t next_prop_off = loadoff(js, (jsoff_t) vdata(iterable)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 9013 + jsoff_t next_prop_off = loadoff(js, (jsoff_t) vdata(iterable)) & ~(3U | FLAGMASK); 9009 9014 jsoff_t length = 0, scan = next_prop_off; 9010 9015 9011 9016 while (scan < js->brk && scan != 0) { ··· 9273 9278 iter_obj = mkval(T_OBJ, vdata(obj)); 9274 9279 } 9275 9280 9276 - jsoff_t prop_off = loadoff(js, (jsoff_t) vdata(iter_obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 9281 + jsoff_t prop_off = loadoff(js, (jsoff_t) vdata(iter_obj)) & ~(3U | FLAGMASK); 9277 9282 9278 9283 while (prop_off < js->brk && prop_off != 0) { 9279 9284 jsoff_t header = loadoff(js, prop_off); ··· 9310 9315 if (existing > 0) { 9311 9316 saveval(js, existing + sizeof(jsoff_t) * 2, key_str); 9312 9317 } else { 9313 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, var_name, var_name_len), key_str, is_const_var); 9318 + jsval_t x = mkprop(js, js->scope, js_mkstr(js, var_name, var_name_len), key_str, is_const_var ? CONSTMASK : 0); 9314 9319 if (is_err(x)) { 9315 9320 res = x; 9316 9321 goto done; ··· 9344 9349 } 9345 9350 } 9346 9351 9347 - prop_off = loadoff(js, prop_off) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 9352 + prop_off = loadoff(js, prop_off) & ~(3U | FLAGMASK); 9348 9353 } 9349 9354 } 9350 9355 ··· 9421 9426 mkscope(js); 9422 9427 iter_scope = true; 9423 9428 jsval_t var_key = js_mkstr(js, &js->code[let_var_off], let_var_len); 9424 - mkprop(js, js->scope, var_key, loop_var_val, false); 9429 + mkprop(js, js->scope, var_key, loop_var_val, 0); 9425 9430 } 9426 9431 9427 9432 js->flags |= F_LOOP; ··· 9827 9832 9828 9833 if (catch_param_len > 0) { 9829 9834 jsval_t key = js_mkstr(js, &js->code[catch_param_off], catch_param_len); 9830 - mkprop(js, js->scope, key, exception_value, false); 9835 + mkprop(js, js->scope, key, exception_value, 0); 9831 9836 } 9832 9837 9833 9838 js->flags = flags & (uint8_t)~F_NOEXEC; ··· 10706 10711 if (lkp_scope(js, js->scope, class_name, class_name_len) > 0) { 10707 10712 return js_mkerr(js, "'%.*s' already declared", (int) class_name_len, class_name); 10708 10713 } 10709 - jsval_t x = mkprop(js, js->scope, js_mkstr(js, class_name, class_name_len), constructor, false); 10714 + jsval_t x = mkprop(js, js->scope, js_mkstr(js, class_name, class_name_len), constructor, 0); 10710 10715 if (is_err(x)) return x; 10711 10716 } 10712 10717 ··· 10824 10829 setprop(js, var_scope, key_val, resolveprop(js, v)); 10825 10830 } 10826 10831 } else { 10827 - jsval_t x = mkprop(js, var_scope, js_mkstr(js, decoded_name, decoded_len), resolveprop(js, v), false); 10832 + jsval_t x = mkprop(js, var_scope, js_mkstr(js, decoded_name, decoded_len), resolveprop(js, v), 0); 10828 10833 if (is_err(x)) return x; 10829 10834 } 10830 10835 } ··· 12876 12881 12877 12882 jsval_t arr = mkarr(js); 12878 12883 jsoff_t idx = 0; 12879 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 12884 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 12880 12885 12881 12886 while (next < js->brk && next != 0) { 12882 12887 jsoff_t header = loadoff(js, next); ··· 12910 12915 } 12911 12916 } 12912 12917 12913 - next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 12918 + next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 12914 12919 while (next < js->brk && next != 0) { 12915 12920 jsoff_t header = loadoff(js, next); 12916 12921 if (is_slot_prop(header)) { next = next_prop(header); continue; } ··· 12990 12995 12991 12996 jsval_t arr = mkarr(js); 12992 12997 jsoff_t idx = 0; 12993 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 12998 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 12994 12999 12995 13000 while (next < js->brk && next != 0) { 12996 13001 jsoff_t header = loadoff(js, next); ··· 13048 13053 13049 13054 jsval_t arr = mkarr(js); 13050 13055 jsoff_t idx = 0; 13051 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 13056 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 13052 13057 13053 13058 while (next < js->brk && next != 0) { 13054 13059 jsoff_t header = loadoff(js, next); ··· 13200 13205 13201 13206 if (nargs >= 2 && vtype(args[1]) == T_OBJ) { 13202 13207 jsval_t props = args[1]; 13203 - jsoff_t next = loadoff(js, (jsoff_t) vdata(props)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 13208 + jsoff_t next = loadoff(js, (jsoff_t) vdata(props)) & ~(3U | FLAGMASK); 13204 13209 13205 13210 while (next < js->brk && next != 0) { 13206 13211 jsoff_t header = loadoff(js, next); ··· 13359 13364 js_set_descriptor(js, as_obj, prop_str, prop_len, desc_flags); 13360 13365 13361 13366 if (existing_off > 0) { 13362 - if (is_const_prop(js, existing_off)) { 13367 + if (is_nonconfig_prop(js, existing_off)) { 13363 13368 return js_mkerr(js, "Cannot redefine non-configurable property"); 13364 13369 } 13365 13370 ··· 13367 13372 saveval(js, existing_off + sizeof(jsoff_t) * 2, value); 13368 13373 } 13369 13374 13370 - if (!configurable) { 13375 + if (!writable || !configurable) { 13371 13376 jsoff_t head = (jsoff_t) vdata(as_obj); 13372 13377 jsoff_t firstprop = loadoff(js, head); 13373 - if ((firstprop & ~(3U | CONSTMASK | ARRMASK | SLOTMASK)) == existing_off) { 13374 - saveoff(js, head, firstprop | CONSTMASK); 13378 + if ((firstprop & ~(3U | FLAGMASK)) == existing_off) { 13379 + jsoff_t flags = 0; 13380 + if (!writable) flags |= CONSTMASK; 13381 + if (!configurable) flags |= NONCONFIGMASK; 13382 + saveoff(js, head, firstprop | flags); 13383 + } else { 13384 + jsoff_t prop_header = loadoff(js, existing_off); 13385 + jsoff_t flags = 0; 13386 + if (!writable) flags |= CONSTMASK; 13387 + if (!configurable) flags |= NONCONFIGMASK; 13388 + saveoff(js, existing_off, prop_header | flags); 13375 13389 } 13376 13390 } 13377 13391 } else { 13378 - if (!has_value) { 13379 - value = js_mkundef(); 13380 - } 13381 - 13392 + if (!has_value) value = js_mkundef(); 13382 13393 jsval_t prop_key = js_mkstr(js, prop_str, prop_len); 13383 - bool mark_const = !writable; 13384 - mkprop(js, as_obj, prop_key, value, mark_const); 13394 + jsoff_t flags = (writable ? 0 : CONSTMASK) | (configurable ? 0 : NONCONFIGMASK); 13395 + mkprop(js, as_obj, prop_key, value, flags); 13385 13396 } 13386 13397 } 13387 13398 ··· 13404 13415 } 13405 13416 13406 13417 jsval_t props_obj = props; 13407 - jsoff_t next = loadoff(js, (jsoff_t) vdata(props_obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 13418 + jsoff_t next = loadoff(js, (jsoff_t) vdata(props_obj)) & ~(3U | FLAGMASK); 13408 13419 13409 13420 while (next < js->brk && next != 0) { 13410 13421 jsoff_t header = loadoff(js, next); ··· 13451 13462 if (st != T_OBJ && st != T_ARR && st != T_FUNC) continue; 13452 13463 13453 13464 jsval_t src_obj = (st == T_OBJ) ? source : mkval(T_OBJ, vdata(source)); 13454 - jsoff_t next = loadoff(js, (jsoff_t) vdata(src_obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 13465 + jsoff_t next = loadoff(js, (jsoff_t) vdata(src_obj)) & ~(3U | FLAGMASK); 13455 13466 13456 13467 while (next < js->brk && next != 0) { 13457 13468 jsoff_t header = loadoff(js, next); ··· 13491 13502 if (t != T_OBJ && t != T_ARR && t != T_FUNC) return obj; 13492 13503 jsval_t as_obj = (t == T_OBJ) ? obj : mkval(T_OBJ, vdata(obj)); 13493 13504 13494 - jsoff_t next = loadoff(js, (jsoff_t) vdata(as_obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 13505 + jsoff_t next = loadoff(js, (jsoff_t) vdata(as_obj)) & ~(3U | FLAGMASK); 13495 13506 13496 13507 while (next < js->brk && next != 0) { 13497 13508 jsoff_t header = loadoff(js, next); ··· 13505 13516 next = next_prop(header); 13506 13517 if (is_internal_prop(key, klen)) continue; 13507 13518 13519 + jsoff_t freeze_flags = CONSTMASK | NONCONFIGMASK; 13508 13520 jsoff_t head = (jsoff_t) vdata(as_obj); 13509 13521 jsoff_t firstprop = loadoff(js, head); 13510 - if ((firstprop & ~(3U | CONSTMASK | ARRMASK | SLOTMASK)) == cur_prop) { 13511 - saveoff(js, head, firstprop | CONSTMASK); 13522 + if ((firstprop & ~(3U | FLAGMASK)) == cur_prop) { 13523 + saveoff(js, head, firstprop | freeze_flags); 13512 13524 } else { 13513 - jsoff_t prev = head; 13514 - jsoff_t scan = firstprop & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 13515 - while (scan < js->brk && scan != 0) { 13516 - if (scan == cur_prop) { 13517 - jsoff_t prev_val = loadoff(js, prev); 13518 - saveoff(js, prev, prev_val | CONSTMASK); 13519 - break; 13520 - } 13521 - prev = scan; 13522 - scan = loadoff(js, scan) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 13523 - } 13525 + jsoff_t prop_header = loadoff(js, cur_prop); 13526 + saveoff(js, cur_prop, prop_header | freeze_flags); 13524 13527 } 13525 13528 13526 13529 js_set_descriptor(js, as_obj, key, klen, JS_DESC_E); ··· 13552 13555 jsval_t as_obj = (t == T_OBJ) ? obj : mkval(T_OBJ, vdata(obj)); 13553 13556 13554 13557 set_slot(js, as_obj, SLOT_SEALED, js_mktrue()); 13555 - jsoff_t next = loadoff(js, (jsoff_t) vdata(as_obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 13558 + jsoff_t next = loadoff(js, (jsoff_t) vdata(as_obj)) & ~(3U | FLAGMASK); 13556 13559 13557 13560 while (next < js->brk && next != 0) { 13558 13561 jsoff_t header = loadoff(js, next); ··· 13562 13565 jsoff_t klen = offtolen(loadoff(js, koff)); 13563 13566 const char *key = (char *) &js->mem[koff + sizeof(koff)]; 13564 13567 13568 + jsoff_t cur_prop = next; 13565 13569 next = next_prop(header); 13566 13570 13567 13571 if (is_internal_prop(key, klen)) continue; 13572 + 13573 + jsoff_t head = (jsoff_t) vdata(as_obj); 13574 + jsoff_t firstprop = loadoff(js, head); 13575 + if ((firstprop & ~(3U | FLAGMASK)) == cur_prop) { 13576 + saveoff(js, head, firstprop | NONCONFIGMASK); 13577 + } else { 13578 + jsoff_t prop_header = loadoff(js, cur_prop); 13579 + saveoff(js, cur_prop, prop_header | NONCONFIGMASK); 13580 + } 13568 13581 13569 13582 js_set_descriptor(js, as_obj, key, klen, JS_DESC_W | JS_DESC_E); 13570 13583 } ··· 13696 13709 13697 13710 jsval_t arr = mkarr(js); 13698 13711 jsoff_t idx = 0; 13699 - jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 13712 + jsoff_t next = loadoff(js, (jsoff_t) vdata(obj)) & ~(3U | FLAGMASK); 13700 13713 13701 13714 while (next < js->brk && next != 0) { 13702 13715 jsoff_t header = loadoff(js, next); ··· 19025 19038 } 19026 19039 19027 19040 jsval_t key = js_mkstr(js, name, name_len); 19028 - mkprop(js, js->scope, key, resolveprop(js, value), is_const); 19041 + mkprop(js, js->scope, key, resolveprop(js, value), is_const ? CONSTMASK : 0); 19029 19042 setprop(js, js->module_ns, key, resolveprop(js, value)); 19030 19043 19031 19044 return value; ··· 20563 20576 saveval(js, existing + sizeof(jsoff_t) * 2, val); 20564 20577 } else { 20565 20578 jsval_t key_str = js_mkstr(js, key, key_len); 20566 - mkprop(js, obj, key_str, val, false); 20579 + mkprop(js, obj, key_str, val, 0); 20567 20580 } 20568 20581 } else if (vtype(obj) == T_FUNC) { 20569 20582 jsval_t func_obj = mkval(T_OBJ, vdata(obj)); ··· 20576 20589 saveval(js, existing + sizeof(jsoff_t) * 2, val); 20577 20590 } else { 20578 20591 jsval_t key_str = js_mkstr(js, key, key_len); 20579 - mkprop(js, func_obj, key_str, val, false); 20592 + mkprop(js, func_obj, key_str, val, 0); 20580 20593 } 20581 20594 } 20582 20595 } ··· 20596 20609 20597 20610 jsoff_t prop_off = lkp(js, obj, key, len); 20598 20611 if (prop_off == 0) return true; 20599 - if (is_const_prop(js, prop_off)) return false; 20612 + if (is_nonconfig_prop(js, prop_off)) return false; 20600 20613 20601 20614 descriptor_entry_t *desc = lookup_descriptor(obj_off, key, len); 20602 20615 if (desc && !desc->configurable) return false; 20603 20616 20604 - jsoff_t first_prop = loadoff(js, obj_off) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 20617 + jsoff_t first_prop = loadoff(js, obj_off) & ~(3U | FLAGMASK); 20605 20618 if (first_prop == prop_off) { 20606 - jsoff_t deleted_next = loadoff(js, prop_off) & ~(CONSTMASK | ARRMASK | SLOTMASK); 20619 + jsoff_t deleted_next = loadoff(js, prop_off) & ~FLAGMASK; 20607 20620 jsoff_t current = loadoff(js, obj_off); 20608 - saveoff(js, obj_off, (deleted_next & ~3U) | (current & (CONSTMASK | ARRMASK | SLOTMASK | 3U))); 20621 + saveoff(js, obj_off, (deleted_next & ~3U) | (current & (FLAGMASK | 3U))); 20609 20622 increment_version(js, obj_off); 20610 20623 return true; 20611 20624 } 20612 20625 20613 20626 jsoff_t prev = first_prop; 20614 20627 while (prev != 0) { 20615 - jsoff_t next_prop = loadoff(js, prev) & ~(CONSTMASK | ARRMASK | SLOTMASK); 20628 + jsoff_t next_prop = loadoff(js, prev) & ~FLAGMASK; 20616 20629 if (next_prop == prop_off) { 20617 - jsoff_t deleted_next = loadoff(js, prop_off) & ~(CONSTMASK | ARRMASK | SLOTMASK); 20618 - jsoff_t prev_flags = loadoff(js, prev) & (CONSTMASK | ARRMASK | SLOTMASK); 20630 + jsoff_t deleted_next = loadoff(js, prop_off) & ~FLAGMASK; 20631 + jsoff_t prev_flags = loadoff(js, prev) & FLAGMASK; 20619 20632 saveoff(js, prev, deleted_next | prev_flags); 20620 20633 increment_version(js, obj_off); 20621 20634 return true; ··· 20672 20685 20673 20686 void js_merge_obj(struct js *js, jsval_t dst, jsval_t src) { 20674 20687 if (vtype(dst) != T_OBJ || vtype(src) != T_OBJ) return; 20675 - jsoff_t next = loadoff(js, (jsoff_t) vdata(src)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 20688 + jsoff_t next = loadoff(js, (jsoff_t) vdata(src)) & ~(3U | FLAGMASK); 20676 20689 while (next < js->brk && next != 0) { 20677 20690 jsoff_t header = loadoff(js, next); 20678 20691 if (is_slot_prop(header)) { next = next_prop(header); continue; } ··· 21051 21064 21052 21065 if (vtype(obj) == T_OBJ || vtype(obj) == T_ARR || vtype(obj) == T_FUNC) { 21053 21066 jsval_t check_obj = (vtype(obj) == T_FUNC) ? mkval(T_OBJ, vdata(obj)) : obj; 21054 - jsoff_t next = loadoff(js, (jsoff_t) vdata(check_obj)) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 21067 + jsoff_t next = loadoff(js, (jsoff_t) vdata(check_obj)) & ~(3U | FLAGMASK); 21055 21068 iter.current = (void *)(uintptr_t)next; 21056 21069 } 21057 21070 ··· 21083 21096 21084 21097 if (value) *value = val; 21085 21098 21086 - jsoff_t next_off = loadoff(js, next) & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 21099 + jsoff_t next_off = loadoff(js, next) & ~(3U | FLAGMASK); 21087 21100 while (next_off < js->brk && next_off != 0) { 21088 21101 jsoff_t header = loadoff(js, next_off); 21089 21102 if (!is_slot_prop(header)) break; ··· 21115 21128 while (off < js->brk) { 21116 21129 memcpy(&v, &js->mem[off], sizeof(v)); 21117 21130 printf(" %5u: ", off); 21118 - jsoff_t cleaned = v & ~(CONSTMASK | ARRMASK | SLOTMASK); 21131 + jsoff_t cleaned = v & ~FLAGMASK; 21119 21132 if ((cleaned & 3U) == T_OBJ) { 21120 21133 printf("OBJ %u %u%s\n", cleaned & ~3U, loadoff(js, (jsoff_t) (off + sizeof(off))), (v & CONSTMASK) ? " [CONST]" : ""); 21121 21134 } else if ((cleaned & 3U) == T_PROP) { ··· 21129 21142 printf("???\n"); 21130 21143 break; 21131 21144 } 21132 - off += esize(v & ~(CONSTMASK | ARRMASK | SLOTMASK)); 21145 + off += esize(v & ~FLAGMASK); 21133 21146 } 21134 21147 } 21135 21148 #endif
+5 -5
src/gc.c
··· 87 87 } 88 88 89 89 static jsoff_t gc_esize(jsoff_t w) { 90 - jsoff_t cleaned = w & ~(CONSTMASK | ARRMASK | SLOTMASK); 90 + jsoff_t cleaned = w & ~FLAGMASK; 91 91 switch (cleaned & 3U) { 92 92 case JS_T_OBJ: return (jsoff_t)(sizeof(jsoff_t) + sizeof(jsoff_t)); 93 93 case JS_T_PROP: return (jsoff_t)(sizeof(jsoff_t) + sizeof(jsoff_t) + sizeof(jsval_t)); ··· 167 167 fwd_add(&ctx->fwd, old_off, new_off); 168 168 mark_set(ctx, old_off); 169 169 170 - jsoff_t next_prop = header & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 170 + jsoff_t next_prop = header & ~(3U | FLAGMASK); 171 171 if (next_prop != 0 && next_prop < ctx->js->brk) { 172 172 jsoff_t new_next = gc_copy_prop(ctx, next_prop); 173 - jsoff_t new_header = (new_next & ~3U) | (header & (3U | CONSTMASK | ARRMASK | SLOTMASK)); 173 + jsoff_t new_header = (new_next & ~3U) | (header & (3U | FLAGMASK)); 174 174 gc_saveoff(ctx->new_mem, new_off, new_header); 175 175 } 176 176 ··· 215 215 fwd_add(&ctx->fwd, old_off, new_off); 216 216 mark_set(ctx, old_off); 217 217 218 - jsoff_t first_prop = header & ~(3U | CONSTMASK | ARRMASK | SLOTMASK); 218 + jsoff_t first_prop = header & ~(3U | FLAGMASK); 219 219 if (first_prop != 0 && first_prop < ctx->js->brk) { 220 220 jsoff_t new_first = gc_copy_prop(ctx, first_prop); 221 - jsoff_t new_header = (new_first & ~3U) | (header & (3U | CONSTMASK | ARRMASK | SLOTMASK)); 221 + jsoff_t new_header = (new_first & ~3U) | (header & (3U | FLAGMASK)); 222 222 gc_saveoff(ctx->new_mem, new_off, new_header); 223 223 } 224 224