comparison mupdf-source/thirdparty/mujs/jsstate.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
3 #include <assert.h>
4 #include <errno.h>
5
6 static int js_ptry(js_State *J) {
7 if (J->trytop == JS_TRYLIMIT) {
8 J->stack[J->top].t.type = JS_TLITSTR;
9 J->stack[J->top].u.litstr = "exception stack overflow";
10 ++J->top;
11 return 1;
12 }
13 return 0;
14 }
15
16 static void *js_defaultalloc(void *actx, void *ptr, int size)
17 {
18 if (size == 0) {
19 free(ptr);
20 return NULL;
21 }
22 return realloc(ptr, (size_t)size);
23 }
24
25 static void js_defaultreport(js_State *J, const char *message)
26 {
27 fputs(message, stderr);
28 fputc('\n', stderr);
29 }
30
31 static void js_defaultpanic(js_State *J)
32 {
33 js_report(J, "uncaught exception");
34 /* return to javascript to abort */
35 }
36
37 int js_ploadstring(js_State *J, const char *filename, const char *source)
38 {
39 if (js_ptry(J))
40 return 1;
41 if (js_try(J))
42 return 1;
43 js_loadstring(J, filename, source);
44 js_endtry(J);
45 return 0;
46 }
47
48 int js_ploadfile(js_State *J, const char *filename)
49 {
50 if (js_ptry(J))
51 return 1;
52 if (js_try(J))
53 return 1;
54 js_loadfile(J, filename);
55 js_endtry(J);
56 return 0;
57 }
58
59 const char *js_trystring(js_State *J, int idx, const char *error)
60 {
61 const char *s;
62 if (js_ptry(J)) {
63 js_pop(J, 1);
64 return error;
65 }
66 if (js_try(J)) {
67 js_pop(J, 1);
68 return error;
69 }
70 s = js_tostring(J, idx);
71 js_endtry(J);
72 return s;
73 }
74
75 double js_trynumber(js_State *J, int idx, double error)
76 {
77 double v;
78 if (js_ptry(J)) {
79 js_pop(J, 1);
80 return error;
81 }
82 if (js_try(J)) {
83 js_pop(J, 1);
84 return error;
85 }
86 v = js_tonumber(J, idx);
87 js_endtry(J);
88 return v;
89 }
90
91 int js_tryinteger(js_State *J, int idx, int error)
92 {
93 int v;
94 if (js_ptry(J)) {
95 js_pop(J, 1);
96 return error;
97 }
98 if (js_try(J)) {
99 js_pop(J, 1);
100 return error;
101 }
102 v = js_tointeger(J, idx);
103 js_endtry(J);
104 return v;
105 }
106
107 int js_tryboolean(js_State *J, int idx, int error)
108 {
109 int v;
110 if (js_ptry(J)) {
111 js_pop(J, 1);
112 return error;
113 }
114 if (js_try(J)) {
115 js_pop(J, 1);
116 return error;
117 }
118 v = js_toboolean(J, idx);
119 js_endtry(J);
120 return v;
121 }
122
123 static void js_loadstringx(js_State *J, const char *filename, const char *source, int iseval)
124 {
125 js_Ast *P;
126 js_Function *F;
127
128 if (js_try(J)) {
129 jsP_freeparse(J);
130 js_throw(J);
131 }
132
133 P = jsP_parse(J, filename, source);
134 F = jsC_compilescript(J, P, iseval ? J->strict : J->default_strict);
135 jsP_freeparse(J);
136 js_newscript(J, F, iseval ? (J->strict ? J->E : NULL) : J->GE);
137
138 js_endtry(J);
139 }
140
141 void js_loadeval(js_State *J, const char *filename, const char *source)
142 {
143 js_loadstringx(J, filename, source, 1);
144 }
145
146 void js_loadstring(js_State *J, const char *filename, const char *source)
147 {
148 js_loadstringx(J, filename, source, 0);
149 }
150
151 void js_loadfile(js_State *J, const char *filename)
152 {
153 FILE *f;
154 char *s, *p;
155 int n, t;
156
157 f = fopen(filename, "rb");
158 if (!f) {
159 js_error(J, "cannot open file '%s': %s", filename, strerror(errno));
160 }
161
162 if (fseek(f, 0, SEEK_END) < 0) {
163 fclose(f);
164 js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno));
165 }
166
167 n = ftell(f);
168 if (n < 0) {
169 fclose(f);
170 js_error(J, "cannot tell in file '%s': %s", filename, strerror(errno));
171 }
172
173 if (fseek(f, 0, SEEK_SET) < 0) {
174 fclose(f);
175 js_error(J, "cannot seek in file '%s': %s", filename, strerror(errno));
176 }
177
178 if (js_try(J)) {
179 fclose(f);
180 js_throw(J);
181 }
182 s = js_malloc(J, n + 1); /* add space for string terminator */
183 js_endtry(J);
184
185 t = fread(s, 1, (size_t)n, f);
186 if (t != n) {
187 js_free(J, s);
188 fclose(f);
189 js_error(J, "cannot read data from file '%s': %s", filename, strerror(errno));
190 }
191
192 s[n] = 0; /* zero-terminate string containing file data */
193
194 if (js_try(J)) {
195 js_free(J, s);
196 fclose(f);
197 js_throw(J);
198 }
199
200 /* skip first line if it starts with "#!" */
201 p = s;
202 if (p[0] == '#' && p[1] == '!') {
203 p += 2;
204 while (*p && *p != '\n')
205 ++p;
206 }
207
208 js_loadstring(J, filename, p);
209
210 js_free(J, s);
211 fclose(f);
212 js_endtry(J);
213 }
214
215 int js_dostring(js_State *J, const char *source)
216 {
217 if (js_ptry(J)) {
218 js_report(J, "exception stack overflow");
219 js_pop(J, 1);
220 return 1;
221 }
222 if (js_try(J)) {
223 js_report(J, js_trystring(J, -1, "Error"));
224 js_pop(J, 1);
225 return 1;
226 }
227 js_loadstring(J, "[string]", source);
228 js_pushundefined(J);
229 js_call(J, 0);
230 js_pop(J, 1);
231 js_endtry(J);
232 return 0;
233 }
234
235 int js_dofile(js_State *J, const char *filename)
236 {
237 if (js_ptry(J)) {
238 js_report(J, "exception stack overflow");
239 js_pop(J, 1);
240 return 1;
241 }
242 if (js_try(J)) {
243 js_report(J, js_trystring(J, -1, "Error"));
244 js_pop(J, 1);
245 return 1;
246 }
247 js_loadfile(J, filename);
248 js_pushundefined(J);
249 js_call(J, 0);
250 js_pop(J, 1);
251 js_endtry(J);
252 return 0;
253 }
254
255 js_Panic js_atpanic(js_State *J, js_Panic panic)
256 {
257 js_Panic old = J->panic;
258 J->panic = panic;
259 return old;
260 }
261
262 void js_report(js_State *J, const char *message)
263 {
264 if (J->report)
265 J->report(J, message);
266 }
267
268 void js_setreport(js_State *J, js_Report report)
269 {
270 J->report = report;
271 }
272
273 void js_setcontext(js_State *J, void *uctx)
274 {
275 J->uctx = uctx;
276 }
277
278 void *js_getcontext(js_State *J)
279 {
280 return J->uctx;
281 }
282
283 js_State *js_newstate(js_Alloc alloc, void *actx, int flags)
284 {
285 js_State *J;
286
287 assert(sizeof(js_Value) == 16);
288 assert(soffsetof(js_Value, t.type) == 15);
289
290 if (!alloc)
291 alloc = js_defaultalloc;
292
293 J = alloc(actx, NULL, sizeof *J);
294 if (!J)
295 return NULL;
296 memset(J, 0, sizeof(*J));
297 J->actx = actx;
298 J->alloc = alloc;
299
300 if (flags & JS_STRICT)
301 J->strict = J->default_strict = 1;
302
303 J->trace[0].name = "-top-";
304 J->trace[0].file = "native";
305 J->trace[0].line = 0;
306
307 J->report = js_defaultreport;
308 J->panic = js_defaultpanic;
309
310 J->stack = alloc(actx, NULL, JS_STACKSIZE * sizeof *J->stack);
311 if (!J->stack) {
312 alloc(actx, J, 0);
313 return NULL;
314 }
315
316 J->gcmark = 1;
317 J->nextref = 0;
318 J->gcthresh = 0; /* reaches stability within ~ 2-5 GC cycles */
319
320 if (js_try(J)) {
321 js_freestate(J);
322 return NULL;
323 }
324
325 J->R = jsV_newobject(J, JS_COBJECT, NULL);
326 J->G = jsV_newobject(J, JS_COBJECT, NULL);
327 J->E = jsR_newenvironment(J, J->G, NULL);
328 J->GE = J->E;
329
330 jsB_init(J);
331
332 js_endtry(J);
333 return J;
334 }