mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-27 06:43:19 +08:00
Run exec on regular expressions held as any (#1600)
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/6902-dyn-regexp-exec.js"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -2784,6 +2784,24 @@ static ScrDyn *scr_native_regex_invoke(void *ptr, ScrDyn *self, const char *meth
|
||||
scr_str_release(subject);
|
||||
return scr_exc_pending() ? NULL : scr_dyn_new_bool(matches);
|
||||
}
|
||||
if (strcmp(method, "exec") == 0) {
|
||||
/* The match array: each capture (undefined when it did not
|
||||
* participate), then index, input and groups; null without a match.
|
||||
* The exec itself reads and advances lastIndex. */
|
||||
ScrStr *subject = scr_dyn_string_coerce_js(argc ? args[0] : scr_dyn_undefined());
|
||||
if (!subject) return NULL;
|
||||
ScrArr *row = scr_regex_exec(subject, re);
|
||||
scr_str_release(subject);
|
||||
if (!row) return scr_exc_pending() ? NULL : scr_dyn_new_null();
|
||||
ScrDyn *match = scr_dyn_new_arr();
|
||||
for (size_t k = 0; k < row->len; k++)
|
||||
scr_dyn_arr_push(match, *scr_arr_state_ptr(row, k) == SCR_ARR_VALUE
|
||||
? scr_dyn_new_str((ScrStr *)(uintptr_t)row->data[k])
|
||||
: scr_dyn_retain(scr_dyn_undefined()));
|
||||
scr_arr_copy_metadata(row, match);
|
||||
scr_arr_release(row);
|
||||
return match;
|
||||
}
|
||||
static const char message[] = "Native RegExp method has no lowering";
|
||||
scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
|
||||
return NULL;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// exec on a regular expression held as an untyped value returns Node's
|
||||
// match array: the captures (undefined for one that did not participate),
|
||||
// index, input and groups. Global and sticky expressions read and advance
|
||||
// lastIndex, and reset it when nothing matches.
|
||||
function dyn(value) {
|
||||
return [value][0];
|
||||
}
|
||||
function show(label, match) {
|
||||
if (match === null) return console.log(label, null);
|
||||
console.log(label, JSON.stringify([...match]), match.index, match.input, JSON.stringify(match.groups), match.length);
|
||||
}
|
||||
|
||||
const plain = dyn(/(\d+)-(x)?/);
|
||||
show("plain", plain.exec("a 12- b"));
|
||||
show("miss", plain.exec("none"));
|
||||
console.log("plain lastIndex", plain.lastIndex);
|
||||
|
||||
const global = dyn(/o(.)/g);
|
||||
show("g1", global.exec("foo boo"));
|
||||
console.log("after g1", global.lastIndex);
|
||||
show("g2", global.exec("foo boo"));
|
||||
console.log("after g2", global.lastIndex);
|
||||
show("g3", global.exec("foo boo"));
|
||||
console.log("after g3", global.lastIndex);
|
||||
global.lastIndex = 5;
|
||||
show("from 5", global.exec("foo boo"));
|
||||
|
||||
const sticky = dyn(/b/y);
|
||||
show("sticky miss", sticky.exec("ab"));
|
||||
sticky.lastIndex = 1;
|
||||
show("sticky hit", sticky.exec("ab"));
|
||||
console.log("sticky after", sticky.lastIndex);
|
||||
|
||||
const named = dyn(/(?<year>\d{4})-(?<month>\d{2})(?:-(?<day>\d{2}))?/);
|
||||
const date = named.exec("on 2024-05");
|
||||
show("named", date);
|
||||
console.log("year", date.groups.year, "day", date.groups.day, Object.getPrototypeOf(date.groups) === null);
|
||||
|
||||
const unicode = dyn(/\u{1F600}(.)/u);
|
||||
show("unicode", unicode.exec("x\u{1F600}y"));
|
||||
show("coerced", dyn(/1/).exec(123));
|
||||
const matches = [];
|
||||
const all = dyn(/a(\d)/g);
|
||||
let m;
|
||||
while ((m = all.exec("a1 a2 a3")) !== null) matches.push(m[1] + "@" + m.index);
|
||||
console.log("loop", matches.join(","), all.lastIndex);
|
||||
console.log("Array.isArray", Array.isArray(dyn(/x/).exec("x")));
|
||||
@@ -0,0 +1 @@
|
||||
{ "plain": 2611, "san": 3084 }
|
||||
Reference in New Issue
Block a user