Bump VERSION to commit 32064e1

This commit is contained in:
Alec Murphy
2026-03-02 09:46:12 -05:00
parent 5d216e3e65
commit 1bc618fa9a
11 changed files with 84 additions and 30 deletions

1
src/mujs/VERSION Normal file
View File

@@ -0,0 +1 @@
commit 32064e10caa45e68fc87331ca53d042049cc9396

View File

@@ -240,7 +240,7 @@ static void Ap_slice(js_State *J)
static int Ap_sort_cmp(js_State *J, int idx_a, int idx_b) static int Ap_sort_cmp(js_State *J, int idx_a, int idx_b)
{ {
js_Object *obj = js_tovalue(J, 0)->u.object; js_Object *obj = js_tovalue(J, 0)->u.object;
if (obj->u.a.simple) { if (obj->u.a.simple && idx_b < obj->u.a.flat_length) {
js_Value *val_a = &obj->u.a.array[idx_a]; js_Value *val_a = &obj->u.a.array[idx_a];
js_Value *val_b = &obj->u.a.array[idx_b]; js_Value *val_b = &obj->u.a.array[idx_b];
int und_a = val_a->t.type == JS_TUNDEFINED; int und_a = val_a->t.type == JS_TUNDEFINED;
@@ -326,7 +326,7 @@ static int Ap_sort_cmp(js_State *J, int idx_a, int idx_b)
static void Ap_sort_swap(js_State *J, int idx_a, int idx_b) static void Ap_sort_swap(js_State *J, int idx_a, int idx_b)
{ {
js_Object *obj = js_tovalue(J, 0)->u.object; js_Object *obj = js_tovalue(J, 0)->u.object;
if (obj->u.a.simple) { if (obj->u.a.simple && idx_b < obj->u.a.flat_length) {
js_Value tmp = obj->u.a.array[idx_a]; js_Value tmp = obj->u.a.array[idx_a];
obj->u.a.array[idx_a] = obj->u.a.array[idx_b]; obj->u.a.array[idx_a] = obj->u.a.array[idx_b];
obj->u.a.array[idx_b] = tmp; obj->u.a.array[idx_b] = tmp;
@@ -354,7 +354,7 @@ static int Ap_sort_leaf(js_State *J, int i, int end)
int lc = (j << 1) + 1; /* left child */ int lc = (j << 1) + 1; /* left child */
int rc = (j << 1) + 2; /* right child */ int rc = (j << 1) + 2; /* right child */
while (rc < end) { while (rc < end) {
if (Ap_sort_cmp(J, rc, lc) > 0) if (Ap_sort_cmp(J, lc, rc) <= 0)
j = rc; j = rc;
else else
j = lc; j = lc;
@@ -369,8 +369,9 @@ static int Ap_sort_leaf(js_State *J, int i, int end)
static void Ap_sort_sift(js_State *J, int i, int end) static void Ap_sort_sift(js_State *J, int i, int end)
{ {
int j = Ap_sort_leaf(J, i, end); int j = Ap_sort_leaf(J, i, end);
while (Ap_sort_cmp(J, i, j) > 0) while (j > i && Ap_sort_cmp(J, i, j) > 0) {
j = (j - 1) >> 1; /* parent */ j = (j - 1) >> 1; /* parent */
}
while (j > i) { while (j > i) {
Ap_sort_swap(J, i, j); Ap_sort_swap(J, i, j);
j = (j - 1) >> 1; /* parent */ j = (j - 1) >> 1; /* parent */

View File

@@ -53,6 +53,13 @@ static void Ep_toString(js_State *J)
} }
} }
static void Ep_get_stack(js_State *J)
{
Ep_toString(J);
js_getproperty(J, 0, "stackTrace");
js_concat(J);
}
static int jsB_ErrorX(js_State *J, js_Object *prototype) static int jsB_ErrorX(js_State *J, js_Object *prototype)
{ {
js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype)); js_pushobject(J, jsV_newobject(J, JS_CERROR, prototype));
@@ -61,7 +68,7 @@ static int jsB_ErrorX(js_State *J, js_Object *prototype)
js_defproperty(J, -2, "message", JS_DONTENUM); js_defproperty(J, -2, "message", JS_DONTENUM);
} }
if (jsB_stacktrace(J, 1)) if (jsB_stacktrace(J, 1))
js_defproperty(J, -2, "stack", JS_DONTENUM); js_defproperty(J, -2, "stackTrace", JS_DONTENUM);
return 1; return 1;
} }
@@ -71,7 +78,7 @@ static void js_newerrorx(js_State *J, const char *message, js_Object *prototype)
js_pushstring(J, message); js_pushstring(J, message);
js_setproperty(J, -2, "message"); js_setproperty(J, -2, "message");
if (jsB_stacktrace(J, 0)) if (jsB_stacktrace(J, 0))
js_setproperty(J, -2, "stack"); js_setproperty(J, -2, "stackTrace");
} }
#define DERROR(name, Name) \ #define DERROR(name, Name) \
@@ -105,8 +112,13 @@ void jsB_initerror(js_State *J)
{ {
js_pushobject(J, J->Error_prototype); js_pushobject(J, J->Error_prototype);
{ {
jsB_props(J, "name", "Error"); jsB_props(J, "name", "Error");
jsB_propf(J, "Error.prototype.toString", Ep_toString, 0); jsB_propf(J, "Error.prototype.toString", Ep_toString, 0);
jsB_props(J, "message", "");
js_newcfunction(J, Ep_get_stack, "stack", 0);
js_pushnull(J);
js_defaccessor(J, -3, "stack", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
} }
js_newcconstructor(J, jsB_Error, jsB_Error, "Error", 1); js_newcconstructor(J, jsB_Error, jsB_Error, "Error", 1);
js_defglobal(J, "Error", JS_DONTENUM); js_defglobal(J, "Error", JS_DONTENUM);

View File

@@ -270,6 +270,9 @@ struct js_State
js_Object *gcroot; /* gc scan list */ js_Object *gcroot; /* gc scan list */
int runlimit;
int memlimit;
/* environments on the call stack but currently not in scope */ /* environments on the call stack but currently not in scope */
int envtop; int envtop;
js_Environment *envstack[JS_ENVLIMIT]; js_Environment *envstack[JS_ENVLIMIT];

View File

@@ -102,7 +102,7 @@ static int jsY_findkeyword(js_State *J, const char *s)
J->text = keywords[i]; J->text = keywords[i];
return TK_BREAK + i; /* first keyword + i */ return TK_BREAK + i; /* first keyword + i */
} }
J->text = js_intern(J, s); J->text = s;
return TK_IDENTIFIER; return TK_IDENTIFIER;
} }
@@ -204,14 +204,15 @@ static void textinit(js_State *J)
static void textpush(js_State *J, Rune c) static void textpush(js_State *J, Rune c)
{ {
int n; int n, newcap;
if (c == EOF) if (c == EOF)
n = 1; n = 1;
else else
n = runelen(c); n = runelen(c);
if (J->lexbuf.len + n > J->lexbuf.cap) { if (J->lexbuf.len + n > J->lexbuf.cap) {
J->lexbuf.cap = J->lexbuf.cap * 2; 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, J->lexbuf.cap);
J->lexbuf.cap = newcap;
} }
if (c == EOF) if (c == EOF)
J->lexbuf.text[J->lexbuf.len++] = 0; J->lexbuf.text[J->lexbuf.len++] = 0;
@@ -449,7 +450,7 @@ static int lexstring(js_State *J)
s = textend(J); s = textend(J);
J->text = js_intern(J, s); J->text = s;
return TK_STRING; return TK_STRING;
} }
@@ -523,7 +524,7 @@ static int lexregexp(js_State *J)
if (g > 1 || i > 1 || m > 1) if (g > 1 || i > 1 || m > 1)
jsY_error(J, "duplicated flag in regular expression"); jsY_error(J, "duplicated flag in regular expression");
J->text = js_intern(J, s); J->text = s;
J->number = 0; J->number = 0;
if (g) J->number += JS_REGEXP_G; if (g) J->number += JS_REGEXP_G;
if (i) J->number += JS_REGEXP_I; if (i) J->number += JS_REGEXP_I;
@@ -828,7 +829,7 @@ static int lexjsonstring(js_State *J)
s = textend(J); s = textend(J);
J->text = js_intern(J, s); J->text = s;
return TK_STRING; return TK_STRING;
} }

