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