comparison 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
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 #include "jsi.h"
2 #include "regexp.h"
3
4 static void jsB_globalf(js_State *J, const char *name, js_CFunction cfun, int n)
5 {
6 js_newcfunction(J, cfun, name, n);
7 js_defglobal(J, name, JS_DONTENUM);
8 }
9
10 void jsB_propf(js_State *J, const char *name, js_CFunction cfun, int n)
11 {
12 const char *pname = strrchr(name, '.');
13 pname = pname ? pname + 1 : name;
14 js_newcfunction(J, cfun, name, n);
15 js_defproperty(J, -2, pname, JS_DONTENUM);
16 }
17
18 void jsB_propn(js_State *J, const char *name, double number)
19 {
20 js_pushnumber(J, number);
21 js_defproperty(J, -2, name, JS_READONLY | JS_DONTENUM | JS_DONTCONF);
22 }
23
24 void jsB_props(js_State *J, const char *name, const char *string)
25 {
26 js_pushliteral(J, string);
27 js_defproperty(J, -2, name, JS_DONTENUM);
28 }
29
30 static void jsB_parseInt(js_State *J)
31 {
32 const char *s = js_tostring(J, 1);
33 int radix = js_isdefined(J, 2) ? js_tointeger(J, 2) : 0;
34 double sign = 1;
35 double n;
36 char *e;
37
38 while (jsY_iswhite(*s) || jsY_isnewline(*s))
39 ++s;
40 if (*s == '-') {
41 ++s;
42 sign = -1;
43 } else if (*s == '+') {
44 ++s;
45 }
46 if (radix == 0) {
47 radix = 10;
48 if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
49 s += 2;
50 radix = 16;
51 }
52 } else if (radix < 2 || radix > 36) {
53 js_pushnumber(J, NAN);
54 return;
55 }
56 n = js_strtol(s, &e, radix);
57 if (s == e)
58 js_pushnumber(J, NAN);
59 else
60 js_pushnumber(J, n * sign);
61 }
62
63 static void jsB_parseFloat(js_State *J)
64 {
65 const char *s = js_tostring(J, 1);
66 char *e;
67 double n;
68
69 while (jsY_iswhite(*s) || jsY_isnewline(*s)) ++s;
70 if (!strncmp(s, "Infinity", 8))
71 js_pushnumber(J, INFINITY);
72 else if (!strncmp(s, "+Infinity", 9))
73 js_pushnumber(J, INFINITY);
74 else if (!strncmp(s, "-Infinity", 9))
75 js_pushnumber(J, -INFINITY);
76 else {
77 n = js_stringtofloat(s, &e);
78 if (e == s)
79 js_pushnumber(J, NAN);
80 else
81 js_pushnumber(J, n);
82 }
83 }
84
85 static void jsB_isNaN(js_State *J)
86 {
87 double n = js_tonumber(J, 1);
88 js_pushboolean(J, isnan(n));
89 }
90
91 static void jsB_isFinite(js_State *J)
92 {
93 double n = js_tonumber(J, 1);
94 js_pushboolean(J, isfinite(n));
95 }
96
97 static void Encode(js_State *J, const char *str_, const char *unescaped)
98 {
99 /* NOTE: volatile to silence GCC warning about longjmp clobbering a variable */
100 const char * volatile str = str_;
101 js_Buffer *sb = NULL;
102
103 static const char *HEX = "0123456789ABCDEF";
104
105 if (js_try(J)) {
106 js_free(J, sb);
107 js_throw(J);
108 }
109
110 while (*str) {
111 int c = (unsigned char) *str++;
112 if (strchr(unescaped, c))
113 js_putc(J, &sb, c);
114 else {
115 js_putc(J, &sb, '%');
116 js_putc(J, &sb, HEX[(c >> 4) & 0xf]);
117 js_putc(J, &sb, HEX[c & 0xf]);
118 }
119 }
120 js_putc(J, &sb, 0);
121
122 js_pushstring(J, sb ? sb->s : "");
123 js_endtry(J);
124 js_free(J, sb);
125 }
126
127 static void Decode(js_State *J, const char *str_, const char *reserved)
128 {
129 /* NOTE: volatile to silence GCC warning about longjmp clobbering a variable */
130 const char * volatile str = str_;
131 js_Buffer *sb = NULL;
132 int a, b;
133
134 if (js_try(J)) {
135 js_free(J, sb);
136 js_throw(J);
137 }
138
139 while (*str) {
140 int c = (unsigned char) *str++;
141 if (c != '%')
142 js_putc(J, &sb, c);
143 else {
144 if (!str[0] || !str[1])
145 js_urierror(J, "truncated escape sequence");
146 a = *str++;
147 b = *str++;
148 if (!jsY_ishex(a) || !jsY_ishex(b))
149 js_urierror(J, "invalid escape sequence");
150 c = jsY_tohex(a) << 4 | jsY_tohex(b);
151 if (!strchr(reserved, c))
152 js_putc(J, &sb, c);
153 else {
154 js_putc(J, &sb, '%');
155 js_putc(J, &sb, a);
156 js_putc(J, &sb, b);
157 }
158 }
159 }
160 js_putc(J, &sb, 0);
161
162 js_pushstring(J, sb ? sb->s : "");
163 js_endtry(J);
164 js_free(J, sb);
165 }
166
167 #define URIRESERVED ";/?:@&=+$,"
168 #define URIALPHA "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
169 #define URIDIGIT "0123456789"
170 #define URIMARK "-_.!~*'()"
171 #define URIUNESCAPED URIALPHA URIDIGIT URIMARK
172
173 static void jsB_decodeURI(js_State *J)
174 {
175 Decode(J, js_tostring(J, 1), URIRESERVED "#");
176 }
177
178 static void jsB_decodeURIComponent(js_State *J)
179 {
180 Decode(J, js_tostring(J, 1), "");
181 }
182
183 static void jsB_encodeURI(js_State *J)
184 {
185 Encode(J, js_tostring(J, 1), URIUNESCAPED URIRESERVED "#");
186 }
187
188 static void jsB_encodeURIComponent(js_State *J)
189 {
190 Encode(J, js_tostring(J, 1), URIUNESCAPED);
191 }
192
193 void jsB_init(js_State *J)
194 {
195 /* Create the prototype objects here, before the constructors */
196 J->Object_prototype = jsV_newobject(J, JS_COBJECT, NULL);
197 J->Array_prototype = jsV_newobject(J, JS_CARRAY, J->Object_prototype);
198 J->Function_prototype = jsV_newobject(J, JS_CCFUNCTION, J->Object_prototype);
199 J->Boolean_prototype = jsV_newobject(J, JS_CBOOLEAN, J->Object_prototype);
200 J->Number_prototype = jsV_newobject(J, JS_CNUMBER, J->Object_prototype);
201 J->String_prototype = jsV_newobject(J, JS_CSTRING, J->Object_prototype);
202 J->Date_prototype = jsV_newobject(J, JS_CDATE, J->Object_prototype);
203
204 J->RegExp_prototype = jsV_newobject(J, JS_CREGEXP, J->Object_prototype);
205 J->RegExp_prototype->u.r.prog = js_regcompx(J->alloc, J->actx, "(?:)", 0, NULL);
206 J->RegExp_prototype->u.r.source = js_strdup(J, "(?:)");
207
208 /* All the native error types */
209 J->Error_prototype = jsV_newobject(J, JS_CERROR, J->Object_prototype);
210 J->EvalError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
211 J->RangeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
212 J->ReferenceError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
213 J->SyntaxError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
214 J->TypeError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
215 J->URIError_prototype = jsV_newobject(J, JS_CERROR, J->Error_prototype);
216
217 /* Create the constructors and fill out the prototype objects */
218 jsB_initobject(J);
219 jsB_initarray(J);
220 jsB_initfunction(J);
221 jsB_initboolean(J);
222 jsB_initnumber(J);
223 jsB_initstring(J);
224 jsB_initregexp(J);
225 jsB_initdate(J);
226 jsB_initerror(J);
227 jsB_initmath(J);
228 jsB_initjson(J);
229
230 /* Initialize the global object */
231 js_pushnumber(J, NAN);
232 js_defglobal(J, "NaN", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
233
234 js_pushnumber(J, INFINITY);
235 js_defglobal(J, "Infinity", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
236
237 js_pushundefined(J);
238 js_defglobal(J, "undefined", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
239
240 jsB_globalf(J, "parseInt", jsB_parseInt, 1);
241 jsB_globalf(J, "parseFloat", jsB_parseFloat, 1);
242 jsB_globalf(J, "isNaN", jsB_isNaN, 1);
243 jsB_globalf(J, "isFinite", jsB_isFinite, 1);
244
245 jsB_globalf(J, "decodeURI", jsB_decodeURI, 1);
246 jsB_globalf(J, "decodeURIComponent", jsB_decodeURIComponent, 1);
247 jsB_globalf(J, "encodeURI", jsB_encodeURI, 1);
248 jsB_globalf(J, "encodeURIComponent", jsB_encodeURIComponent, 1);
249 }