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.

implement ALL of regex

+347 -66
+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.9') 77 + version_conf.set('ANT_VERSION', '0.1.1.10') 78 78 version_conf.set('ANT_GIT_HASH', git_hash) 79 79 version_conf.set('ANT_BUILD_DATE', build_date) 80 80
+346 -65
src/ant.c
··· 373 373 static bool streq(const char *buf, size_t len, const char *p, size_t n); 374 374 static size_t tostr(struct js *js, jsval_t value, char *buf, size_t len); 375 375 static size_t strpromise(struct js *js, jsval_t value, char *buf, size_t len); 376 + static size_t js_regex_to_posix(const char *src, size_t src_len, char *dst, size_t dst_size); 376 377 377 378 static inline jsoff_t esize(jsoff_t w); 378 379 static jsval_t js_expr(struct js *js); ··· 482 483 static jsval_t builtin_atob(struct js *js, jsval_t *args, int nargs); 483 484 static jsval_t builtin_Object(struct js *js, jsval_t *args, int nargs); 484 485 static jsval_t builtin_RegExp(struct js *js, jsval_t *args, int nargs); 486 + static jsval_t builtin_regexp_test(struct js *js, jsval_t *args, int nargs); 487 + static jsval_t builtin_regexp_exec(struct js *js, jsval_t *args, int nargs); 488 + static jsval_t builtin_string_search(struct js *js, jsval_t *args, int nargs); 485 489 static jsval_t builtin_Promise(struct js *js, jsval_t *args, int nargs); 486 490 static jsval_t builtin_Promise_resolve(struct js *js, jsval_t *args, int nargs); 487 491 static jsval_t builtin_Promise_reject(struct js *js, jsval_t *args, int nargs); ··· 4954 4958 jsval_t flags = js_mkstr(js, &js->code[flags_start], flags_end - flags_start); 4955 4959 4956 4960 jsval_t regexp_obj = mkobj(js, 0); 4961 + jsval_t regexp_proto = get_ctor_proto(js, "RegExp", 6); 4962 + if (vtype(regexp_proto) == T_OBJ) set_proto(js, regexp_obj, regexp_proto); 4963 + 4957 4964 setprop(js, regexp_obj, js_mkstr(js, "source", 6), pattern); 4958 4965 setprop(js, regexp_obj, js_mkstr(js, "flags", 5), flags); 4959 - 4966 + 4960 4967 jsoff_t flen = flags_end - flags_start; 4961 4968 const char *fstr = &js->code[flags_start]; 4962 - bool global = false, ignoreCase = false, multiline = false; 4969 + bool global = false, ignoreCase = false, multiline = false, dotAll = false, sticky = false; 4963 4970 for (jsoff_t i = 0; i < flen; i++) { 4964 4971 if (fstr[i] == 'g') global = true; 4965 4972 if (fstr[i] == 'i') ignoreCase = true; 4966 4973 if (fstr[i] == 'm') multiline = true; 4974 + if (fstr[i] == 's') dotAll = true; 4975 + if (fstr[i] == 'y') sticky = true; 4967 4976 } 4968 - 4977 + 4969 4978 setprop(js, regexp_obj, js_mkstr(js, "global", 6), mkval(T_BOOL, global ? 1 : 0)); 4970 4979 setprop(js, regexp_obj, js_mkstr(js, "ignoreCase", 10), mkval(T_BOOL, ignoreCase ? 1 : 0)); 4971 4980 setprop(js, regexp_obj, js_mkstr(js, "multiline", 9), mkval(T_BOOL, multiline ? 1 : 0)); 4972 - 4981 + setprop(js, regexp_obj, js_mkstr(js, "dotAll", 6), mkval(T_BOOL, dotAll ? 1 : 0)); 4982 + setprop(js, regexp_obj, js_mkstr(js, "sticky", 6), mkval(T_BOOL, sticky ? 1 : 0)); 4983 + 4973 4984 return regexp_obj; 4974 4985 } 4975 4986 ··· 8889 8900 if (!use_this) { 8890 8901 regexp_obj = mkobj(js, 0); 8891 8902 } 8892 - 8903 + jsval_t regexp_proto = get_ctor_proto(js, "RegExp", 6); 8904 + if (vtype(regexp_proto) == T_OBJ) set_proto(js, regexp_obj, regexp_proto); 8905 + 8893 8906 jsval_t pattern = js_mkstr(js, "", 0); 8894 8907 if (nargs > 0) { 8895 8908 if (vtype(args[0]) == T_STR) { ··· 8914 8927 jsoff_t flags_len, flags_off = vstr(js, flags, &flags_len); 8915 8928 const char *flags_str = (char *) &js->mem[flags_off]; 8916 8929 8917 - bool global = false, ignoreCase = false, multiline = false; 8930 + bool global = false, ignoreCase = false, multiline = false, dotAll = false, sticky = false; 8918 8931 for (jsoff_t i = 0; i < flags_len; i++) { 8919 8932 if (flags_str[i] == 'g') global = true; 8920 8933 if (flags_str[i] == 'i') ignoreCase = true; 8921 8934 if (flags_str[i] == 'm') multiline = true; 8935 + if (flags_str[i] == 's') dotAll = true; 8936 + if (flags_str[i] == 'y') sticky = true; 8922 8937 } 8923 - 8938 + 8924 8939 setprop(js, regexp_obj, js_mkstr(js, "global", 6), mkval(T_BOOL, global ? 1 : 0)); 8925 8940 setprop(js, regexp_obj, js_mkstr(js, "ignoreCase", 10), mkval(T_BOOL, ignoreCase ? 1 : 0)); 8926 8941 setprop(js, regexp_obj, js_mkstr(js, "multiline", 9), mkval(T_BOOL, multiline ? 1 : 0)); 8927 - 8942 + setprop(js, regexp_obj, js_mkstr(js, "dotAll", 6), mkval(T_BOOL, dotAll ? 1 : 0)); 8943 + setprop(js, regexp_obj, js_mkstr(js, "sticky", 6), mkval(T_BOOL, sticky ? 1 : 0)); 8944 + 8928 8945 return regexp_obj; 8929 8946 } 8930 8947 8948 + static jsval_t builtin_regexp_test(struct js *js, jsval_t *args, int nargs) { 8949 + jsval_t regexp = js->this_val; 8950 + if (vtype(regexp) != T_OBJ) return js_mkerr(js, "test called on non-regexp"); 8951 + if (nargs < 1) return mkval(T_BOOL, 0); 8952 + 8953 + jsval_t str_arg = args[0]; 8954 + if (vtype(str_arg) != T_STR) return mkval(T_BOOL, 0); 8955 + 8956 + jsoff_t source_off = lkp(js, regexp, "source", 6); 8957 + if (source_off == 0) return mkval(T_BOOL, 0); 8958 + jsval_t source_val = resolveprop(js, mkval(T_PROP, source_off)); 8959 + if (vtype(source_val) != T_STR) return mkval(T_BOOL, 0); 8960 + 8961 + jsoff_t plen, poff = vstr(js, source_val, &plen); 8962 + char pattern_buf[256]; 8963 + jsoff_t pattern_len = plen < sizeof(pattern_buf) - 1 ? plen : sizeof(pattern_buf) - 1; 8964 + memcpy(pattern_buf, &js->mem[poff], pattern_len); 8965 + pattern_buf[pattern_len] = '\0'; 8966 + 8967 + bool ignore_case = false; 8968 + jsoff_t flags_off = lkp(js, regexp, "flags", 5); 8969 + if (flags_off != 0) { 8970 + jsval_t flags_val = resolveprop(js, mkval(T_PROP, flags_off)); 8971 + if (vtype(flags_val) == T_STR) { 8972 + jsoff_t flen, foff = vstr(js, flags_val, &flen); 8973 + const char *flags_str = (char *) &js->mem[foff]; 8974 + for (jsoff_t i = 0; i < flen; i++) { 8975 + if (flags_str[i] == 'i') ignore_case = true; 8976 + } 8977 + } 8978 + } 8979 + 8980 + jsoff_t str_len, str_off = vstr(js, str_arg, &str_len); 8981 + char *str_buf = (char *)ANT_GC_MALLOC(str_len + 1); 8982 + if (!str_buf) return js_mkerr(js, "oom"); 8983 + memcpy(str_buf, &js->mem[str_off], str_len); 8984 + str_buf[str_len] = '\0'; 8985 + 8986 + regex_t regex; 8987 + int cflags = REG_EXTENDED | REG_NOSUB; 8988 + if (ignore_case) cflags |= REG_ICASE; 8989 + 8990 + char posix_pattern[512]; 8991 + js_regex_to_posix(pattern_buf, pattern_len, posix_pattern, sizeof(posix_pattern)); 8992 + 8993 + int rc = regcomp(&regex, posix_pattern, cflags); 8994 + if (rc != 0) { 8995 + ANT_GC_FREE(str_buf); 8996 + return mkval(T_BOOL, 0); 8997 + } 8998 + 8999 + int result = regexec(&regex, str_buf, 0, NULL, 0); 9000 + regfree(&regex); 9001 + ANT_GC_FREE(str_buf); 9002 + 9003 + return mkval(T_BOOL, result == 0 ? 1 : 0); 9004 + } 9005 + 9006 + static jsval_t builtin_regexp_exec(struct js *js, jsval_t *args, int nargs) { 9007 + jsval_t regexp = js->this_val; 9008 + if (vtype(regexp) != T_OBJ) return js_mkerr(js, "exec called on non-regexp"); 9009 + if (nargs < 1) return js_mknull(); 9010 + 9011 + jsval_t str_arg = args[0]; 9012 + if (vtype(str_arg) != T_STR) return js_mknull(); 9013 + 9014 + jsoff_t source_off = lkp(js, regexp, "source", 6); 9015 + if (source_off == 0) return js_mknull(); 9016 + jsval_t source_val = resolveprop(js, mkval(T_PROP, source_off)); 9017 + if (vtype(source_val) != T_STR) return js_mknull(); 9018 + 9019 + jsoff_t plen, poff = vstr(js, source_val, &plen); 9020 + char pattern_buf[256]; 9021 + jsoff_t pattern_len = plen < sizeof(pattern_buf) - 1 ? plen : sizeof(pattern_buf) - 1; 9022 + memcpy(pattern_buf, &js->mem[poff], pattern_len); 9023 + pattern_buf[pattern_len] = '\0'; 9024 + 9025 + bool ignore_case = false; 9026 + jsoff_t flags_off = lkp(js, regexp, "flags", 5); 9027 + if (flags_off != 0) { 9028 + jsval_t flags_val = resolveprop(js, mkval(T_PROP, flags_off)); 9029 + if (vtype(flags_val) == T_STR) { 9030 + jsoff_t flen, foff = vstr(js, flags_val, &flen); 9031 + const char *flags_str = (char *) &js->mem[foff]; 9032 + for (jsoff_t i = 0; i < flen; i++) { 9033 + if (flags_str[i] == 'i') ignore_case = true; 9034 + } 9035 + } 9036 + } 9037 + 9038 + jsoff_t str_len, str_off = vstr(js, str_arg, &str_len); 9039 + const char *str_ptr = (char *) &js->mem[str_off]; 9040 + char *str_buf = (char *)ANT_GC_MALLOC(str_len + 1); 9041 + if (!str_buf) return js_mkerr(js, "oom"); 9042 + memcpy(str_buf, str_ptr, str_len); 9043 + str_buf[str_len] = '\0'; 9044 + 9045 + char posix_pattern[512]; 9046 + js_regex_to_posix(pattern_buf, pattern_len, posix_pattern, sizeof(posix_pattern)); 9047 + 9048 + regex_t regex; 9049 + int cflags = REG_EXTENDED; 9050 + if (ignore_case) cflags |= REG_ICASE; 9051 + 9052 + if (regcomp(&regex, posix_pattern, cflags) != 0) { 9053 + ANT_GC_FREE(str_buf); 9054 + return js_mknull(); 9055 + } 9056 + 9057 + regmatch_t matches[10]; 9058 + int ret = regexec(&regex, str_buf, 10, matches, 0); 9059 + if (ret != 0) { 9060 + regfree(&regex); 9061 + ANT_GC_FREE(str_buf); 9062 + return js_mknull(); 9063 + } 9064 + 9065 + jsval_t result_arr = js_mkarr(js); 9066 + for (int i = 0; i < 10 && matches[i].rm_so >= 0; i++) { 9067 + jsoff_t m_start = (jsoff_t)matches[i].rm_so; 9068 + jsoff_t m_len = (jsoff_t)(matches[i].rm_eo - matches[i].rm_so); 9069 + jsval_t match_str = js_mkstr(js, str_ptr + m_start, m_len); 9070 + js_arr_push(js, result_arr, match_str); 9071 + } 9072 + 9073 + setprop(js, result_arr, js_mkstr(js, "index", 5), tov((double)matches[0].rm_so)); 9074 + setprop(js, result_arr, js_mkstr(js, "input", 5), str_arg); 9075 + 9076 + regfree(&regex); 9077 + ANT_GC_FREE(str_buf); 9078 + return result_arr; 9079 + } 9080 + 9081 + static jsval_t builtin_string_search(struct js *js, jsval_t *args, int nargs) { 9082 + jsval_t str = js->this_val; 9083 + if (vtype(str) != T_STR) return js_mkerr(js, "search called on non-string"); 9084 + if (nargs < 1) return tov(-1); 9085 + 9086 + jsval_t pattern = args[0]; 9087 + char pattern_buf[256]; 9088 + jsoff_t pattern_len = 0; 9089 + bool ignore_case = false; 9090 + 9091 + if (vtype(pattern) == T_OBJ) { 9092 + jsoff_t source_off = lkp(js, pattern, "source", 6); 9093 + if (source_off == 0) return tov(-1); 9094 + jsval_t source_val = resolveprop(js, mkval(T_PROP, source_off)); 9095 + if (vtype(source_val) != T_STR) return tov(-1); 9096 + 9097 + jsoff_t plen, poff = vstr(js, source_val, &plen); 9098 + pattern_len = plen < sizeof(pattern_buf) - 1 ? plen : sizeof(pattern_buf) - 1; 9099 + memcpy(pattern_buf, &js->mem[poff], pattern_len); 9100 + pattern_buf[pattern_len] = '\0'; 9101 + 9102 + jsoff_t flags_off = lkp(js, pattern, "flags", 5); 9103 + if (flags_off != 0) { 9104 + jsval_t flags_val = resolveprop(js, mkval(T_PROP, flags_off)); 9105 + if (vtype(flags_val) == T_STR) { 9106 + jsoff_t flen, foff = vstr(js, flags_val, &flen); 9107 + const char *flags_str = (char *) &js->mem[foff]; 9108 + for (jsoff_t i = 0; i < flen; i++) { 9109 + if (flags_str[i] == 'i') ignore_case = true; 9110 + } 9111 + } 9112 + } 9113 + } else if (vtype(pattern) == T_STR) { 9114 + jsoff_t plen, poff = vstr(js, pattern, &plen); 9115 + pattern_len = plen < sizeof(pattern_buf) - 1 ? plen : sizeof(pattern_buf) - 1; 9116 + memcpy(pattern_buf, &js->mem[poff], pattern_len); 9117 + pattern_buf[pattern_len] = '\0'; 9118 + } else { 9119 + return tov(-1); 9120 + } 9121 + 9122 + jsoff_t str_len, str_off = vstr(js, str, &str_len); 9123 + char *str_buf = (char *)ANT_GC_MALLOC(str_len + 1); 9124 + if (!str_buf) return js_mkerr(js, "oom"); 9125 + memcpy(str_buf, &js->mem[str_off], str_len); 9126 + str_buf[str_len] = '\0'; 9127 + 9128 + char posix_pattern[512]; 9129 + js_regex_to_posix(pattern_buf, pattern_len, posix_pattern, sizeof(posix_pattern)); 9130 + 9131 + regex_t regex; 9132 + int cflags = REG_EXTENDED; 9133 + if (ignore_case) cflags |= REG_ICASE; 9134 + 9135 + if (regcomp(&regex, posix_pattern, cflags) != 0) { 9136 + ANT_GC_FREE(str_buf); 9137 + return tov(-1); 9138 + } 9139 + 9140 + regmatch_t match; 9141 + int ret = regexec(&regex, str_buf, 1, &match, 0); 9142 + regfree(&regex); 9143 + ANT_GC_FREE(str_buf); 9144 + 9145 + if (ret != 0) return tov(-1); 9146 + return tov((double)match.rm_so); 9147 + } 9148 + 8931 9149 static jsval_t builtin_Date(struct js *js, jsval_t *args, int nargs) { 8932 9150 jsval_t date_obj = js->this_val; 8933 9151 bool use_this = (vtype(date_obj) == T_OBJ); ··· 11838 12056 jsoff_t str_len, str_off = vstr(js, str, &str_len); 11839 12057 const char *str_ptr = (char *) &js->mem[str_off]; 11840 12058 jsval_t arr = mkarr(js); 11841 - 12059 + 11842 12060 if (is_err(arr)) return arr; 11843 - if (nargs == 0 || vtype(args[0]) != T_STR) { 11844 - jsval_t key = js_mkstr(js, "0", 1); 11845 - setprop(js, arr, key, str); 12061 + if (nargs == 0) goto return_whole; 12062 + 12063 + jsval_t sep_arg = args[0]; 12064 + if (vtype(sep_arg) == T_OBJ) { 12065 + jsoff_t source_off = lkp(js, sep_arg, "source", 6); 12066 + if (source_off == 0) goto return_whole; 12067 + jsval_t source_val = resolveprop(js, mkval(T_PROP, source_off)); 12068 + if (vtype(source_val) != T_STR) goto return_whole; 12069 + 12070 + jsoff_t plen, poff = vstr(js, source_val, &plen); 12071 + char pattern_buf[256]; 12072 + jsoff_t pattern_len = plen < sizeof(pattern_buf) - 1 ? plen : sizeof(pattern_buf) - 1; 12073 + memcpy(pattern_buf, &js->mem[poff], pattern_len); 12074 + pattern_buf[pattern_len] = '\0'; 12075 + 12076 + char posix_pattern[512]; 12077 + js_regex_to_posix(pattern_buf, pattern_len, posix_pattern, sizeof(posix_pattern)); 12078 + 12079 + regex_t regex; 12080 + if (regcomp(&regex, posix_pattern, REG_EXTENDED) != 0) goto return_whole; 12081 + 12082 + char *str_buf = (char *)ANT_GC_MALLOC(str_len + 1); 12083 + if (!str_buf) { regfree(&regex); return js_mkerr(js, "oom"); } 12084 + memcpy(str_buf, str_ptr, str_len); 12085 + str_buf[str_len] = '\0'; 12086 + 12087 + jsoff_t idx = 0, start = 0; 12088 + regmatch_t match; 12089 + while (regexec(&regex, str_buf + start, 1, &match, 0) == 0) { 12090 + jsoff_t match_start = start + (jsoff_t)match.rm_so; 12091 + jsoff_t match_end = start + (jsoff_t)match.rm_eo; 12092 + char idxstr[16]; 12093 + snprintf(idxstr, sizeof(idxstr), "%u", (unsigned)idx); 12094 + jsval_t key = js_mkstr(js, idxstr, strlen(idxstr)); 12095 + jsval_t part = js_mkstr(js, str_ptr + start, match_start - start); 12096 + setprop(js, arr, key, part); 12097 + idx++; 12098 + start = match_end; 12099 + if (match.rm_so == match.rm_eo) start++; 12100 + if (start >= str_len) break; 12101 + } 12102 + if (start <= str_len) { 12103 + char idxstr[16]; 12104 + snprintf(idxstr, sizeof(idxstr), "%u", (unsigned)idx); 12105 + jsval_t key = js_mkstr(js, idxstr, strlen(idxstr)); 12106 + jsval_t part = js_mkstr(js, str_ptr + start, str_len - start); 12107 + setprop(js, arr, key, part); 12108 + idx++; 12109 + } 12110 + regfree(&regex); 12111 + ANT_GC_FREE(str_buf); 11846 12112 jsval_t len_key = js_mkstr(js, "length", 6); 11847 - setprop(js, arr, len_key, tov(1)); 12113 + setprop(js, arr, len_key, tov((double)idx)); 11848 12114 return mkval(T_ARR, vdata(arr)); 11849 12115 } 11850 - 11851 - jsval_t sep = args[0]; 11852 - jsoff_t sep_len, sep_off = vstr(js, sep, &sep_len); 12116 + 12117 + if (vtype(sep_arg) != T_STR) goto return_whole; 12118 + 12119 + jsoff_t sep_len, sep_off = vstr(js, sep_arg, &sep_len); 11853 12120 const char *sep_ptr = (char *) &js->mem[sep_off]; 11854 - jsoff_t idx = 0; 11855 - jsoff_t start = 0; 11856 - 12121 + jsoff_t idx = 0, start = 0; 12122 + 11857 12123 if (sep_len == 0) { 11858 12124 for (jsoff_t i = 0; i < str_len; i++) { 11859 12125 char idxstr[16]; ··· 11863 12129 setprop(js, arr, key, part); 11864 12130 idx++; 11865 12131 } 11866 - } else { 11867 - for (jsoff_t i = 0; i <= str_len - sep_len; i++) { 11868 - if (memcmp(str_ptr + i, sep_ptr, sep_len) == 0) { 11869 - char idxstr[16]; 11870 - snprintf(idxstr, sizeof(idxstr), "%u", (unsigned) idx); 11871 - jsval_t key = js_mkstr(js, idxstr, strlen(idxstr)); 11872 - jsval_t part = js_mkstr(js, str_ptr + start, i - start); 11873 - setprop(js, arr, key, part); 11874 - idx++; 11875 - start = i + sep_len; 11876 - i += sep_len - 1; 11877 - } 11878 - } 11879 - if (start <= str_len) { 11880 - char idxstr[16]; 11881 - snprintf(idxstr, sizeof(idxstr), "%u", (unsigned) idx); 11882 - jsval_t key = js_mkstr(js, idxstr, strlen(idxstr)); 11883 - jsval_t part = js_mkstr(js, str_ptr + start, str_len - start); 11884 - setprop(js, arr, key, part); 11885 - idx++; 11886 - } 12132 + goto set_length; 12133 + } 12134 + 12135 + for (jsoff_t i = 0; i <= str_len - sep_len; i++) { 12136 + if (memcmp(str_ptr + i, sep_ptr, sep_len) != 0) continue; 12137 + char idxstr[16]; 12138 + snprintf(idxstr, sizeof(idxstr), "%u", (unsigned) idx); 12139 + jsval_t key = js_mkstr(js, idxstr, strlen(idxstr)); 12140 + jsval_t part = js_mkstr(js, str_ptr + start, i - start); 12141 + setprop(js, arr, key, part); 12142 + idx++; 12143 + start = i + sep_len; 12144 + i += sep_len - 1; 12145 + } 12146 + if (start <= str_len) { 12147 + char idxstr[16]; 12148 + snprintf(idxstr, sizeof(idxstr), "%u", (unsigned) idx); 12149 + jsval_t key = js_mkstr(js, idxstr, strlen(idxstr)); 12150 + jsval_t part = js_mkstr(js, str_ptr + start, str_len - start); 12151 + setprop(js, arr, key, part); 12152 + idx++; 11887 12153 } 11888 - 12154 + 12155 + set_length:; 11889 12156 jsval_t len_key = js_mkstr(js, "length", 6); 11890 12157 setprop(js, arr, len_key, tov((double) idx)); 12158 + return mkval(T_ARR, vdata(arr)); 12159 + 12160 + return_whole: 12161 + setprop(js, arr, js_mkstr(js, "0", 1), str); 12162 + setprop(js, arr, js_mkstr(js, "length", 6), tov(1)); 11891 12163 return mkval(T_ARR, vdata(arr)); 11892 12164 } 11893 12165 ··· 12290 12562 static jsval_t do_regex_match(struct js *js, const char *pattern_str, const char *str_ptr, jsoff_t str_len, char *str_buf, bool global_flag, bool ignore_case) { 12291 12563 regex_t regex; 12292 12564 int cflags = REG_EXTENDED; 12293 - 12565 + 12294 12566 if (ignore_case) cflags |= REG_ICASE; 12295 12567 if (regcomp(&regex, pattern_str, cflags) != 0) return js_mknull(); 12296 - 12568 + 12297 12569 jsval_t result_arr = js_mkarr(js); 12298 12570 if (is_err(result_arr)) { 12299 12571 regfree(&regex); 12300 12572 return result_arr; 12301 12573 } 12302 - 12303 - regmatch_t match; 12574 + 12575 + regmatch_t matches[10]; 12304 12576 jsoff_t pos = 0; 12305 12577 int match_count = 0; 12306 - 12578 + 12307 12579 while (pos < str_len) { 12308 - int ret = regexec(&regex, str_buf + pos, 1, &match, 0); 12309 - if (ret != 0 || match.rm_so < 0) break; 12310 - 12311 - jsoff_t match_start = pos + (jsoff_t)match.rm_so; 12312 - jsoff_t match_len = (jsoff_t)(match.rm_eo - match.rm_so); 12313 - 12314 - jsval_t match_str = js_mkstr(js, str_ptr + match_start, match_len); 12315 - if (is_err(match_str)) { 12316 - regfree(&regex); 12317 - return match_str; 12580 + int nmatch = global_flag ? 1 : 10; 12581 + int ret = regexec(&regex, str_buf + pos, nmatch, matches, 0); 12582 + if (ret != 0 || matches[0].rm_so < 0) break; 12583 + 12584 + if (global_flag) { 12585 + jsoff_t match_start = pos + (jsoff_t)matches[0].rm_so; 12586 + jsoff_t match_len = (jsoff_t)(matches[0].rm_eo - matches[0].rm_so); 12587 + jsval_t match_str = js_mkstr(js, str_ptr + match_start, match_len); 12588 + if (is_err(match_str)) { regfree(&regex); return match_str; } 12589 + js_arr_push(js, result_arr, match_str); 12590 + } else { 12591 + for (int i = 0; i < 10 && matches[i].rm_so >= 0; i++) { 12592 + jsoff_t m_start = pos + (jsoff_t)matches[i].rm_so; 12593 + jsoff_t m_len = (jsoff_t)(matches[i].rm_eo - matches[i].rm_so); 12594 + jsval_t match_str = js_mkstr(js, str_ptr + m_start, m_len); 12595 + if (is_err(match_str)) { regfree(&regex); return match_str; } 12596 + js_arr_push(js, result_arr, match_str); 12597 + } 12318 12598 } 12319 - 12320 - js_arr_push(js, result_arr, match_str); 12321 12599 match_count++; 12322 - 12600 + 12323 12601 if (!global_flag) break; 12324 - 12325 - if (match.rm_eo == 0) { 12602 + 12603 + if (matches[0].rm_eo == 0) { 12326 12604 pos++; 12327 12605 } else { 12328 - pos += (jsoff_t)match.rm_eo; 12606 + pos += (jsoff_t)matches[0].rm_eo; 12329 12607 } 12330 12608 } 12331 - 12609 + 12332 12610 regfree(&regex); 12333 - 12611 + 12334 12612 if (match_count == 0) return js_mknull(); 12335 12613 return result_arr; 12336 12614 } ··· 15122 15400 setprop(js, string_proto, js_mkstr(js, "at", 2), js_mkfun(builtin_string_at)); 15123 15401 setprop(js, string_proto, js_mkstr(js, "lastIndexOf", 11), js_mkfun(builtin_string_lastIndexOf)); 15124 15402 setprop(js, string_proto, js_mkstr(js, "concat", 6), js_mkfun(builtin_string_concat)); 15403 + setprop(js, string_proto, js_mkstr(js, "search", 6), js_mkfun(builtin_string_search)); 15125 15404 15126 15405 jsval_t number_proto = js_mkobj(js); 15127 15406 set_proto(js, number_proto, object_proto); ··· 15186 15465 15187 15466 jsval_t regexp_proto = js_mkobj(js); 15188 15467 set_proto(js, regexp_proto, object_proto); 15189 - 15468 + setprop(js, regexp_proto, js_mkstr(js, "test", 4), js_mkfun(builtin_regexp_test)); 15469 + setprop(js, regexp_proto, js_mkstr(js, "exec", 4), js_mkfun(builtin_regexp_exec)); 15470 + 15190 15471 jsval_t map_proto = js_mkobj(js); 15191 15472 set_proto(js, map_proto, object_proto); 15192 15473 setprop(js, map_proto, js_mkstr(js, "set", 3), js_mkfun(map_set));