From fdd7438be0a72e44186b988a6c47c0271f3600f0 Mon Sep 17 00:00:00 2001 From: Alec Murphy Date: Fri, 10 Apr 2026 13:48:32 -0400 Subject: [PATCH] Bump VERSION to commit 0b4ed7e --- src/mujs/VERSION | 2 +- src/mujs/jsarray.c | 37 +++++++++++++++++++++++++++++++ src/mujs/jsi.h | 1 + src/mujs/jslex.c | 2 +- src/mujs/jsrun.c | 1 + src/mujs/jsstring.c | 25 +++++++++++++-------- src/mujs/tools/test262-harness.js | 10 ++++----- 7 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/mujs/VERSION b/src/mujs/VERSION index 5ece3ad..372a573 100644 --- a/src/mujs/VERSION +++ b/src/mujs/VERSION @@ -1 +1 @@ -commit 7368c02b4409107ed64aea19a1c32e6852c76d66 +commit 0b4ed7e4ba37030fdd00f6a17b6de75cd7d7954b diff --git a/src/mujs/jsarray.c b/src/mujs/jsarray.c index ca30cba..356ca5f 100644 --- a/src/mujs/jsarray.c +++ b/src/mujs/jsarray.c @@ -63,6 +63,38 @@ static void Ap_concat(js_State *J) } } +/* ugly cycle detection for Array.prototype.join */ +static void Ap_join(js_State *J); +static void Ap_toString(js_State *J); +static int Ap_join_cycle(js_State *J) +{ + js_Object *needle = js_toobject(J, 0); + int top = J->tracetop - 1; + while (top > 0) { + int stk = J->trace[top].stack; + js_Value *fun = &J->stack[stk-1]; + if (fun->t.type != JS_TOBJECT) return 0; + if (fun->u.object->type != JS_CCFUNCTION) return 0; + if (fun->u.object->u.c.function == Ap_join) + { + js_Value *obj = &J->stack[stk]; + if (obj->t.type != JS_TOBJECT) return 0; + if (obj->u.object == needle) + return 1; + } + else if (fun->u.object->u.c.function == Ap_toString) + { + /* join calls toString which calls join which calls toString, etc */ + } + else + { + return 0; + } + --top; + } + return 0; +} + static void Ap_join(js_State *J) { char * volatile out = NULL; @@ -71,6 +103,11 @@ static void Ap_join(js_State *J) int seplen; int k, n, len, rlen; + if (Ap_join_cycle(J)) { + js_pushliteral(J, ""); + return; + } + len = js_getlength(J, 0); if (js_isdefined(J, 1)) { diff --git a/src/mujs/jsi.h b/src/mujs/jsi.h index c3bb06e..0e2c8c9 100644 --- a/src/mujs/jsi.h +++ b/src/mujs/jsi.h @@ -166,6 +166,7 @@ struct js_StackTrace const char *name; const char *file; int line; + int stack; }; /* Exception handling */ diff --git a/src/mujs/jslex.c b/src/mujs/jslex.c index cebd8ab..0104e03 100644 --- a/src/mujs/jslex.c +++ b/src/mujs/jslex.c @@ -211,7 +211,7 @@ static void textpush(js_State *J, Rune c) n = runelen(c); if (J->lexbuf.len + n > J->lexbuf.cap) { newcap = J->lexbuf.cap * 2; - J->lexbuf.text = js_realloc(J, J->lexbuf.text, J->lexbuf.cap); + J->lexbuf.text = js_realloc(J, J->lexbuf.text, newcap); J->lexbuf.cap = newcap; } if (c == EOF) diff --git a/src/mujs/jsrun.c b/src/mujs/jsrun.c index 4c37d3e..dce7750 100644 --- a/src/mujs/jsrun.c +++ b/src/mujs/jsrun.c @@ -1289,6 +1289,7 @@ static void jsR_pushtrace(js_State *J, const char *name, const char *file, int l if (J->tracetop + 1 == JS_ENVLIMIT) js_error(J, "call stack overflow"); ++J->tracetop; + J->trace[J->tracetop].stack = J->bot; J->trace[J->tracetop].name = name; J->trace[J->tracetop].file = file; J->trace[J->tracetop].line = line; diff --git a/src/mujs/jsstring.c b/src/mujs/jsstring.c index 30464c8..1ebe99a 100644 --- a/src/mujs/jsstring.c +++ b/src/mujs/jsstring.c @@ -76,13 +76,18 @@ int js_utfptrtoidx(const char *s, const char *p) int i = 0; while (s < p) { if (*(unsigned char *)s < Runeself) + { ++s; + ++i; + } else + { s += chartorune(&rune, s); - if (rune >= 0x10000) - i += 2; - else - i += 1; + if (rune >= 0x10000) + i += 2; + else + i += 1; + } } return i; } @@ -462,6 +467,7 @@ static void Sp_match(js_State *J) int len; const char *a, *b, *c, *e; Resub m; + Rune rune; text = checkstring(J, 0); @@ -497,7 +503,7 @@ static void Sp_match(js_State *J) a = c; if (c - b == 0) - ++a; + a += chartorune(&rune, a); } if (len == 0) { @@ -532,12 +538,12 @@ static void Sp_search(js_State *J) static void Sp_replace_regexp(js_State *J) { js_Regexp *re; - const char *source, *s, *r; + const char *source, *source0, *s, *r; js_Buffer *sb = NULL; int n, x; Resub m; - source = checkstring(J, 0); + source = source0 = checkstring(J, 0); re = js_toregexp(J, 1); if (js_doregexec(J, re->prog, source, &m, 0)) { @@ -577,7 +583,7 @@ loop: case 0: --r; /* end of string; back up */ /* fallthrough */ case '$': js_putc(J, &sb, '$'); break; - case '`': js_putm(J, &sb, source, s); break; + case '`': js_putm(J, &sb, source0, s); break; case '\'': js_puts(J, &sb, s + n); break; case '&': js_putm(J, &sb, s, s + n); @@ -709,6 +715,7 @@ static void Sp_split_regexp(js_State *J) int limit, len, k; const char *p, *a, *b, *c, *e; Resub m; + Rune rune; text = checkstring(J, 0); re = js_toregexp(J, 1); @@ -741,7 +748,7 @@ static void Sp_split_regexp(js_State *J) /* empty string at end of last match */ if (b == c && b == p) { - ++a; + a += chartorune(&rune, a); continue; } diff --git a/src/mujs/tools/test262-harness.js b/src/mujs/tools/test262-harness.js index 1b7eab1..54ae9c4 100644 --- a/src/mujs/tools/test262-harness.js +++ b/src/mujs/tools/test262-harness.js @@ -127,16 +127,16 @@ var msg = !neg_str ? err : "[Mismatch @negative " + neg_str + "]" + "\n " + err; info += (result.runtime ? "[run] " : "[load] ") + msg; - if (err && err.stackTrace && (result.runtime || full_mode)) { + if (err && err.stack && (result.runtime || full_mode)) { if (full_mode) { - info += err.stackTrace; + info += err.stack; } else { // trim the internal loader from the trace - var internal = err.stackTrace.indexOf("\n" + load("mujs_blahblah()").err.stackTrace.trim().split("\n")[1]); + var internal = err.stack.indexOf("\n" + load("mujs_blahblah()").err.stack.trim().split("\n")[1]); if (internal >= 0) - info += err.stackTrace.substring(0, internal); + info += err.stack.substring(0, internal); else - info += err.stackTrace; + info += err.stack; } } } else {