diff mupdf-source/thirdparty/mujs/jsbuiltin.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/jsbuiltin.c	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,249 @@
+#include "jsi.h"
+#include "regexp.h"
+
+static void jsB_globalf(js_State *J, const char *name, js_CFunction cfun, int n)
+{
+	js_newcfunction(J, cfun, name, n);
+	js_defglobal(J, name, JS_DONTENUM);
+}
+
+void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n)
+{
+	const char *pname = strrchr(name, '.');
+	pname = pname ? pname + 1 : name;
+	js_newcfunction(J, cfun, name, n);
+	js_defproperty(J, -2, pname, JS_DONTENUM);
+}
+
+void jsB_propn(js_State *J, const char *name, double number)
+{
+	js_pushnumber(J, number);
+	js_defproperty(J, -2, name, JS_READONLY | JS_DONTENUM | JS_DONTCONF);
+}
+
+void jsB_props(js_State *J, const char *name, const char *string)
+{
+	js_pushliteral(J, string);
+	js_defproperty(J, -2, name, JS_DONTENUM);
+}
+
+static void jsB_parseInt(js_State *J)
+{
+	const char *s = js_tostring(J, 1);
+	int radix = js_isdefined(J, 2) ? js_tointeger(J, 2) : 0;
+	double sign = 1;
+	double n;
+	char *e;
+
+	while (jsY_iswhite(*s) || jsY_isnewline(*s))
+		++s;
+	if (*s == '-') {
+		++s;
+		sign = -1;
+	} else if (*s == '+') {
+		++s;
+	}
+	if (radix == 0) {
+		radix = 10;
+		if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
+			s += 2;
+			radix = 16;
+		}
+	} else if (radix < 2 || radix > 36) {
+		js_pushnumber(J, NAN);
+		return;
+	}
+	n = js_strtol(s, &e, radix);
+	if (s == e)
+		js_pushnumber(J, NAN);
+	else
+		js_pushnumber(J, n * sign);
+}
+
+static void jsB_parseFloat(js_State *J)
+{
+	const char *s = js_tostring(J, 1);
+	char *e;
+	double n;
+
+	while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
+	if (!strncmp(s, "Infinity", 8))
+		js_pushnumber(J, INFINITY);
+	else if (!strncmp(s, "+Infinity", 9))
+		js_pushnumber(J, INFINITY);
+	else if (!strncmp(s, "-Infinity", 9))
+		js_pushnumber(J, -INFINITY);
+	else {
+		n = js_stringtofloat(s, &e);
+		if (e == s)
+			js_pushnumber(J, NAN);
+		else
+			js_pushnumber(J, n);
+	}
+}
+
+static void jsB_isNaN(js_State *J)
+{
+	double n = js_tonumber(J, 1);
+	js_pushboolean(J, isnan(n));
+}
+
+static void jsB_isFinite(js_State *J)
+{
+	double n = js_tonumber(J, 1);
+	js_pushboolean(J, isfinite(n));
+}
+
+static void Encode(js_State *J, const char *str_, const char *unescaped)
+{
+	/* NOTE: volatile to silence GCC warning about longjmp clobbering a variable */
+	const char * volatile str = str_;
+	js_Buffer *sb = NULL;
+
+	static const char *HEX = "0123456789ABCDEF";
+
+	if (js_try(J)) {
+		js_free(J, sb);
+		js_throw(J);
+	}
+
+	while (*str) {
+		int c = (unsigned char) *str++;
+		if (strchr(unescaped, c))
+			js_putc(J, &sb, c);
+		else {
+			js_putc(J, &sb, '%');
+			js_putc(J, &sb, HEX[(c >> 4) & 0xf]);
+			js_putc(J, &sb, HEX[c & 0xf]);
+		}
+	}
+	js_putc(J, &sb, 0);
+
+	js_pushstring(J, sb ? sb->s : "");
+	js_endtry(J);
+	js_free(J, sb);
+}
+
+static void Decode(js_State *J, const char *str_, const char *reserved)
+{
+	/* NOTE: volatile to silence GCC warning about longjmp clobbering a variable */
+	const char * volatile str = str_;
+	js_Buffer *sb = NULL;
+	int a, b;
+
+	if (js_try(J)) {
+		js_free(J, sb);
+		js_throw(J);
+	}
+
+	while (*str) {
+		int c = (unsigned char) *str++;
+		if (c != '%')
+			js_putc(J, &sb, c);
+		else {
+			if (!str[0] || !str[1])
+				js_urierror(J, "truncated escape sequence");
+			a = *str++;
+			b = *str++;
+			if (!jsY_ishex(a) || !jsY_ishex(b))
+				js_urierror(J, "invalid escape sequence");
+			c = jsY_tohex(a) << 4 | jsY_tohex(b);
+			if (!strchr(reserved, c))
+				js_putc(J, &sb, c);
+			else {
+				js_putc(J, &sb, '%');
+				js_putc(J, &sb, a);
+				js_putc(J, &sb, b);
+			}
+		}
+	}
+	js_putc(J, &sb, 0);
+
+	js_pushstring(J, sb ? sb->s : "");
+	js_endtry(J);
+	js_free(J, sb);
+}
+
+#define URIRESERVED ";/?:@&=+$,"
+#define URIALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define URIDIGIT "0123456789"
+#define URIMARK "-_.!~*'()"
+#define URIUNESCAPED URIALPHA URIDIGIT URIMARK
+
+static void jsB_decodeURI(js_State *J)
+{
+	Decode(J, js_tostring(J, 1), URIRESERVED "#");
+}
+
+static void jsB_decodeURIComponent(js_State *J)
+{
+	Decode(J, js_tostring(J, 1), "");
+}
+
+static void jsB_encodeURI(js_State *J)
+{
+	Encode(J, js_tostring(J, 1), URIUNESCAPED URIRESERVED "#");
+}
+
+static void jsB_encodeURIComponent(js_State *J)
+{
+	Encode(J, js_tostring(J, 1), URIUNESCAPED);
+}
+
+void jsB_init(js_State *J)
+{
+	/* Create the prototype objects here, before the constructors */
+	J->Object_prototype = jsV_newobject(J, JS_COBJECT, NULL);
+	J->Array_prototype = jsV_newobject(J, JS_CARRAY, J->Object_prototype);
+	J->Function_prototype = jsV_newobject(J, JS_CCFUNCTION, J->Object_prototype);
+	J->Boolean_prototype = jsV_newobject(J, JS_CBOOLEAN, J->Object_prototype);
+	J->Number_prototype = jsV_newobject(J, JS_CNUMBER, J->Object_prototype);
+	J->String_prototype = jsV_newobject(J, JS_CSTRING, J->Object_prototype);
+	J->Date_prototype = jsV_newobject(J, JS_CDATE, J->Object_prototype);
+
+	J->RegExp_prototype = jsV_newobject(J, JS_CREGEXP, J->Object_prototype);
+	J->RegExp_prototype->u.r.prog = js_regcompx(J->alloc, J->actx, "(?:)", 0, NULL);
+	J->RegExp_prototype->u.r.source = js_strdup(J, "(?:)");
+
+	/* All the native error types */
+	J->Error_prototype = jsV_newobject(J, JS_CERROR, J->Object_prototype);
+	J->EvalError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
+	J->RangeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
+	J->ReferenceError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
+	J->SyntaxError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
+	J->TypeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
+	J->URIError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
+
+	/* Create the constructors and fill out the prototype objects */
+	jsB_initobject(J);
+	jsB_initarray(J);
+	jsB_initfunction(J);
+	jsB_initboolean(J);
+	jsB_initnumber(J);
+	jsB_initstring(J);
+	jsB_initregexp(J);
+	jsB_initdate(J);
+	jsB_initerror(J);
+	jsB_initmath(J);
+	jsB_initjson(J);
+
+	/* Initialize the global object */
+	js_pushnumber(J, NAN);
+	js_defglobal(J, "NaN", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
+
+	js_pushnumber(J, INFINITY);
+	js_defglobal(J, "Infinity", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
+
+	js_pushundefined(J);
+	js_defglobal(J, "undefined", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
+
+	jsB_globalf(J, "parseInt", jsB_parseInt, 1);
+	jsB_globalf(J, "parseFloat", jsB_parseFloat, 1);
+	jsB_globalf(J, "isNaN", jsB_isNaN, 1);
+	jsB_globalf(J, "isFinite", jsB_isFinite, 1);
+
+	jsB_globalf(J, "decodeURI", jsB_decodeURI, 1);
+	jsB_globalf(J, "decodeURIComponent", jsB_decodeURIComponent, 1);
+	jsB_globalf(J, "encodeURI", jsB_encodeURI, 1);
+	jsB_globalf(J, "encodeURIComponent", jsB_encodeURIComponent, 1);
+}