diff mupdf-source/thirdparty/mujs/jsrepr.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/thirdparty/mujs/jsrepr.c	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,285 @@
+#include "jsi.h"
+#include "utf.h"
+
+static void reprvalue(js_State *J, js_Buffer **sb);
+
+static void reprnum(js_State *J, js_Buffer **sb, double n)
+{
+	char buf[40];
+	if (n == 0 && signbit(n))
+		js_puts(J, sb, "-0");
+	else
+		js_puts(J, sb, jsV_numbertostring(J, buf, n));
+}
+
+static void reprstr(js_State *J, js_Buffer **sb, const char *s)
+{
+	static const char *HEX = "0123456789ABCDEF";
+	int i, n;
+	Rune c;
+	js_putc(J, sb, '"');
+	while (*s) {
+		n = chartorune(&c, s);
+		switch (c) {
+		case '"': js_puts(J, sb, "\\\""); break;
+		case '\\': js_puts(J, sb, "\\\\"); break;
+		case '\b': js_puts(J, sb, "\\b"); break;
+		case '\f': js_puts(J, sb, "\\f"); break;
+		case '\n': js_puts(J, sb, "\\n"); break;
+		case '\r': js_puts(J, sb, "\\r"); break;
+		case '\t': js_puts(J, sb, "\\t"); break;
+		default:
+			if (c < ' ') {
+				js_putc(J, sb, '\\');
+				js_putc(J, sb, 'x');
+				js_putc(J, sb, HEX[(c>>4)&15]);
+				js_putc(J, sb, HEX[c&15]);
+			} else if (c < 128) {
+				js_putc(J, sb, c);
+			} else if (c < 0x10000) {
+				js_putc(J, sb, '\\');
+				js_putc(J, sb, 'u');
+				js_putc(J, sb, HEX[(c>>12)&15]);
+				js_putc(J, sb, HEX[(c>>8)&15]);
+				js_putc(J, sb, HEX[(c>>4)&15]);
+				js_putc(J, sb, HEX[c&15]);
+			} else {
+				for (i = 0; i < n; ++i)
+					js_putc(J, sb, s[i]);
+			}
+			break;
+		}
+		s += n;
+	}
+	js_putc(J, sb, '"');
+}
+
+#ifndef isalpha
+#define isalpha(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
+#endif
+#ifndef isdigit
+#define isdigit(c) (c >= '0' && c <= '9')
+#endif
+
+static void reprident(js_State *J, js_Buffer **sb, const char *name)
+{
+	const char *p = name;
+	if (isdigit(*p))
+		while (isdigit(*p))
+			++p;
+	else if (isalpha(*p) || *p == '_')
+		while (isdigit(*p) || isalpha(*p) || *p == '_')
+			++p;
+	if (p > name && *p == 0)
+		js_puts(J, sb, name);
+	else
+		reprstr(J, sb, name);
+}
+
+static void reprobject(js_State *J, js_Buffer **sb)
+{
+	const char *key;
+	int i, n;
+
+	n = js_gettop(J) - 1;
+	for (i = 0; i < n; ++i) {
+		if (js_isobject(J, i)) {
+			if (js_toobject(J, i) == js_toobject(J, -1)) {
+				js_puts(J, sb, "{}");
+				return;
+			}
+		}
+	}
+
+	n = 0;
+	js_putc(J, sb, '{');
+	js_pushiterator(J, -1, 1);
+	while ((key = js_nextiterator(J, -1))) {
+		if (n++ > 0)
+			js_puts(J, sb, ", ");
+		reprident(J, sb, key);
+		js_puts(J, sb, ": ");
+		js_getproperty(J, -2, key);
+		reprvalue(J, sb);
+		js_pop(J, 1);
+	}
+	js_pop(J, 1);
+	js_putc(J, sb, '}');
+}
+
+static void reprarray(js_State *J, js_Buffer **sb)
+{
+	int n, i;
+
+	n = js_gettop(J) - 1;
+	for (i = 0; i < n; ++i) {
+		if (js_isobject(J, i)) {
+			if (js_toobject(J, i) == js_toobject(J, -1)) {
+				js_puts(J, sb, "[]");
+				return;
+			}
+		}
+	}
+
+	js_putc(J, sb, '[');
+	n = js_getlength(J, -1);
+	for (i = 0; i < n; ++i) {
+		if (i > 0)
+			js_puts(J, sb, ", ");
+		if (js_hasindex(J, -1, i)) {
+			reprvalue(J, sb);
+			js_pop(J, 1);
+		}
+	}
+	js_putc(J, sb, ']');
+}
+
+static void reprfun(js_State *J, js_Buffer **sb, js_Function *fun)
+{
+	int i;
+	js_puts(J, sb, "function ");
+	js_puts(J, sb, fun->name);
+	js_putc(J, sb, '(');
+	for (i = 0; i < fun->numparams; ++i) {
+		if (i > 0)
+			js_puts(J, sb, ", ");
+		js_puts(J, sb, fun->vartab[i]);
+	}
+	js_puts(J, sb, ") { [byte code] }");
+}
+
+static void reprvalue(js_State *J, js_Buffer **sb)
+{
+	if (js_isundefined(J, -1))
+		js_puts(J, sb, "undefined");
+	else if (js_isnull(J, -1))
+		js_puts(J, sb, "null");
+	else if (js_isboolean(J, -1))
+		js_puts(J, sb, js_toboolean(J, -1) ? "true" : "false");
+	else if (js_isnumber(J, -1))
+		reprnum(J, sb, js_tonumber(J, -1));
+	else if (js_isstring(J, -1))
+		reprstr(J, sb, js_tostring(J, -1));
+	else if (js_isobject(J, -1)) {
+		js_Object *obj = js_toobject(J, -1);
+		switch (obj->type) {
+		default:
+			reprobject(J, sb);
+			break;
+		case JS_CARRAY:
+			reprarray(J, sb);
+			break;
+		case JS_CFUNCTION:
+		case JS_CSCRIPT:
+			reprfun(J, sb, obj->u.f.function);
+			break;
+		case JS_CCFUNCTION:
+			js_puts(J, sb, "function ");
+			js_puts(J, sb, obj->u.c.name);
+			js_puts(J, sb, "() { [native code] }");
+			break;
+		case JS_CBOOLEAN:
+			js_puts(J, sb, "(new Boolean(");
+			js_puts(J, sb, obj->u.boolean ? "true" : "false");
+			js_puts(J, sb, "))");
+			break;
+		case JS_CNUMBER:
+			js_puts(J, sb, "(new Number(");
+			reprnum(J, sb, obj->u.number);
+			js_puts(J, sb, "))");
+			break;
+		case JS_CSTRING:
+			js_puts(J, sb, "(new String(");
+			reprstr(J, sb, obj->u.s.string);
+			js_puts(J, sb, "))");
+			break;
+		case JS_CREGEXP:
+			js_putc(J, sb, '/');
+			js_puts(J, sb, obj->u.r.source);
+			js_putc(J, sb, '/');
+			if (obj->u.r.flags & JS_REGEXP_G) js_putc(J, sb, 'g');
+			if (obj->u.r.flags & JS_REGEXP_I) js_putc(J, sb, 'i');
+			if (obj->u.r.flags & JS_REGEXP_M) js_putc(J, sb, 'm');
+			break;
+		case JS_CDATE:
+			{
+				char buf[40];
+				js_puts(J, sb, "(new Date(");
+				js_puts(J, sb, jsV_numbertostring(J, buf, obj->u.number));
+				js_puts(J, sb, "))");
+			}
+			break;
+		case JS_CERROR:
+			js_puts(J, sb, "(new ");
+			js_getproperty(J, -1, "name");
+			js_puts(J, sb, js_tostring(J, -1));
+			js_pop(J, 1);
+			js_putc(J, sb, '(');
+			if (js_hasproperty(J, -1, "message")) {
+				reprvalue(J, sb);
+				js_pop(J, 1);
+			}
+			js_puts(J, sb, "))");
+			break;
+		case JS_CMATH:
+			js_puts(J, sb, "Math");
+			break;
+		case JS_CJSON:
+			js_puts(J, sb, "JSON");
+			break;
+		case JS_CITERATOR:
+			js_puts(J, sb, "[iterator ");
+			break;
+		case JS_CUSERDATA:
+			js_puts(J, sb, "[userdata ");
+			js_puts(J, sb, obj->u.user.tag);
+			js_putc(J, sb, ']');
+			break;
+		}
+	}
+}
+
+void js_repr(js_State *J, int idx)
+{
+	js_Buffer *sb = NULL;
+	int savebot;
+
+	if (js_try(J)) {
+		js_free(J, sb);
+		js_throw(J);
+	}
+
+	js_copy(J, idx);
+
+	savebot = J->bot;
+	J->bot = J->top - 1;
+	reprvalue(J, &sb);
+	J->bot = savebot;
+
+	js_pop(J, 1);
+
+	js_putc(J, &sb, 0);
+	js_pushstring(J, sb ? sb->s : "undefined");
+
+	js_endtry(J);
+	js_free(J, sb);
+}
+
+const char *js_torepr(js_State *J, int idx)
+{
+	js_repr(J, idx);
+	js_replace(J, idx < 0 ? idx-1 : idx);
+	return js_tostring(J, idx);
+}
+
+const char *js_tryrepr(js_State *J, int idx, const char *error)
+{
+	const char *s;
+	if (js_try(J)) {
+		js_pop(J, 1);
+		return error;
+	}
+	s = js_torepr(J, idx);
+	js_endtry(J);
+	return s;
+}