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.

improve json module

+237 -198
+1 -1
examples/results.txt
··· 905 905 compat-table/es6/misc.Proxy.get.Function.bind.js: TypeError: bind requires a function 906 906 compat-table/es6/misc.Proxy.get.HasBinding.js: failed 907 907 compat-table/es6/misc.Proxy.get.IteratorComplete.js: OK 908 - compat-table/es6/misc.Proxy.get.JSON.stringify.js: failed 908 + compat-table/es6/misc.Proxy.get.JSON.stringify.js: OK 909 909 compat-table/es6/misc.Proxy.get.Object.assign.js: failed 910 910 compat-table/es6/misc.Proxy.get.Object.defineProperties.js: failed 911 911 compat-table/es6/misc.Proxy.get.Promise.resolve.js: failed
+3
include/modules/json.h
··· 9 9 ant_value_t js_json_parse(ant_t *js, ant_value_t *args, int nargs); 10 10 ant_value_t js_json_stringify(ant_t *js, ant_value_t *args, int nargs); 11 11 12 + ant_value_t json_parse_value(ant_t *js, ant_value_t value); 13 + ant_value_t json_stringify_value(ant_t *js, ant_value_t value); 14 + 12 15 #endif
+1 -1
src/esm/loader.c
··· 924 924 925 925 ant_value_t json_str = js_mkstr(js, file.data, file.size); 926 926 free(file.data); 927 - return js_json_parse(js, &json_str, 1); 927 + return json_parse_value(js, json_str); 928 928 } 929 929 930 930 static ant_value_t esm_load_text(ant_t *js, const char *path) {
+7 -8
src/modules/fetch.c
··· 86 86 static ant_value_t response_json(ant_t *js, ant_value_t *args, int nargs) { 87 87 ant_value_t this = js_getthis(js); 88 88 ant_value_t body = js_get_slot(this, SLOT_DATA); 89 - ant_value_t parsed = js_json_parse(js, &body, 1); 89 + ant_value_t parsed = json_parse_value(js, body); 90 90 ant_value_t promise = js_mkpromise(js); 91 91 92 92 if (vtype(parsed) == T_ERR) { ··· 349 349 void gc_mark_fetch(ant_t *js, gc_mark_fn mark) { 350 350 if (!pending_requests) return; 351 351 unsigned int len = utarray_len(pending_requests); 352 + 352 353 for (unsigned int i = 0; i < len; i++) { 353 - fetch_request_t **reqp = (fetch_request_t **)utarray_eltptr(pending_requests, i); 354 - if (reqp && *reqp) { 355 - mark(js, (*reqp)->promise); 356 - mark(js, (*reqp)->headers_obj); 357 - } 358 - } 354 + fetch_request_t **reqp = (fetch_request_t **)utarray_eltptr(pending_requests, i); 355 + if (reqp && *reqp) { 356 + mark(js, (*reqp)->promise); 357 + mark(js, (*reqp)->headers_obj); 358 + }} 359 359 } 360 -
+157 -159
src/modules/json.c
··· 106 106 if (ctx->stack_size > 0) ctx->stack_size--; 107 107 } 108 108 109 - typedef struct { char *key; size_t key_len; ant_value_t value; } prop_entry; 110 - 111 - static int should_skip_prop(ant_t *js, const char *key, size_t key_len, ant_value_t value) { 112 - if (is_internal_prop(key, (ant_offset_t)key_len)) return 1; 113 - if (!is_special_object(value)) return 0; 114 - return vtype(js_get_slot(value, SLOT_CODE)) == T_CFUNC; 109 + static inline int key_matches(const char *a, size_t a_len, const char *b, size_t b_len) { 110 + return a_len == b_len && memcmp(a, b, a_len) == 0; 115 111 } 116 112 117 - static prop_entry *collect_props(ant_t *js, ant_value_t val, int *out_count) { 118 - prop_entry *props = NULL; 119 - int count = 0, cap = 0; 120 - const char *key; 121 - size_t key_len; 122 - ant_value_t value; 123 - 124 - ant_iter_t iter = js_prop_iter_begin(js, val); 125 - while (js_prop_iter_next(&iter, &key, &key_len, &value)) { 126 - if (should_skip_prop(js, key, key_len, value)) continue; 127 - 128 - if (count >= cap) { 129 - cap = cap ? cap * 2 : 8; 130 - props = realloc(props, cap * sizeof(prop_entry)); 131 - } 132 - 133 - props[count].key = malloc(key_len + 1); 134 - memcpy(props[count].key, key, key_len); 135 - props[count].key[key_len] = '\0'; 136 - props[count].key_len = key_len; 137 - props[count].value = value; 138 - count++; 139 - } 140 - js_prop_iter_end(&iter); 141 - 142 - *out_count = count; 143 - return props; 113 + static inline bool json_is_array(ant_value_t value) { 114 + return vtype(value) == T_ARR; 144 115 } 145 116 146 - static inline void free_props(prop_entry *props, int from, int to) { 147 - for (int i = from; i <= to; i++) free(props[i].key); 148 - free(props); 149 - } 150 - 151 - static inline int key_matches(const char *a, size_t a_len, const char *b, size_t b_len) { 152 - return a_len == b_len && memcmp(a, b, a_len) == 0; 117 + static inline ant_value_t json_snapshot_keys(ant_t *js, ant_value_t value) { 118 + if (!is_special_object(value)) return js_mkarr(js); 119 + return js_for_in_keys(js, value); 153 120 } 154 121 155 122 static int is_key_in_replacer_arr(ant_t *js, json_cycle_ctx *ctx, const char *key, size_t key_len) { 156 123 if (!is_special_object(ctx->replacer_arr)) return 1; 157 124 158 125 for (int i = 0; i < ctx->replacer_arr_len; i++) { 126 + char idxstr[32]; 127 + snprintf(idxstr, sizeof(idxstr), "%d", i); 128 + 129 + ant_value_t item = js_get(js, ctx->replacer_arr, idxstr); 130 + int type = vtype(item); 131 + 132 + if (type == T_STR) { 133 + size_t item_len; 134 + char *item_str = js_getstr(js, item, &item_len); 135 + if (key_matches(item_str, item_len, key, key_len)) return 1; 136 + } else if (type == T_NUM) { 137 + char numstr[32]; 138 + snprintf(numstr, sizeof(numstr), "%.0f", js_getnum(item)); 139 + if (key_matches(numstr, strlen(numstr), key, key_len)) return 1; 140 + }} 141 + 142 + return 0; 143 + } 144 + 145 + static yyjson_mut_val *ant_value_to_yyjson_with_key( 146 + ant_t *js, yyjson_mut_doc *doc, const char *key, 147 + ant_value_t val, json_cycle_ctx *ctx, int in_array 148 + ); 149 + 150 + static ant_value_t apply_reviver( 151 + ant_t *js, ant_value_t holder, 152 + const char *key, ant_value_t reviver 153 + ); 154 + 155 + static yyjson_mut_val *json_array_to_yyjson( 156 + ant_t *js, yyjson_mut_doc *doc, ant_value_t val, json_cycle_ctx *ctx 157 + ) { 158 + yyjson_mut_val *arr = yyjson_mut_arr(doc); 159 + ant_offset_t length = js_arr_len(js, val); 160 + ant_value_t saved_holder = ctx->holder; 161 + 162 + ctx->holder = val; 163 + for (ant_offset_t i = 0; i < length; i++) { 159 164 char idxstr[32]; 160 - snprintf(idxstr, sizeof(idxstr), "%d", i); 161 - ant_value_t item = js_get(js, ctx->replacer_arr, idxstr); 162 - int type = vtype(item); 165 + uint_to_str(idxstr, sizeof(idxstr), (uint64_t)i); 166 + ant_value_t elem = js_arr_get(js, val, i); 167 + yyjson_mut_val *item = ant_value_to_yyjson_with_key(js, doc, idxstr, elem, ctx, 1); 168 + if (ctx->has_cycle) { 169 + ctx->holder = saved_holder; 170 + return NULL; 171 + } 172 + yyjson_mut_arr_add_val(arr, item); 173 + } 174 + 175 + ctx->holder = saved_holder; 176 + return arr; 177 + } 178 + 179 + static yyjson_mut_val *json_object_to_yyjson( 180 + ant_t *js, yyjson_mut_doc *doc, ant_value_t val, json_cycle_ctx *ctx 181 + ) { 182 + yyjson_mut_val *obj = yyjson_mut_obj(doc); 183 + ant_value_t keys = json_snapshot_keys(js, val); 184 + ant_value_t saved_holder = ctx->holder; 185 + 186 + if (is_err(keys)) { 187 + ctx->has_cycle = 1; 188 + return NULL; 189 + } 190 + 191 + ctx->holder = val; 192 + ant_offset_t key_count = js_arr_len(js, keys); 193 + 194 + for (ant_offset_t i = 0; i < key_count; i++) { 195 + ant_value_t key_val = js_arr_get(js, keys, i); 196 + size_t key_len = 0; 197 + char *key = js_getstr(js, key_val, &key_len); 163 198 164 - if (type == T_STR) { 165 - size_t item_len; 166 - char *item_str = js_getstr(js, item, &item_len); 167 - if (key_matches(item_str, item_len, key, key_len)) return 1; 168 - } else if (type == T_NUM) { 169 - char numstr[32]; 170 - snprintf(numstr, sizeof(numstr), "%.0f", js_getnum(item)); 171 - if (key_matches(numstr, strlen(numstr), key, key_len)) return 1; 199 + if (!key) continue; 200 + if (!is_key_in_replacer_arr(js, ctx, key, key_len)) continue; 201 + 202 + ant_value_t prop = js_get(js, val, key); 203 + int ptype = vtype(prop); 204 + if (ptype == T_UNDEF || ptype == T_FUNC) continue; 205 + 206 + yyjson_mut_val *jval = ant_value_to_yyjson_with_key(js, doc, key, prop, ctx, 0); 207 + if (ctx->has_cycle) { 208 + ctx->holder = saved_holder; 209 + return NULL; 172 210 } 211 + 212 + if (jval == YYJSON_SKIP_VALUE) continue; 213 + yyjson_mut_obj_add(obj, yyjson_mut_strncpy(doc, key, key_len), jval); 173 214 } 174 - return 0; 215 + 216 + ctx->holder = saved_holder; 217 + return obj; 175 218 } 176 - 177 - static yyjson_mut_val *ant_value_to_yyjson_with_key(ant_t *js, yyjson_mut_doc *doc, const char *key, ant_value_t val, json_cycle_ctx *ctx, int in_array); 178 219 179 220 static yyjson_mut_val *ant_value_to_yyjson_impl(ant_t *js, yyjson_mut_doc *doc, ant_value_t val, json_cycle_ctx *ctx, int in_array) { 180 221 int type = vtype(val); 181 222 yyjson_mut_val *result = NULL; 182 223 183 224 if (is_special_object(val)) { 184 - ant_value_t toJSON = js_get(js, val, "toJSON"); 185 - if (vtype(toJSON) == T_FUNC) { 186 - ant_value_t r = sv_vm_call(js->vm, js, toJSON, js_mkundef(), &val, 1, NULL, false); 187 - if (vtype(r) == T_ERR) { ctx->has_cycle = 1; return NULL; } 188 - return ant_value_to_yyjson_impl(js, doc, r, ctx, in_array); 189 - } 190 - } 225 + ant_value_t toJSON = js_get(js, val, "toJSON"); 226 + if (vtype(toJSON) == T_FUNC) { 227 + ant_value_t r = sv_vm_call(js->vm, js, toJSON, js_mkundef(), &val, 1, NULL, false); 228 + if (vtype(r) == T_ERR) { ctx->has_cycle = 1; return NULL; } 229 + return ant_value_to_yyjson_impl(js, doc, r, ctx, in_array); 230 + }} 191 231 192 232 switch (type) { 193 233 case T_NULL: return yyjson_mut_null(doc); ··· 220 260 221 261 if (json_cycle_check(ctx, val)) return NULL; 222 262 json_cycle_push(ctx, val); 223 - 224 - ant_value_t length_val = js_get(js, val, "length"); 225 - 226 - if (vtype(length_val) == T_NUM) { 227 - yyjson_mut_val *arr = yyjson_mut_arr(doc); 228 - int length = (int)js_getnum(length_val); 229 - 230 - ant_value_t saved_holder = ctx->holder; 231 - ctx->holder = val; 232 - 233 - for (int i = 0; i < length; i++) { 234 - char idxstr[32]; 235 - snprintf(idxstr, sizeof(idxstr), "%d", i); 236 - ant_value_t elem = js_get(js, val, idxstr); 237 - yyjson_mut_val *item = ant_value_to_yyjson_with_key(js, doc, idxstr, elem, ctx, 1); 238 - if (ctx->has_cycle) { ctx->holder = saved_holder; goto done; } 239 - yyjson_mut_arr_add_val(arr, item); 240 - } 241 - ctx->holder = saved_holder; 242 - result = arr; 243 - goto done; 244 - } 245 - 246 - yyjson_mut_val *obj = yyjson_mut_obj(doc); 247 - int prop_count; 248 - prop_entry *props = collect_props(js, val, &prop_count); 249 - 250 - ant_value_t saved_holder = ctx->holder; 251 - ctx->holder = val; 252 - 253 - for (int i = 0; i < prop_count; i++) { 254 - prop_entry *p = &props[i]; 255 - 256 - if (!is_key_in_replacer_arr(js, ctx, p->key, p->key_len)) { 257 - free(p->key); continue; 258 - } 259 - 260 - int ptype = vtype(p->value); 261 - if (ptype == T_UNDEF || ptype == T_FUNC) { free(p->key); continue; } 262 - 263 - yyjson_mut_val *jval = ant_value_to_yyjson_with_key(js, doc, p->key, p->value, ctx, 0); 264 - if (ctx->has_cycle) { free_props(props, 0, i); ctx->holder = saved_holder; goto done; } 265 - if (jval == YYJSON_SKIP_VALUE) { free(p->key); continue; } 266 - 267 - yyjson_mut_obj_add(obj, yyjson_mut_strncpy(doc, p->key, p->key_len), jval); 268 - free(p->key); 269 - } 270 - 271 - ctx->holder = saved_holder; 272 - free(props); 273 - result = obj; 263 + 264 + result = json_is_array(val) 265 + ? json_array_to_yyjson(js, doc, val, ctx) 266 + : json_object_to_yyjson(js, doc, val, ctx); 274 267 275 - done: 276 268 json_cycle_pop(ctx); 277 269 return result; 278 270 } 279 271 280 - static yyjson_mut_val *ant_value_to_yyjson_with_key(ant_t *js, yyjson_mut_doc *doc, const char *key, ant_value_t val, json_cycle_ctx *ctx, int in_array) { 272 + static yyjson_mut_val *ant_value_to_yyjson_with_key( 273 + ant_t *js, yyjson_mut_doc *doc, const char *key, 274 + ant_value_t val, json_cycle_ctx *ctx, int in_array 275 + ) { 281 276 if (vtype(ctx->replacer_func) != T_FUNC) 282 277 return ant_value_to_yyjson_impl(js, doc, val, ctx, in_array); 283 278 ··· 297 292 return ant_value_to_yyjson_with_key(js, doc, "", val, ctx, 0); 298 293 } 299 294 300 - static ant_value_t apply_reviver(ant_t *js, ant_value_t holder, const char *key, ant_value_t reviver) { 301 - ant_value_t val = js_get(js, holder, key); 302 - 303 - if (is_special_object(val)) { 304 - ant_value_t len_val = js_get(js, val, "length"); 305 - if (vtype(len_val) == T_NUM) { 306 - int length = (int)js_getnum(len_val); 307 - for (int i = 0; i < length; i++) { 308 - char idxstr[32]; 309 - snprintf(idxstr, sizeof(idxstr), "%d", i); 310 - ant_value_t new_elem = apply_reviver(js, val, idxstr, reviver); 311 - if (vtype(new_elem) == T_UNDEF) js_delete_prop(js, val, idxstr, strlen(idxstr)); 312 - else js_set(js, val, idxstr, new_elem); 313 - } 314 - } else { 315 - const char *prop_key; 316 - size_t prop_key_len; 317 - ant_value_t prop_value; 318 - 319 - ant_value_t keys_arr = js_mkobj(js); 320 - int key_count = 0; 321 - ant_iter_t iter = js_prop_iter_begin(js, val); 322 - while (js_prop_iter_next(&iter, &prop_key, &prop_key_len, &prop_value)) { 323 - if (is_internal_prop(prop_key, (ant_offset_t)prop_key_len)) continue; 324 - char idxstr[32]; 325 - snprintf(idxstr, sizeof(idxstr), "%d", key_count); 326 - js_set(js, keys_arr, idxstr, js_mkstr(js, prop_key, prop_key_len)); 327 - key_count++; 328 - } 329 - js_prop_iter_end(&iter); 330 - 331 - for (int i = 0; i < key_count; i++) { 332 - char idxstr[32]; 333 - snprintf(idxstr, sizeof(idxstr), "%d", i); 334 - ant_value_t key_str = js_get(js, keys_arr, idxstr); 335 - size_t klen; 336 - char *kstr = js_getstr(js, key_str, &klen); 337 - ant_value_t new_val = apply_reviver(js, val, kstr, reviver); 338 - if (vtype(new_val) == T_UNDEF) js_delete_prop(js, val, kstr, strlen(kstr)); 339 - else js_set(js, val, kstr, new_val); 340 - } 341 - } 342 - } 343 - 295 + static ant_value_t apply_reviver_call(ant_t *js, ant_value_t holder, const char *key, ant_value_t reviver) { 344 296 ant_value_t key_str = js_mkstr(js, key, strlen(key)); 345 297 ant_value_t call_args[2] = { key_str, js_get(js, holder, key) }; 346 - 347 298 return sv_vm_call(js->vm, js, reviver, holder, call_args, 2, NULL, false); 348 299 } 349 300 301 + static void apply_reviver_to_array(ant_t *js, ant_value_t value, ant_value_t reviver) { 302 + ant_offset_t length = js_arr_len(js, value); 303 + 304 + for (ant_offset_t i = 0; i < length; i++) { 305 + char idxstr[32]; 306 + size_t idx_len = uint_to_str(idxstr, sizeof(idxstr), (uint64_t)i); 307 + ant_value_t new_elem = apply_reviver(js, value, idxstr, reviver); 308 + if (vtype(new_elem) == T_UNDEF) js_delete_prop(js, value, idxstr, idx_len); 309 + else js_set(js, value, idxstr, new_elem); 310 + } 311 + } 312 + 313 + static void apply_reviver_to_object(ant_t *js, ant_value_t value, ant_value_t reviver) { 314 + ant_value_t keys = json_snapshot_keys(js, value); 315 + if (is_err(keys) || vtype(keys) != T_ARR) return; 316 + 317 + ant_offset_t key_count = js_arr_len(js, keys); 318 + for (ant_offset_t i = 0; i < key_count; i++) { 319 + ant_value_t key_val = js_arr_get(js, keys, i); 320 + size_t key_len = 0; 321 + char *key = js_getstr(js, key_val, &key_len); 322 + if (!key) continue; 323 + ant_value_t new_val = apply_reviver(js, value, key, reviver); 324 + if (vtype(new_val) == T_UNDEF) js_delete_prop(js, value, key, key_len); 325 + else js_set(js, value, key, new_val); 326 + } 327 + } 328 + 329 + static ant_value_t apply_reviver(ant_t *js, ant_value_t holder, const char *key, ant_value_t reviver) { 330 + ant_value_t val = js_get(js, holder, key); 331 + 332 + if (json_is_array(val)) apply_reviver_to_array(js, val, reviver); 333 + else if (vtype(val) == T_OBJ) apply_reviver_to_object(js, val, reviver); 334 + 335 + return apply_reviver_call(js, holder, key, reviver); 336 + } 337 + 350 338 ant_value_t js_json_parse(ant_t *js, ant_value_t *args, int nargs) { 351 339 if (nargs < 1) return js_mkerr(js, "JSON.parse() requires at least 1 argument"); 352 340 if (vtype(args[0]) != T_STR) return js_mkerr(js, "JSON.parse() argument must be a string"); ··· 368 356 } 369 357 370 358 return result; 359 + } 360 + 361 + ant_value_t json_parse_value(ant_t *js, ant_value_t value) { 362 + ant_value_t args[1] = { value }; 363 + return js_json_parse(js, args, 1); 371 364 } 372 365 373 366 static yyjson_write_flag get_write_flags(ant_value_t *args, int nargs) { ··· 446 439 free(ctx.stack); 447 440 yyjson_mut_doc_free(doc); 448 441 return result; 442 + } 443 + 444 + ant_value_t json_stringify_value(ant_t *js, ant_value_t value) { 445 + ant_value_t args[1] = { value }; 446 + return js_json_stringify(js, args, 1); 449 447 } 450 448 451 449 void init_json_module() {
+1 -1
src/modules/request.c
··· 364 364 ant_value_t str = (data && size > 0) 365 365 ? js_mkstr(js, (const char *)data, size) 366 366 : js_mkstr(js, "", 0); 367 - ant_value_t parsed = js_json_parse(js, &str, 1); 367 + ant_value_t parsed = json_parse_value(js, str); 368 368 if (is_err(parsed)) js_reject_promise(js, promise, request_rejection_reason(js, parsed)); 369 369 else js_resolve_promise(js, promise, parsed); 370 370 break;
+44 -14
src/modules/response.c
··· 304 304 } 305 305 case BODY_JSON: { 306 306 ant_value_t str = (data && size > 0) ? js_mkstr(js, (const char *)data, size) : js_mkstr(js, "", 0); 307 - ant_value_t parsed = js_json_parse(js, &str, 1); 307 + ant_value_t parsed = json_parse_value(js, str); 308 308 if (is_err(parsed)) js_reject_promise(js, promise, response_rejection_reason(js, parsed)); 309 309 else js_resolve_promise(js, promise, parsed); 310 310 break; ··· 343 343 }} 344 344 } 345 345 346 - static uint8_t *concat_chunks(ant_t *js, ant_value_t chunks, size_t *out_size) { 346 + static bool response_chunk_is_uint8_array(ant_value_t chunk, TypedArrayData **out_ta) { 347 + if (!is_object_type(chunk)) return false; 348 + ant_value_t slot = js_get_slot(chunk, SLOT_BUFFER); 349 + TypedArrayData *ta = (TypedArrayData *)js_gettypedarray(slot); 350 + if (!ta || !ta->buffer || ta->buffer->is_detached) return false; 351 + if (ta->type != TYPED_ARRAY_UINT8) return false; 352 + *out_ta = ta; 353 + return true; 354 + } 355 + 356 + static uint8_t *concat_uint8_chunks( 357 + ant_t *js, ant_value_t chunks, 358 + size_t *out_size, ant_value_t *err_out 359 + ) { 347 360 ant_offset_t n = js_arr_len(js, chunks); 348 361 size_t total = 0; 349 362 size_t pos = 0; 350 363 uint8_t *buf = NULL; 364 + TypedArrayData *ta = NULL; 365 + 366 + *out_size = 0; 367 + *err_out = js_mkundef(); 351 368 352 369 for (ant_offset_t i = 0; i < n; i++) { 353 370 ant_value_t chunk = js_arr_get(js, chunks, i); 354 - if (vtype(chunk) != T_TYPEDARRAY) continue; 355 - TypedArrayData *ta = (TypedArrayData *)js_gettypedarray(chunk); 356 - if (ta && ta->buffer && !ta->buffer->is_detached) total += ta->byte_length; 371 + if (!response_chunk_is_uint8_array(chunk, &ta)) { 372 + *err_out = js_mkerr_typed(js, JS_ERR_TYPE, "Response body stream chunk must be a Uint8Array"); 373 + return NULL; 374 + } 375 + total += ta->byte_length; 357 376 } 358 377 359 378 buf = total > 0 ? malloc(total) : NULL; 360 - if (total > 0 && !buf) return NULL; 379 + if (total > 0 && !buf) { 380 + *err_out = js_mkerr(js, "out of memory"); 381 + return NULL; 382 + } 361 383 362 384 for (ant_offset_t i = 0; i < n; i++) { 363 385 ant_value_t chunk = js_arr_get(js, chunks, i); 364 - if (vtype(chunk) != T_TYPEDARRAY) continue; 365 - TypedArrayData *ta = (TypedArrayData *)js_gettypedarray(chunk); 366 - if (!ta || !ta->buffer || ta->buffer->is_detached || ta->byte_length == 0) continue; 386 + if (!response_chunk_is_uint8_array(chunk, &ta)) { 387 + free(buf); 388 + *err_out = js_mkerr_typed(js, JS_ERR_TYPE, "Response body stream chunk must be a Uint8Array"); 389 + return NULL; 390 + } 391 + if (ta->byte_length == 0) continue; 367 392 memcpy(buf + pos, ta->buffer->data + ta->byte_offset, ta->byte_length); 368 393 pos += ta->byte_length; 369 394 } ··· 402 427 403 428 if (vtype(done_val) == T_BOOL && done_val == js_true) { 404 429 size_t size = 0; 405 - uint8_t *data = concat_chunks(js, chunks, &size); 430 + ant_value_t chunk_err = js_mkundef(); 431 + uint8_t *data = concat_uint8_chunks(js, chunks, &size, &chunk_err); 432 + if (is_err(chunk_err)) { 433 + js_reject_promise(js, promise, response_rejection_reason(js, chunk_err)); 434 + return js_mkundef(); 435 + } 406 436 ant_value_t type_v = js_get(js, state, "type"); 407 437 const char *body_type = (vtype(type_v) == T_STR) ? js_getstr(js, type_v, NULL) : NULL; 408 438 resolve_body_promise(js, promise, data, size, body_type, mode, true); ··· 461 491 } 462 492 463 493 stream = js_get_slot(this, SLOT_RESPONSE_BODY_STREAM); 464 - if (d->body_used || (d->body_is_stream && rs_is_stream(stream) && rs_stream_unusable(stream))) { 494 + if (d->body_used || (rs_is_stream(stream) && rs_stream_unusable(stream))) { 465 495 js_reject_promise(js, promise, response_rejection_reason(js, 466 496 js_mkerr_typed(js, JS_ERR_TYPE, "body stream is disturbed or locked"))); 467 497 return promise; 468 498 } 469 499 470 500 d->body_used = true; 471 - if (rs_is_stream(stream) && d->body_is_stream) 501 + if (rs_is_stream(stream)) 472 502 return consume_body_from_stream(js, stream, promise, mode, response_effective_body_type(js, this, d)); 473 503 474 504 resolve_body_promise(js, promise, d->body_data, d->body_size, response_effective_body_type(js, this, d), mode, true); ··· 778 808 bool init_has_content_type = false; 779 809 780 810 if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "Response.json requires 1 argument"); 781 - stringify = js_json_stringify(js, args, 1); 811 + stringify = json_stringify_value(js, args[0]); 782 812 if (is_err(stringify)) return stringify; 783 813 if (vtype(stringify) == T_UNDEF) { 784 814 return js_mkerr_typed(js, JS_ERR_TYPE, "Response.json data is not JSON serializable"); ··· 882 912 883 913 RES_GETTER_START(body_used) 884 914 ant_value_t stored_stream = js_get_slot(this, SLOT_RESPONSE_BODY_STREAM); 885 - bool used = d->body_used || (d->body_is_stream && rs_is_stream(stored_stream) && rs_stream_disturbed(stored_stream)); 915 + bool used = d->body_used || (rs_is_stream(stored_stream) && rs_stream_disturbed(stored_stream)); 886 916 return js_bool(used); 887 917 RES_GETTER_END 888 918
+1 -3
src/modules/server.c
··· 503 503 response_ctx_t *ctx = (response_ctx_t *)(unsigned long)js_getnum(ctx_val); 504 504 if (!ctx) return js_mkundef(); 505 505 506 - ant_value_t stringify_args[1] = { args[0] }; 507 - ant_value_t result = js_json_stringify(js, stringify_args, 1); 506 + ant_value_t result = json_stringify_value(js, args[0]); 508 507 509 508 if (vtype(result) == T_STR) { 510 509 size_t len; ··· 1031 1030 void init_server_module() { 1032 1031 js_set(rt->js, rt->ant_obj, "serve", js_mkfun(js_serve)); 1033 1032 } 1034 -
+1 -2
src/modules/util.c
··· 97 97 } 98 98 99 99 static bool util_sb_append_json(ant_t *js, util_sb_t *sb, ant_value_t v) { 100 - ant_value_t stringify_args[1] = {v}; 101 - ant_value_t json = js_json_stringify(js, stringify_args, 1); 100 + ant_value_t json = json_stringify_value(js, v); 102 101 if (vtype(json) != T_STR) { 103 102 return util_sb_append_n(sb, "[Circular]", 10); 104 103 }
+4 -8
src/modules/worker_threads.c
··· 81 81 const char *raw = getenv(WT_ENV_STORE_JSON); 82 82 if (raw && raw[0]) { 83 83 ant_value_t input = js_mkstr(js, raw, strlen(raw)); 84 - ant_value_t parse_args[1] = {input}; 85 - ant_value_t parsed = js_json_parse(js, parse_args, 1); 84 + ant_value_t parsed = json_parse_value(js, input); 86 85 if (is_object_type(parsed)) store = parsed; 87 86 } 88 87 } ··· 411 410 ant_t *js = wt->js; 412 411 413 412 ant_value_t s = js_mkstr(js, json, len); 414 - ant_value_t parse_args[1] = {s}; 415 - ant_value_t msg = js_json_parse(js, parse_args, 1); 413 + ant_value_t msg = json_parse_value(js, s); 416 414 if (is_err(msg)) msg = s; 417 415 418 416 wt_emit(wt, "message", msg); ··· 914 912 ant_value_t value_json = js_json_stringify(js, value_stringify_args, 1); 915 913 if (vtype(value_json) != T_STR) return js_mkerr(js, "setEnvironmentData value must be JSON-serializable"); 916 914 917 - ant_value_t parse_args[1] = {value_json}; 918 - ant_value_t cloned = js_json_parse(js, parse_args, 1); 915 + ant_value_t cloned = json_parse_value(js, value_json); 919 916 if (is_err(cloned)) return js_mkerr(js, "setEnvironmentData value must be JSON-serializable"); 920 917 921 918 size_t key_len = 0; ··· 1016 1013 const char *worker_data_json = getenv(WT_ENV_DATA_JSON); 1017 1014 if (worker_data_json && worker_data_json[0]) { 1018 1015 ant_value_t raw = js_mkstr(js, worker_data_json, strlen(worker_data_json)); 1019 - ant_value_t parse_args[1] = {raw}; 1020 - ant_value_t parsed = js_json_parse(js, parse_args, 1); 1016 + ant_value_t parsed = json_parse_value(js, raw); 1021 1017 js_set(js, lib, "workerData", is_err(parsed) ? js_mkundef() : parsed); 1022 1018 } else js_set(js, lib, "workerData", js_mkundef()); 1023 1019 } else {
+17 -1
src/streams/pipes.c
··· 11 11 #include "streams/pipes.h" 12 12 #include "streams/readable.h" 13 13 #include "streams/writable.h" 14 + #include "modules/structured-clone.h" 14 15 15 16 static void pipes_chain_promise( 16 17 ant_t *js, ant_value_t value, ··· 365 366 366 367 ant_value_t reader_args[1] = { source }; 367 368 ant_value_t saved = js->new_target; 369 + 368 370 js->new_target = g_reader_proto; 369 371 ant_value_t reader = js_rs_reader_ctor(js, reader_args, 1); 370 372 js->new_target = saved; 373 + 371 374 if (is_err(reader)) return pipe_create_rejected(js, js->thrown_value); 375 + rs->disturbed = true; 372 376 373 377 ant_value_t writer = ws_acquire_writer(js, dest); 374 378 if (is_err(writer)) { ··· 585 589 } 586 590 587 591 static void tee_pull(ant_t *js, ant_value_t state); 592 + static ant_value_t tee_read_reject(ant_t *js, ant_value_t *args, int nargs); 588 593 589 594 static ant_value_t tee_cancel_both_resolve(ant_t *js, ant_value_t *args, int nargs) { 590 595 ant_value_t state = js_get_slot(js->current_func, SLOT_DATA); ··· 622 627 } 623 628 624 629 ant_value_t value = js_get(js, result, "value"); 630 + ant_value_t clone = value; 631 + 632 + if (!st->canceled1 && !st->canceled2) { 633 + ant_value_t clone_args[1] = { value }; 634 + clone = js_structured_clone(js, clone_args, 1); 635 + if (is_err(clone)) { 636 + tee_read_reject(js, &clone, 1); 637 + return js_mkundef(); 638 + }} 639 + 625 640 if (!st->canceled1) tee_enqueue_branch(js, branch1, value); 626 - if (!st->canceled2) tee_enqueue_branch(js, branch2, value); 641 + if (!st->canceled2) tee_enqueue_branch(js, branch2, clone); 642 + 627 643 return js_mkundef(); 628 644 } 629 645