fix text header chasing

This commit is contained in:
2026-02-06 23:20:48 -06:00
parent 1e4646999d
commit 168f7c71d5

View File

@@ -21907,32 +21907,18 @@ static JSValue js_cell_text_trim (JSContext *ctx, JSValue this_val, int argc, JS
if (argc < 1) return JS_NULL; if (argc < 1) return JS_NULL;
if (!JS_IsText (argv[0])) return JS_NULL; if (!JS_IsText (argv[0])) return JS_NULL;
JSGCRef str_ref; JSValue str = argv[0];
JS_PushGCRef (ctx, &str_ref);
str_ref.val = JS_ToString (ctx, argv[0]);
if (JS_IsException (str_ref.val)) {
JS_PopGCRef (ctx, &str_ref);
return str_ref.val;
}
JSText *p = JS_VALUE_GET_STRING (str_ref.val);
int start = 0; int start = 0;
int end = (int)JSText_len (p); int end = js_string_value_len (str);
if (argc > 1 && !JS_IsNull (argv[1])) { if (argc > 1 && !JS_IsNull (argv[1])) {
/* Custom trim with reject characters */ /* Custom trim with reject characters */
const char *reject = JS_ToCString (ctx, argv[1]); const char *reject = JS_ToCString (ctx, argv[1]);
if (!reject) { if (!reject) return JS_EXCEPTION;
JS_PopGCRef (ctx, &str_ref);
return JS_EXCEPTION;
}
size_t reject_len = strlen (reject); size_t reject_len = strlen (reject);
/* Re-chase p after JS_ToCString which can trigger GC */
p = JS_VALUE_GET_STRING (str_ref.val);
while (start < end) { while (start < end) {
uint32_t c = string_get (p, start); uint32_t c = js_string_value_get (str, start);
int found = 0; int found = 0;
for (size_t i = 0; i < reject_len; i++) { for (size_t i = 0; i < reject_len; i++) {
if (c == (uint8_t)reject[i]) { if (c == (uint8_t)reject[i]) {
@@ -21944,7 +21930,7 @@ static JSValue js_cell_text_trim (JSContext *ctx, JSValue this_val, int argc, JS
start++; start++;
} }
while (end > start) { while (end > start) {
uint32_t c = string_get (p, end - 1); uint32_t c = js_string_value_get (str, end - 1);
int found = 0; int found = 0;
for (size_t i = 0; i < reject_len; i++) { for (size_t i = 0; i < reject_len; i++) {
if (c == (uint8_t)reject[i]) { if (c == (uint8_t)reject[i]) {
@@ -21958,17 +21944,13 @@ static JSValue js_cell_text_trim (JSContext *ctx, JSValue this_val, int argc, JS
JS_FreeCString (ctx, reject); JS_FreeCString (ctx, reject);
} else { } else {
/* Default: trim whitespace */ /* Default: trim whitespace */
while (start < end && lre_is_space (string_get (p, start))) while (start < end && lre_is_space (js_string_value_get (str, start)))
start++; start++;
while (end > start && lre_is_space (string_get (p, end - 1))) while (end > start && lre_is_space (js_string_value_get (str, end - 1)))
end--; end--;
} }
/* Re-chase before js_sub_string */ return js_sub_string_val (ctx, str, start, end);
p = JS_VALUE_GET_STRING (str_ref.val);
JSValue result = js_sub_string (ctx, p, start, end);
JS_PopGCRef (ctx, &str_ref);
return result;
} }
/* text.codepoint(str) - get first codepoint */ /* text.codepoint(str) - get first codepoint */
@@ -22386,9 +22368,7 @@ static JSValue js_cell_text_search (JSContext *ctx, JSValue this_val, int argc,
if (JS_SetPropertyStr (ctx, rx, "lastIndex", JS_NewInt32 (ctx, 0)) < 0) if (JS_SetPropertyStr (ctx, rx, "lastIndex", JS_NewInt32 (ctx, 0)) < 0)
goto fail_rx_search; goto fail_rx_search;
/* Re-chase p before js_sub_string */ JSValue sub_str = js_sub_string_val (ctx, str, from, len);
JSText *p = JS_VALUE_GET_STRING (str);
JSValue sub_str = js_sub_string (ctx, p, from, len);
if (JS_IsException (sub_str)) goto fail_rx_search; if (JS_IsException (sub_str)) goto fail_rx_search;
JSValue exec_res = JS_Invoke (ctx, rx, JS_KEY_exec, 1, (JSValue *)&sub_str); JSValue exec_res = JS_Invoke (ctx, rx, JS_KEY_exec, 1, (JSValue *)&sub_str);
@@ -22499,9 +22479,7 @@ static JSValue js_cell_text_extract (JSContext *ctx, JSValue this_val, int argc,
if (from == 0 && to == len) { if (from == 0 && to == len) {
sub_str = str; sub_str = str;
} else { } else {
/* Re-chase p before js_sub_string */ sub_str = js_sub_string_val (ctx, str, from, to);
JSText *p = JS_VALUE_GET_STRING (str);
sub_str = js_sub_string (ctx, p, from, to);
if (JS_IsException (sub_str)) goto fail_rx; if (JS_IsException (sub_str)) goto fail_rx;
} }
@@ -22566,28 +22544,35 @@ static JSValue js_cell_text_extract (JSContext *ctx, JSValue this_val, int argc,
JSValue needle_val = JS_ToString (ctx, argv[1]); JSValue needle_val = JS_ToString (ctx, argv[1]);
if (JS_IsException (needle_val)) return JS_EXCEPTION; if (JS_IsException (needle_val)) return JS_EXCEPTION;
int needle_len = (int)JSText_len (JS_VALUE_GET_STRING (needle_val)); int needle_len = js_string_value_len (needle_val);
/* Re-chase both p and needle right before js_str_find_range */ /* Find needle in str[from..to) */
JSText *p = JS_VALUE_GET_STRING (str); int pos = -1;
JSText *needle = JS_VALUE_GET_STRING (needle_val); if (needle_len == 0) {
int pos = js_str_find_range (p, from, to, needle); pos = from;
} else if (needle_len <= (to - from)) {
int limit = to - needle_len;
for (int i = from; i <= limit; i++) {
int j = 0;
for (; j < needle_len; j++) {
if (js_string_value_get (str, i + j) != js_string_value_get (needle_val, j))
break;
}
if (j == needle_len) { pos = i; break; }
}
}
if (pos < 0) return JS_NULL; if (pos < 0) return JS_NULL;
JSValue arr = JS_NewArrayLen (ctx, 1); JSValue arr = JS_NewArrayLen (ctx, 1);
if (JS_IsException (arr)) return JS_EXCEPTION; if (JS_IsException (arr)) return JS_EXCEPTION;
/* Re-chase p before js_sub_string */ JSValue match = js_sub_string_val (ctx, str, pos, pos + needle_len);
p = JS_VALUE_GET_STRING (str); if (JS_IsException (match))
JSValue match = js_sub_string (ctx, p, pos, pos + needle_len);
if (JS_IsException (match)) {
return JS_EXCEPTION; return JS_EXCEPTION;
}
if (JS_SetPropertyUint32 (ctx, arr, 0, match) < 0) { if (JS_SetPropertyUint32 (ctx, arr, 0, match) < 0)
return JS_EXCEPTION; return JS_EXCEPTION;
}
return arr; return arr;
} }
@@ -22609,20 +22594,17 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
int is_record = JS_IsRecord (collection); int is_record = JS_IsRecord (collection);
if (!is_array && !is_record) return JS_NULL; if (!is_array && !is_record) return JS_NULL;
int len = (int)JSText_len (JS_VALUE_GET_STRING (text_val)); int len = js_string_value_len (text_val);
JSText *result = pretext_init (ctx, len); JSText *result = pretext_init (ctx, len);
if (!result) return JS_EXCEPTION; if (!result) return JS_EXCEPTION;
int pos = 0; int pos = 0;
while (pos < len) { while (pos < len) {
/* Re-chase sp at the start of each loop iteration */
JSText *sp = JS_VALUE_GET_STRING (text_val);
/* Find next '{' */ /* Find next '{' */
int brace_start = -1; int brace_start = -1;
for (int i = pos; i < len; i++) { for (int i = pos; i < len; i++) {
if (string_get (sp, i) == '{') { if (js_string_value_get (text_val, i) == '{') {
brace_start = i; brace_start = i;
break; break;
} }
@@ -22630,8 +22612,7 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
if (brace_start < 0) { if (brace_start < 0) {
/* No more braces, copy rest of string */ /* No more braces, copy rest of string */
sp = JS_VALUE_GET_STRING (text_val); /* Re-chase before js_sub_string */ JSValue tail = js_sub_string_val (ctx, text_val, pos, len);
JSValue tail = js_sub_string (ctx, sp, pos, len);
if (JS_IsException (tail)) return JS_EXCEPTION; if (JS_IsException (tail)) return JS_EXCEPTION;
result = pretext_concat_value (ctx, result, tail); result = pretext_concat_value (ctx, result, tail);
break; break;
@@ -22639,20 +22620,16 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
/* Copy text before brace */ /* Copy text before brace */
if (brace_start > pos) { if (brace_start > pos) {
sp = JS_VALUE_GET_STRING (text_val); /* Re-chase before js_sub_string */ JSValue prefix = js_sub_string_val (ctx, text_val, pos, brace_start);
JSValue prefix = js_sub_string (ctx, sp, pos, brace_start);
if (JS_IsException (prefix)) return JS_EXCEPTION; if (JS_IsException (prefix)) return JS_EXCEPTION;
result = pretext_concat_value (ctx, result, prefix); result = pretext_concat_value (ctx, result, prefix);
if (!result) return JS_EXCEPTION; if (!result) return JS_EXCEPTION;
} }
/* Re-chase sp before searching for closing brace */
sp = JS_VALUE_GET_STRING (text_val);
/* Find closing '}' */ /* Find closing '}' */
int brace_end = -1; int brace_end = -1;
for (int i = brace_start + 1; i < len; i++) { for (int i = brace_start + 1; i < len; i++) {
if (string_get (sp, i) == '}') { if (js_string_value_get (text_val, i) == '}') {
brace_end = i; brace_end = i;
break; break;
} }
@@ -22660,8 +22637,7 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
if (brace_end < 0) { if (brace_end < 0) {
/* No closing brace, copy '{' and continue */ /* No closing brace, copy '{' and continue */
sp = JS_VALUE_GET_STRING (text_val); /* Re-chase before js_sub_string */ JSValue ch = js_sub_string_val (ctx, text_val, brace_start, brace_start + 1);
JSValue ch = js_sub_string (ctx, sp, brace_start, brace_start + 1);
if (JS_IsException (ch)) return JS_EXCEPTION; if (JS_IsException (ch)) return JS_EXCEPTION;
result = pretext_concat_value (ctx, result, ch); result = pretext_concat_value (ctx, result, ch);
if (!result) return JS_EXCEPTION; if (!result) return JS_EXCEPTION;
@@ -22670,17 +22646,15 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
} }
/* Extract content between braces */ /* Extract content between braces */
sp = JS_VALUE_GET_STRING (text_val); /* Re-chase before js_sub_string */ JSValue middle = js_sub_string_val (ctx, text_val, brace_start + 1, brace_end);
JSValue middle = js_sub_string (ctx, sp, brace_start + 1, brace_end);
if (JS_IsException (middle)) return JS_EXCEPTION; if (JS_IsException (middle)) return JS_EXCEPTION;
/* Split on ':' to get name and format_spec */ /* Split on ':' to get name and format_spec */
JSText *middle_str = JS_VALUE_GET_STRING (middle); int middle_len = js_string_value_len (middle);
int middle_len = (int)JSText_len (middle_str);
int colon_pos = -1; int colon_pos = -1;
for (int i = 0; i < middle_len; i++) { for (int i = 0; i < middle_len; i++) {
if (string_get (middle_str, i) == ':') { if (js_string_value_get (middle, i) == ':') {
colon_pos = i; colon_pos = i;
break; break;
} }
@@ -22688,10 +22662,8 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
JSValue name_val, format_spec; JSValue name_val, format_spec;
if (colon_pos >= 0) { if (colon_pos >= 0) {
middle_str = JS_VALUE_GET_STRING (middle); /* Re-chase before js_sub_string */ name_val = js_sub_string_val (ctx, middle, 0, colon_pos);
name_val = js_sub_string (ctx, middle_str, 0, colon_pos); format_spec = js_sub_string_val (ctx, middle, colon_pos + 1, middle_len);
middle_str = JS_VALUE_GET_STRING (middle); /* Re-chase before js_sub_string */
format_spec = js_sub_string (ctx, middle_str, colon_pos + 1, middle_len);
} else { } else {
name_val = middle; name_val = middle;
format_spec = JS_KEY_empty; format_spec = JS_KEY_empty;
@@ -22763,8 +22735,7 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
if (!result) return JS_EXCEPTION; if (!result) return JS_EXCEPTION;
} else { } else {
/* No substitution, keep original {name} or {name:format} */ /* No substitution, keep original {name} or {name:format} */
sp = JS_VALUE_GET_STRING (text_val); /* Re-chase before js_sub_string */ JSValue orig = js_sub_string_val (ctx, text_val, brace_start, brace_end + 1);
JSValue orig = js_sub_string (ctx, sp, brace_start, brace_end + 1);
if (JS_IsException (orig)) return JS_EXCEPTION; if (JS_IsException (orig)) return JS_EXCEPTION;
result = pretext_concat_value (ctx, result, orig); result = pretext_concat_value (ctx, result, orig);
if (!result) return JS_EXCEPTION; if (!result) return JS_EXCEPTION;