View File

@@ -45,7 +45,6 @@ static void jsonexpect(js_State *J, int t)
static void jsonvalue(js_State *J) static void jsonvalue(js_State *J)
{ {
int i; int i;
const char *name;
switch (J->lookahead) { switch (J->lookahead) {
case TK_STRING: case TK_STRING:
@@ -66,11 +65,12 @@ static void jsonvalue(js_State *J)
do { do {
if (J->lookahead != TK_STRING) if (J->lookahead != TK_STRING)
js_syntaxerror(J, "JSON: unexpected token: %s (expected string)", jsY_tokenstring(J->lookahead)); js_syntaxerror(J, "JSON: unexpected token: %s (expected string)", jsY_tokenstring(J->lookahead));
name = J->text; js_pushstring(J, J->text);
jsonnext(J); jsonnext(J);
jsonexpect(J, ':'); jsonexpect(J, ':');
jsonvalue(J); jsonvalue(J);
js_setproperty(J, -2, name); js_setproperty(J, -3, js_tostring(J, -2));
js_pop(J, 1);
} while (jsonaccept(J, ',')); } while (jsonaccept(J, ','));
jsonexpect(J, '}'); jsonexpect(J, '}');
break; break;

View File

@@ -99,7 +99,7 @@ static js_Ast *jsP_list(js_Ast *head)
static js_Ast *jsP_newstrnode(js_State *J, enum js_AstType type, const char *s) static js_Ast *jsP_newstrnode(js_State *J, enum js_AstType type, const char *s)
{ {
js_Ast *node = jsP_newnode(J, type, J->lexline, 0, 0, 0, 0); js_Ast *node = jsP_newnode(J, type, J->lexline, 0, 0, 0, 0);
node->string = s; node->string = js_intern(J, s);
return node; return node;
} }

View File

@@ -35,9 +35,29 @@ static void js_outofmemory(js_State *J)
js_throw(J); js_throw(J);
} }
static void js_runlimit(js_State *J)
{
STACK[TOP].t.type = JS_TLITSTR;
STACK[TOP].u.litstr = "script ran too long";
++TOP;
js_throw(J);
}
void js_setlimit(js_State *J, int runlimit, int memlimit)
{
J->runlimit = runlimit;
J->memlimit = memlimit;
}
void *js_malloc(js_State *J, int size) void *js_malloc(js_State *J, int size)
{ {
void *ptr = J->alloc(J->actx, NULL, size); void *ptr;
if (J->memlimit > 0) {
if (size >= J->memlimit)
js_outofmemory(J);
J->memlimit -= size;
}
ptr = J->alloc(J->actx, NULL, size);
if (!ptr) if (!ptr)
js_outofmemory(J); js_outofmemory(J);
return ptr; return ptr;
@@ -45,6 +65,12 @@ void *js_malloc(js_State *J, int size)
void *js_realloc(js_State *J, void *ptr, int size) void *js_realloc(js_State *J, void *ptr, int size)
{ {
if (J->memlimit > 0) {
// TODO: track released memory
if (size >= J->memlimit)
js_outofmemory(J);
J->memlimit -= size;
}
ptr = J->alloc(J->actx, ptr, size); ptr = J->alloc(J->actx, ptr, size);
if (!ptr) if (!ptr)
js_outofmemory(J); js_outofmemory(J);
@@ -61,6 +87,7 @@ char *js_strdup(js_State *J, const char *s)
void js_free(js_State *J, void *ptr) void js_free(js_State *J, void *ptr)
{ {
// TODO: track released memory (J->memlimit)
J->alloc(J->actx, ptr, 0); J->alloc(J->actx, ptr, 0);
} }
@@ -1547,7 +1574,7 @@ static int jsR_isindex(js_State *J, int idx, int *k)
static void jsR_run(js_State *J, js_Function *F) static void jsR_run(js_State *J, js_Function *F)
{ {
js_Function **FT = F->funtab; js_Function **FT = F->funtab;
const char **VT = F->vartab-1; const char **VT = F->vartab ? F->vartab - 1 : NULL;
int lightweight = F->lightweight; int lightweight = F->lightweight;
js_Instruction *pcstart = F->code; js_Instruction *pcstart = F->code;
js_Instruction *pc = F->code; js_Instruction *pc = F->code;
@@ -1571,6 +1598,12 @@ static void jsR_run(js_State *J, js_Function *F)
pc += sizeof(str) / sizeof(*pc) pc += sizeof(str) / sizeof(*pc)
while (1) { while (1) {
if (J->runlimit > 0) {
if (J->runlimit == 1)
js_runlimit(J);
--J->runlimit;
}
if (J->gccounter > J->gcthresh) if (J->gccounter > J->gcthresh)
js_gc(J, 0); js_gc(J, 0);

View File

@@ -547,6 +547,11 @@ static void Sp_replace_regexp(js_State *J)
re->last = 0; re->last = 0;
if (js_try(J)) {
js_free(J, sb);
js_throw(J);
}
loop: loop:
s = m.sub[0].sp; s = m.sub[0].sp;
n = m.sub[0].ep - m.sub[0].sp; n = m.sub[0].ep - m.sub[0].sp;
@@ -622,10 +627,6 @@ end:
js_puts(J, &sb, s + n); js_puts(J, &sb, s + n);
js_putc(J, &sb, 0); js_putc(J, &sb, 0);
if (js_try(J)) {
js_free(J, sb);
js_throw(J);
}
js_pushstring(J, sb ? sb->s : ""); js_pushstring(J, sb ? sb->s : "");
js_endtry(J); js_endtry(J);
js_free(J, sb); js_free(J, sb);
@@ -647,6 +648,11 @@ static void Sp_replace_string(js_State *J)
} }
n = strlen(needle); n = strlen(needle);
if (js_try(J)) {
js_free(J, sb);
js_throw(J);
}
if (js_iscallable(J, 2)) { if (js_iscallable(J, 2)) {
js_copy(J, 2); js_copy(J, 2);
js_pushundefined(J); js_pushundefined(J);
@@ -683,10 +689,6 @@ static void Sp_replace_string(js_State *J)
js_putc(J, &sb, 0); js_putc(J, &sb, 0);
} }
if (js_try(J)) {
js_free(J, sb);
js_throw(J);
}
js_pushstring(J, sb ? sb->s : ""); js_pushstring(J, sb ? sb->s : "");
js_endtry(J); js_endtry(J);
js_free(J, sb); js_free(J, sb);

View File

@@ -170,7 +170,7 @@ const char *js_itoa(char *out, int v)
unsigned int a; unsigned int a;
int i = 0; int i = 0;
if (v < 0) { if (v < 0) {
a = -v; a = -(unsigned)v; /* cast to avoid -INT_MIN signed overflow UB */
*s++ = '-'; *s++ = '-';
} else { } else {
a = v; a = v;

View File

@@ -9,7 +9,7 @@ extern "C" {
#define JS_VERSION_MAJOR 1 #define JS_VERSION_MAJOR 1
#define JS_VERSION_MINOR 3 #define JS_VERSION_MINOR 3
#define JS_VERSION_PATCH 5 #define JS_VERSION_PATCH 8
#define JS_VERSION (JS_VERSION_MAJOR * 10000 + JS_VERSION_MINOR * 100 + JS_VERSION_PATCH) #define JS_VERSION (JS_VERSION_MAJOR * 10000 + JS_VERSION_MINOR * 100 + JS_VERSION_PATCH)
#define JS_CHECKVERSION(x,y,z) (JS_VERSION >= ((x) * 10000 + (y) * 100 + (z))) #define JS_CHECKVERSION(x,y,z) (JS_VERSION >= ((x) * 10000 + (y) * 100 + (z)))
@@ -56,6 +56,7 @@ void js_setreport(js_State *J, js_Report report);
js_Panic js_atpanic(js_State *J, js_Panic panic); js_Panic js_atpanic(js_State *J, js_Panic panic);
void js_freestate(js_State *J); void js_freestate(js_State *J);
void js_gc(js_State *J, int report); void js_gc(js_State *J, int report);
void js_setlimit(js_State *J, int runlimit, int memlimit);
int js_dostring(js_State *J, const char *source); int js_dostring(js_State *J, const char *source);
int js_dofile(js_State *J, const char *filename); int js_dofile(js_State *J, const char *filename);