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.

URL library

+598 -2
+1 -1
examples/spec/events.js
··· 1 1 import { test, summary } from './helpers.js'; 2 - import { EventEmitter } from 'events'; 2 + import { EventEmitter } from 'ant:events'; 3 3 4 4 console.log('EventEmitter Tests\n'); 5 5
+6
include/modules/url.h
··· 1 + #ifndef URL_H 2 + #define URL_H 3 + 4 + void init_url_module(void); 5 + 6 + #endif
+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.1.1.11') 77 + version_conf.set('ANT_VERSION', '0.1.1.12') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+2
src/main.c
··· 31 31 #include "modules/events.h" 32 32 #include "modules/performance.h" 33 33 #include "modules/uri.h" 34 + #include "modules/url.h" 34 35 35 36 int js_result = EXIT_SUCCESS; 36 37 ··· 197 198 init_events_module(); 198 199 init_performance_module(); 199 200 init_uri_module(); 201 + init_url_module(); 200 202 201 203 ant_register_library(shell_library, "ant:shell", NULL); 202 204 ant_register_library(ffi_library, "ant:ffi", NULL);
+588
src/modules/url.c
··· 1 + #include <stdlib.h> 2 + #include <stdio.h> 3 + #include <string.h> 4 + #include <ctype.h> 5 + 6 + #include "ant.h" 7 + #include "runtime.h" 8 + #include "modules/url.h" 9 + 10 + typedef struct { 11 + char *protocol; 12 + char *username; 13 + char *password; 14 + char *hostname; 15 + char *port; 16 + char *pathname; 17 + char *search; 18 + char *hash; 19 + } parsed_url_t; 20 + 21 + static void free_parsed_url(parsed_url_t *p) { 22 + if (p->protocol) free(p->protocol); 23 + if (p->username) free(p->username); 24 + if (p->password) free(p->password); 25 + if (p->hostname) free(p->hostname); 26 + if (p->port) free(p->port); 27 + if (p->pathname) free(p->pathname); 28 + if (p->search) free(p->search); 29 + if (p->hash) free(p->hash); 30 + } 31 + 32 + static char *url_encode_component(const char *str) { 33 + if (!str) return strdup(""); 34 + size_t len = strlen(str); 35 + char *out = malloc(len * 3 + 1); 36 + if (!out) return NULL; 37 + size_t j = 0; 38 + for (size_t i = 0; i < len; i++) { 39 + unsigned char c = (unsigned char)str[i]; 40 + if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { 41 + out[j++] = c; 42 + } else { 43 + snprintf(out + j, 4, "%%%02X", c); 44 + j += 3; 45 + } 46 + } 47 + out[j] = '\0'; 48 + return out; 49 + } 50 + 51 + static char *url_decode_component(const char *str) { 52 + if (!str) return strdup(""); 53 + size_t len = strlen(str); 54 + char *out = malloc(len + 1); 55 + if (!out) return NULL; 56 + size_t j = 0; 57 + for (size_t i = 0; i < len; i++) { 58 + if (str[i] == '%' && i + 2 < len && isxdigit(str[i+1]) && isxdigit(str[i+2])) { 59 + int hi = isdigit(str[i+1]) ? str[i+1] - '0' : tolower(str[i+1]) - 'a' + 10; 60 + int lo = isdigit(str[i+2]) ? str[i+2] - '0' : tolower(str[i+2]) - 'a' + 10; 61 + out[j++] = (char)((hi << 4) | lo); 62 + i += 2; 63 + } else if (str[i] == '+') { 64 + out[j++] = ' '; 65 + } else { 66 + out[j++] = str[i]; 67 + } 68 + } 69 + out[j] = '\0'; 70 + return out; 71 + } 72 + 73 + static int parse_url(const char *url_str, const char *base_str, parsed_url_t *out) { 74 + memset(out, 0, sizeof(*out)); 75 + 76 + const char *p = url_str; 77 + const char *end = url_str + strlen(url_str); 78 + 79 + if (base_str && *p == '/') { 80 + parsed_url_t base = {0}; 81 + if (parse_url(base_str, NULL, &base) < 0) return -1; 82 + out->protocol = base.protocol ? strdup(base.protocol) : NULL; 83 + out->username = base.username ? strdup(base.username) : strdup(""); 84 + out->password = base.password ? strdup(base.password) : strdup(""); 85 + out->hostname = base.hostname ? strdup(base.hostname) : NULL; 86 + out->port = base.port ? strdup(base.port) : strdup(""); 87 + 88 + char *path_copy = strdup(p); 89 + char *q = strchr(path_copy, '?'); 90 + char *h = strchr(path_copy, '#'); 91 + 92 + if (h) { 93 + out->hash = strdup(h); 94 + *h = '\0'; 95 + } else { 96 + out->hash = strdup(""); 97 + } 98 + 99 + if (q) { 100 + out->search = strdup(q); 101 + *q = '\0'; 102 + } else { 103 + out->search = strdup(""); 104 + } 105 + 106 + out->pathname = strdup(path_copy); 107 + free(path_copy); 108 + 109 + free(base.protocol); free(base.username); free(base.password); 110 + free(base.hostname); free(base.port); free(base.pathname); 111 + free(base.search); free(base.hash); 112 + return 0; 113 + } 114 + 115 + const char *scheme_end = strstr(p, "://"); 116 + if (!scheme_end) return -1; 117 + 118 + size_t scheme_len = scheme_end - p; 119 + out->protocol = malloc(scheme_len + 2); 120 + memcpy(out->protocol, p, scheme_len); 121 + out->protocol[scheme_len] = ':'; 122 + out->protocol[scheme_len + 1] = '\0'; 123 + p = scheme_end + 3; 124 + 125 + out->username = strdup(""); 126 + out->password = strdup(""); 127 + 128 + const char *at = strchr(p, '@'); 129 + const char *slash = strchr(p, '/'); 130 + if (at && (!slash || at < slash)) { 131 + const char *colon = strchr(p, ':'); 132 + if (colon && colon < at) { 133 + free(out->username); 134 + out->username = strndup(p, colon - p); 135 + free(out->password); 136 + out->password = strndup(colon + 1, at - colon - 1); 137 + } else { 138 + free(out->username); 139 + out->username = strndup(p, at - p); 140 + } 141 + p = at + 1; 142 + } 143 + 144 + slash = strchr(p, '/'); 145 + const char *qmark = strchr(p, '?'); 146 + const char *hash = strchr(p, '#'); 147 + 148 + const char *host_end = slash ? slash : (qmark ? qmark : (hash ? hash : end)); 149 + char *host_part = strndup(p, host_end - p); 150 + 151 + char *port_sep = strrchr(host_part, ':'); 152 + if (port_sep && strchr(port_sep, ']') == NULL) { 153 + *port_sep = '\0'; 154 + out->port = strdup(port_sep + 1); 155 + out->hostname = strdup(host_part); 156 + } else { 157 + out->hostname = strdup(host_part); 158 + out->port = strdup(""); 159 + } 160 + free(host_part); 161 + p = host_end; 162 + 163 + if (slash) { 164 + const char *path_end = qmark ? qmark : (hash ? hash : end); 165 + out->pathname = strndup(slash, path_end - slash); 166 + p = path_end; 167 + } else { 168 + out->pathname = strdup("/"); 169 + } 170 + 171 + if (qmark && (!hash || qmark < hash)) { 172 + const char *search_end = hash ? hash : end; 173 + out->search = strndup(qmark, search_end - qmark); 174 + p = search_end; 175 + } else { 176 + out->search = strdup(""); 177 + } 178 + 179 + if (hash) { 180 + out->hash = strdup(hash); 181 + } else { 182 + out->hash = strdup(""); 183 + } 184 + 185 + return 0; 186 + } 187 + 188 + static char *build_href( 189 + const char *protocol, const char *username, const char *password, 190 + const char *hostname, const char *port, const char *pathname, 191 + const char *search, const char *hash 192 + ) { 193 + size_t len = strlen(protocol) + 2 + strlen(hostname) + strlen(pathname) + strlen(search) + strlen(hash) + 32; 194 + if (username && *username) len += strlen(username) + strlen(password) + 2; 195 + if (port && *port) len += strlen(port) + 1; 196 + 197 + char *href = malloc(len); 198 + if (!href) return NULL; 199 + 200 + char *w = href; 201 + w += sprintf(w, "%s//", protocol); 202 + if (username && *username) { 203 + w += sprintf(w, "%s", username); 204 + if (password && *password) w += sprintf(w, ":%s", password); 205 + w += sprintf(w, "@"); 206 + } 207 + w += sprintf(w, "%s", hostname); 208 + if (port && *port) w += sprintf(w, ":%s", port); 209 + w += sprintf(w, "%s%s%s", pathname, search, hash); 210 + return href; 211 + } 212 + 213 + static void update_url_href(struct js *js, jsval_t url_obj) { 214 + char *protocol = js_getstr(js, js_get(js, url_obj, "protocol"), NULL); 215 + char *username = js_getstr(js, js_get(js, url_obj, "username"), NULL); 216 + char *password = js_getstr(js, js_get(js, url_obj, "password"), NULL); 217 + char *hostname = js_getstr(js, js_get(js, url_obj, "hostname"), NULL); 218 + char *port = js_getstr(js, js_get(js, url_obj, "port"), NULL); 219 + char *pathname = js_getstr(js, js_get(js, url_obj, "pathname"), NULL); 220 + char *search = js_getstr(js, js_get(js, url_obj, "search"), NULL); 221 + char *hash = js_getstr(js, js_get(js, url_obj, "hash"), NULL); 222 + 223 + char *host; 224 + if (port && *port) { 225 + size_t hlen = strlen(hostname) + strlen(port) + 2; 226 + host = malloc(hlen); 227 + snprintf(host, hlen, "%s:%s", hostname, port); 228 + } else { 229 + host = strdup(hostname ? hostname : ""); 230 + } 231 + js_set(js, url_obj, "host", js_mkstr(js, host, strlen(host))); 232 + 233 + char *origin; 234 + if (port && *port) { 235 + size_t olen = strlen(protocol) + strlen(hostname) + strlen(port) + 8; 236 + origin = malloc(olen); 237 + snprintf(origin, olen, "%s//%s:%s", protocol ? protocol : "", hostname ? hostname : "", port); 238 + } else { 239 + size_t olen = strlen(protocol) + strlen(hostname) + 8; 240 + origin = malloc(olen); 241 + snprintf(origin, olen, "%s//%s", protocol ? protocol : "", hostname ? hostname : ""); 242 + } 243 + js_set(js, url_obj, "origin", js_mkstr(js, origin, strlen(origin))); 244 + 245 + char *href = build_href( 246 + protocol ? protocol : "", username ? username : "", 247 + password ? password : "", hostname ? hostname : "", 248 + port ? port : "", pathname ? pathname : "/", 249 + search ? search : "", hash ? hash : "" 250 + ); 251 + 252 + js_set(js, url_obj, "href", js_mkstr(js, href, strlen(href))); 253 + 254 + free(host); 255 + free(origin); 256 + free(href); 257 + } 258 + 259 + static jsval_t url_toString(struct js *js, jsval_t *args, int nargs) { 260 + (void)args; (void)nargs; 261 + return js_get(js, js_getthis(js), "href"); 262 + } 263 + 264 + static jsval_t js_URL(struct js *js, jsval_t *args, int nargs) { 265 + if (nargs < 1) return js_mkerr(js, "TypeError: URL requires at least 1 argument"); 266 + 267 + char *url_str = js_getstr(js, args[0], NULL); 268 + char *base_str = (nargs > 1) ? js_getstr(js, args[1], NULL) : NULL; 269 + if (!url_str) return js_mkerr(js, "TypeError: Invalid URL"); 270 + 271 + parsed_url_t parsed; 272 + if (parse_url(url_str, base_str, &parsed) < 0) { 273 + return js_mkerr(js, "TypeError: Invalid URL"); 274 + } 275 + 276 + jsval_t url_obj = js_mkobj(js); 277 + 278 + js_set(js, url_obj, "protocol", js_mkstr(js, parsed.protocol, strlen(parsed.protocol))); 279 + js_set(js, url_obj, "username", js_mkstr(js, parsed.username, strlen(parsed.username))); 280 + js_set(js, url_obj, "password", js_mkstr(js, parsed.password, strlen(parsed.password))); 281 + js_set(js, url_obj, "hostname", js_mkstr(js, parsed.hostname, strlen(parsed.hostname))); 282 + js_set(js, url_obj, "port", js_mkstr(js, parsed.port, strlen(parsed.port))); 283 + js_set(js, url_obj, "pathname", js_mkstr(js, parsed.pathname, strlen(parsed.pathname))); 284 + js_set(js, url_obj, "search", js_mkstr(js, parsed.search, strlen(parsed.search))); 285 + js_set(js, url_obj, "hash", js_mkstr(js, parsed.hash, strlen(parsed.hash))); 286 + 287 + update_url_href(js, url_obj); 288 + 289 + jsval_t search_params; 290 + if (parsed.search && *parsed.search) { 291 + const char *qs = parsed.search[0] == '?' ? parsed.search + 1 : parsed.search; 292 + char code[1024]; 293 + snprintf(code, sizeof(code), "new URLSearchParams('%s')", qs); 294 + search_params = js_eval(js, code, strlen(code)); 295 + } else { 296 + search_params = js_eval(js, "new URLSearchParams()", 21); 297 + } 298 + js_set(js, search_params, "_url", url_obj); 299 + js_set(js, url_obj, "searchParams", search_params); 300 + 301 + js_set(js, url_obj, "toString", js_mkfun(url_toString)); 302 + 303 + free_parsed_url(&parsed); 304 + return url_obj; 305 + } 306 + 307 + static jsval_t usp_get(struct js *js, jsval_t *args, int nargs) { 308 + if (nargs < 1) return js_mknull(); 309 + jsval_t this_val = js_getthis(js); 310 + char *key = js_getstr(js, args[0], NULL); 311 + if (!key) return js_mknull(); 312 + 313 + jsval_t entries = js_get(js, this_val, "_entries"); 314 + if (js_type(entries) != JS_OBJ) return js_mknull(); 315 + 316 + jsval_t len_val = js_get(js, entries, "length"); 317 + int len = (js_type(len_val) == JS_NUM) ? (int)js_getnum(len_val) : 0; 318 + 319 + for (int i = 0; i < len; i++) { 320 + char idx[16]; 321 + snprintf(idx, sizeof(idx), "%d", i); 322 + jsval_t entry = js_get(js, entries, idx); 323 + jsval_t k = js_get(js, entry, "0"); 324 + char *ks = js_getstr(js, k, NULL); 325 + if (ks && strcmp(ks, key) == 0) { 326 + return js_get(js, entry, "1"); 327 + } 328 + } 329 + return js_mknull(); 330 + } 331 + 332 + static jsval_t usp_getAll(struct js *js, jsval_t *args, int nargs) { 333 + if (nargs < 1) return js_mkarr(js); 334 + jsval_t this_val = js_getthis(js); 335 + char *key = js_getstr(js, args[0], NULL); 336 + if (!key) return js_mkarr(js); 337 + 338 + jsval_t result = js_mkarr(js); 339 + jsval_t entries = js_get(js, this_val, "_entries"); 340 + if (js_type(entries) != JS_OBJ) return result; 341 + 342 + jsval_t len_val = js_get(js, entries, "length"); 343 + int len = (js_type(len_val) == JS_NUM) ? (int)js_getnum(len_val) : 0; 344 + 345 + for (int i = 0; i < len; i++) { 346 + char idx[16]; 347 + snprintf(idx, sizeof(idx), "%d", i); 348 + jsval_t entry = js_get(js, entries, idx); 349 + jsval_t k = js_get(js, entry, "0"); 350 + char *ks = js_getstr(js, k, NULL); 351 + if (ks && strcmp(ks, key) == 0) { 352 + js_arr_push(js, result, js_get(js, entry, "1")); 353 + } 354 + } 355 + return result; 356 + } 357 + 358 + static jsval_t usp_has(struct js *js, jsval_t *args, int nargs) { 359 + if (nargs < 1) return js_mkfalse(); 360 + jsval_t this_val = js_getthis(js); 361 + char *key = js_getstr(js, args[0], NULL); 362 + if (!key) return js_mkfalse(); 363 + 364 + jsval_t entries = js_get(js, this_val, "_entries"); 365 + if (js_type(entries) != JS_OBJ) return js_mkfalse(); 366 + 367 + jsval_t len_val = js_get(js, entries, "length"); 368 + int len = (js_type(len_val) == JS_NUM) ? (int)js_getnum(len_val) : 0; 369 + 370 + for (int i = 0; i < len; i++) { 371 + char idx[16]; 372 + snprintf(idx, sizeof(idx), "%d", i); 373 + jsval_t entry = js_get(js, entries, idx); 374 + jsval_t k = js_get(js, entry, "0"); 375 + char *ks = js_getstr(js, k, NULL); 376 + if (ks && strcmp(ks, key) == 0) return js_mktrue(); 377 + } 378 + return js_mkfalse(); 379 + } 380 + 381 + static void usp_sync_url(struct js *js, jsval_t this_val) { 382 + jsval_t url_obj = js_get(js, this_val, "_url"); 383 + if (js_type(url_obj) != JS_OBJ) return; 384 + 385 + jsval_t entries = js_get(js, this_val, "_entries"); 386 + jsval_t len_val = js_get(js, entries, "length"); 387 + int len = (js_type(len_val) == JS_NUM) ? (int)js_getnum(len_val) : 0; 388 + 389 + size_t buf_size = 1024; 390 + char *buf = malloc(buf_size); 391 + buf[0] = '?'; 392 + size_t pos = 1; 393 + 394 + for (int i = 0; i < len; i++) { 395 + char idx[16]; 396 + snprintf(idx, sizeof(idx), "%d", i); 397 + jsval_t entry = js_get(js, entries, idx); 398 + char *k = js_getstr(js, js_get(js, entry, "0"), NULL); 399 + char *v = js_getstr(js, js_get(js, entry, "1"), NULL); 400 + if (!k) continue; 401 + char *ek = url_encode_component(k); 402 + char *ev = url_encode_component(v ? v : ""); 403 + size_t needed = strlen(ek) + strlen(ev) + 3; 404 + if (pos + needed >= buf_size) { 405 + buf_size = buf_size * 2 + needed; 406 + buf = realloc(buf, buf_size); 407 + } 408 + if (pos > 1) buf[pos++] = '&'; 409 + pos += sprintf(buf + pos, "%s=%s", ek, ev); 410 + free(ek); 411 + free(ev); 412 + } 413 + buf[pos] = '\0'; 414 + 415 + js_set(js, url_obj, "search", js_mkstr(js, buf, pos)); 416 + update_url_href(js, url_obj); 417 + free(buf); 418 + } 419 + 420 + static jsval_t usp_set(struct js *js, jsval_t *args, int nargs) { 421 + if (nargs < 2) return js_mkundef(); 422 + jsval_t this_val = js_getthis(js); 423 + char *key = js_getstr(js, args[0], NULL); 424 + if (!key) return js_mkundef(); 425 + 426 + jsval_t entries = js_get(js, this_val, "_entries"); 427 + jsval_t len_val = js_get(js, entries, "length"); 428 + int len = (js_type(len_val) == JS_NUM) ? (int)js_getnum(len_val) : 0; 429 + 430 + jsval_t new_entries = js_mkarr(js); 431 + int found = 0; 432 + 433 + for (int i = 0; i < len; i++) { 434 + char idx[16]; 435 + snprintf(idx, sizeof(idx), "%d", i); 436 + jsval_t entry = js_get(js, entries, idx); 437 + char *ks = js_getstr(js, js_get(js, entry, "0"), NULL); 438 + if (ks && strcmp(ks, key) == 0) { 439 + if (!found) { 440 + jsval_t new_entry = js_mkarr(js); 441 + js_arr_push(js, new_entry, args[0]); 442 + js_arr_push(js, new_entry, args[1]); 443 + js_arr_push(js, new_entries, new_entry); 444 + found = 1; 445 + } 446 + } else { 447 + js_arr_push(js, new_entries, entry); 448 + } 449 + } 450 + 451 + if (!found) { 452 + jsval_t new_entry = js_mkarr(js); 453 + js_arr_push(js, new_entry, args[0]); 454 + js_arr_push(js, new_entry, args[1]); 455 + js_arr_push(js, new_entries, new_entry); 456 + } 457 + 458 + js_set(js, this_val, "_entries", new_entries); 459 + usp_sync_url(js, this_val); 460 + return js_mkundef(); 461 + } 462 + 463 + static jsval_t usp_append(struct js *js, jsval_t *args, int nargs) { 464 + if (nargs < 2) return js_mkundef(); 465 + jsval_t this_val = js_getthis(js); 466 + 467 + jsval_t entries = js_get(js, this_val, "_entries"); 468 + jsval_t entry = js_mkarr(js); 469 + js_arr_push(js, entry, args[0]); 470 + js_arr_push(js, entry, args[1]); 471 + js_arr_push(js, entries, entry); 472 + 473 + usp_sync_url(js, this_val); 474 + return js_mkundef(); 475 + } 476 + 477 + static jsval_t usp_delete(struct js *js, jsval_t *args, int nargs) { 478 + if (nargs < 1) return js_mkundef(); 479 + jsval_t this_val = js_getthis(js); 480 + char *key = js_getstr(js, args[0], NULL); 481 + if (!key) return js_mkundef(); 482 + 483 + jsval_t entries = js_get(js, this_val, "_entries"); 484 + jsval_t len_val = js_get(js, entries, "length"); 485 + int len = (js_type(len_val) == JS_NUM) ? (int)js_getnum(len_val) : 0; 486 + 487 + jsval_t new_entries = js_mkarr(js); 488 + for (int i = 0; i < len; i++) { 489 + char idx[16]; 490 + snprintf(idx, sizeof(idx), "%d", i); 491 + jsval_t entry = js_get(js, entries, idx); 492 + char *ks = js_getstr(js, js_get(js, entry, "0"), NULL); 493 + if (!ks || strcmp(ks, key) != 0) { 494 + js_arr_push(js, new_entries, entry); 495 + } 496 + } 497 + 498 + js_set(js, this_val, "_entries", new_entries); 499 + usp_sync_url(js, this_val); 500 + return js_mkundef(); 501 + } 502 + 503 + static jsval_t usp_toString(struct js *js, jsval_t *args, int nargs) { 504 + (void)args; (void)nargs; 505 + jsval_t this_val = js_getthis(js); 506 + jsval_t entries = js_get(js, this_val, "_entries"); 507 + jsval_t len_val = js_get(js, entries, "length"); 508 + int len = (js_type(len_val) == JS_NUM) ? (int)js_getnum(len_val) : 0; 509 + 510 + size_t buf_size = 1024; 511 + char *buf = malloc(buf_size); 512 + size_t pos = 0; 513 + 514 + for (int i = 0; i < len; i++) { 515 + char idx[16]; 516 + snprintf(idx, sizeof(idx), "%d", i); 517 + jsval_t entry = js_get(js, entries, idx); 518 + char *k = js_getstr(js, js_get(js, entry, "0"), NULL); 519 + char *v = js_getstr(js, js_get(js, entry, "1"), NULL); 520 + if (!k) continue; 521 + char *ek = url_encode_component(k); 522 + char *ev = url_encode_component(v ? v : ""); 523 + size_t needed = strlen(ek) + strlen(ev) + 3; 524 + if (pos + needed >= buf_size) { 525 + buf_size = buf_size * 2 + needed; 526 + buf = realloc(buf, buf_size); 527 + } 528 + if (pos > 0) buf[pos++] = '&'; 529 + pos += sprintf(buf + pos, "%s=%s", ek, ev); 530 + free(ek); 531 + free(ev); 532 + } 533 + buf[pos] = '\0'; 534 + jsval_t ret = js_mkstr(js, buf, pos); 535 + free(buf); 536 + return ret; 537 + } 538 + 539 + static jsval_t js_URLSearchParams(struct js *js, jsval_t *args, int nargs) { 540 + jsval_t usp = js_mkobj(js); 541 + jsval_t entries = js_mkarr(js); 542 + js_set(js, usp, "_entries", entries); 543 + 544 + if (nargs < 1 || js_type(args[0]) != JS_STR) goto done_parse; 545 + char *init = js_getstr(js, args[0], NULL); 546 + if (!init) goto done_parse; 547 + 548 + const char *p = init; 549 + if (*p == '?') p++; 550 + 551 + parse_pair: 552 + if (!*p) goto done_parse; 553 + const char *amp = strchr(p, '&'); 554 + size_t plen = amp ? (size_t)(amp - p) : strlen(p); 555 + char *pair = strndup(p, plen); 556 + char *eq = strchr(pair, '='); 557 + char *key = pair, *val = eq ? (eq[0] = '\0', eq + 1) : ""; 558 + char *dk = url_decode_component(key); 559 + char *dv = url_decode_component(val); 560 + jsval_t entry = js_mkarr(js); 561 + js_arr_push(js, entry, js_mkstr(js, dk, strlen(dk))); 562 + js_arr_push(js, entry, js_mkstr(js, dv, strlen(dv))); 563 + js_arr_push(js, entries, entry); 564 + free(pair); free(dk); free(dv); 565 + if (!amp) goto done_parse; 566 + p = amp + 1; 567 + goto parse_pair; 568 + 569 + done_parse: 570 + 571 + js_set(js, usp, "get", js_mkfun(usp_get)); 572 + js_set(js, usp, "getAll", js_mkfun(usp_getAll)); 573 + js_set(js, usp, "has", js_mkfun(usp_has)); 574 + js_set(js, usp, "set", js_mkfun(usp_set)); 575 + js_set(js, usp, "append", js_mkfun(usp_append)); 576 + js_set(js, usp, "delete", js_mkfun(usp_delete)); 577 + js_set(js, usp, "toString", js_mkfun(usp_toString)); 578 + 579 + return usp; 580 + } 581 + 582 + void init_url_module(void) { 583 + struct js *js = rt->js; 584 + jsval_t glob = js_glob(js); 585 + 586 + js_set(js, glob, "URL", js_mkfun(js_URL)); 587 + js_set(js, glob, "URLSearchParams", js_mkfun(js_URLSearchParams)); 588 + }