/src/mupdf/thirdparty/mujs/jsfunction.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "jsi.h" |
2 | | |
3 | | static void jsB_Function(js_State *J) |
4 | 0 | { |
5 | 0 | int i, top = js_gettop(J); |
6 | 0 | js_Buffer *sb = NULL; |
7 | 0 | const char *body; |
8 | 0 | js_Ast *parse; |
9 | 0 | js_Function *fun; |
10 | |
|
11 | 0 | if (js_try(J)) { |
12 | 0 | js_free(J, sb); |
13 | 0 | jsP_freeparse(J); |
14 | 0 | js_throw(J); |
15 | 0 | } |
16 | | |
17 | | /* p1, p2, ..., pn */ |
18 | 0 | if (top > 2) { |
19 | 0 | for (i = 1; i < top - 1; ++i) { |
20 | 0 | if (i > 1) |
21 | 0 | js_putc(J, &sb, ','); |
22 | 0 | js_puts(J, &sb, js_tostring(J, i)); |
23 | 0 | } |
24 | 0 | js_putc(J, &sb, ')'); |
25 | 0 | js_putc(J, &sb, 0); |
26 | 0 | } |
27 | | |
28 | | /* body */ |
29 | 0 | body = js_isdefined(J, top - 1) ? js_tostring(J, top - 1) : ""; |
30 | |
|
31 | 0 | parse = jsP_parsefunction(J, "[string]", sb ? sb->s : NULL, body); |
32 | 0 | fun = jsC_compilefunction(J, parse); |
33 | |
|
34 | 0 | js_endtry(J); |
35 | 0 | js_free(J, sb); |
36 | 0 | jsP_freeparse(J); |
37 | |
|
38 | 0 | js_newfunction(J, fun, J->GE); |
39 | 0 | } |
40 | | |
41 | | static void jsB_Function_prototype(js_State *J) |
42 | 0 | { |
43 | 0 | js_pushundefined(J); |
44 | 0 | } |
45 | | |
46 | | static void Fp_toString(js_State *J) |
47 | 0 | { |
48 | 0 | js_Object *self = js_toobject(J, 0); |
49 | 0 | js_Buffer *sb = NULL; |
50 | 0 | int i; |
51 | |
|
52 | 0 | if (!js_iscallable(J, 0)) |
53 | 0 | js_typeerror(J, "not a function"); |
54 | | |
55 | 0 | if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT) { |
56 | 0 | js_Function *F = self->u.f.function; |
57 | |
|
58 | 0 | if (js_try(J)) { |
59 | 0 | js_free(J, sb); |
60 | 0 | js_throw(J); |
61 | 0 | } |
62 | | |
63 | 0 | js_puts(J, &sb, "function "); |
64 | 0 | js_puts(J, &sb, F->name); |
65 | 0 | js_putc(J, &sb, '('); |
66 | 0 | for (i = 0; i < F->numparams; ++i) { |
67 | 0 | if (i > 0) js_putc(J, &sb, ','); |
68 | 0 | js_puts(J, &sb, F->vartab[i]); |
69 | 0 | } |
70 | 0 | js_puts(J, &sb, ") { [byte code] }"); |
71 | 0 | js_putc(J, &sb, 0); |
72 | |
|
73 | 0 | js_pushstring(J, sb->s); |
74 | 0 | js_endtry(J); |
75 | 0 | js_free(J, sb); |
76 | 0 | } else if (self->type == JS_CCFUNCTION) { |
77 | 0 | if (js_try(J)) { |
78 | 0 | js_free(J, sb); |
79 | 0 | js_throw(J); |
80 | 0 | } |
81 | | |
82 | 0 | js_puts(J, &sb, "function "); |
83 | 0 | js_puts(J, &sb, self->u.c.name); |
84 | 0 | js_puts(J, &sb, "() { [native code] }"); |
85 | 0 | js_putc(J, &sb, 0); |
86 | |
|
87 | 0 | js_pushstring(J, sb->s); |
88 | 0 | js_endtry(J); |
89 | 0 | js_free(J, sb); |
90 | 0 | } else { |
91 | 0 | js_pushliteral(J, "function () { }"); |
92 | 0 | } |
93 | 0 | } |
94 | | |
95 | | static void Fp_apply(js_State *J) |
96 | 0 | { |
97 | 0 | int i, n; |
98 | |
|
99 | 0 | if (!js_iscallable(J, 0)) |
100 | 0 | js_typeerror(J, "not a function"); |
101 | | |
102 | 0 | js_copy(J, 0); |
103 | 0 | js_copy(J, 1); |
104 | |
|
105 | 0 | if (js_isnull(J, 2) || js_isundefined(J, 2)) { |
106 | 0 | n = 0; |
107 | 0 | } else { |
108 | 0 | n = js_getlength(J, 2); |
109 | 0 | if (n < 0) |
110 | 0 | n = 0; |
111 | 0 | for (i = 0; i < n; ++i) |
112 | 0 | js_getindex(J, 2, i); |
113 | 0 | } |
114 | |
|
115 | 0 | js_call(J, n); |
116 | 0 | } |
117 | | |
118 | | static void Fp_call(js_State *J) |
119 | 0 | { |
120 | 0 | int i, top = js_gettop(J); |
121 | |
|
122 | 0 | if (!js_iscallable(J, 0)) |
123 | 0 | js_typeerror(J, "not a function"); |
124 | | |
125 | 0 | for (i = 0; i < top; ++i) |
126 | 0 | js_copy(J, i); |
127 | |
|
128 | 0 | js_call(J, top - 2); |
129 | 0 | } |
130 | | |
131 | | static void callbound(js_State *J) |
132 | 0 | { |
133 | 0 | int top = js_gettop(J); |
134 | 0 | int i, fun, args, n; |
135 | |
|
136 | 0 | fun = js_gettop(J); |
137 | 0 | js_currentfunction(J); |
138 | 0 | js_getproperty(J, fun, "__TargetFunction__"); |
139 | 0 | js_getproperty(J, fun, "__BoundThis__"); |
140 | |
|
141 | 0 | args = js_gettop(J); |
142 | 0 | js_getproperty(J, fun, "__BoundArguments__"); |
143 | 0 | n = js_getlength(J, args); |
144 | 0 | if (n < 0) |
145 | 0 | n = 0; |
146 | 0 | for (i = 0; i < n; ++i) |
147 | 0 | js_getindex(J, args, i); |
148 | 0 | js_remove(J, args); |
149 | |
|
150 | 0 | for (i = 1; i < top; ++i) |
151 | 0 | js_copy(J, i); |
152 | |
|
153 | 0 | js_call(J, n + top - 1); |
154 | 0 | } |
155 | | |
156 | | static void constructbound(js_State *J) |
157 | 0 | { |
158 | 0 | int top = js_gettop(J); |
159 | 0 | int i, fun, args, n; |
160 | |
|
161 | 0 | fun = js_gettop(J); |
162 | 0 | js_currentfunction(J); |
163 | 0 | js_getproperty(J, fun, "__TargetFunction__"); |
164 | |
|
165 | 0 | args = js_gettop(J); |
166 | 0 | js_getproperty(J, fun, "__BoundArguments__"); |
167 | 0 | n = js_getlength(J, args); |
168 | 0 | if (n < 0) |
169 | 0 | n = 0; |
170 | 0 | for (i = 0; i < n; ++i) |
171 | 0 | js_getindex(J, args, i); |
172 | 0 | js_remove(J, args); |
173 | |
|
174 | 0 | for (i = 1; i < top; ++i) |
175 | 0 | js_copy(J, i); |
176 | |
|
177 | 0 | js_construct(J, n + top - 1); |
178 | 0 | } |
179 | | |
180 | | static void Fp_bind(js_State *J) |
181 | 0 | { |
182 | 0 | int i, top = js_gettop(J); |
183 | 0 | int n; |
184 | |
|
185 | 0 | if (!js_iscallable(J, 0)) |
186 | 0 | js_typeerror(J, "not a function"); |
187 | | |
188 | 0 | n = js_getlength(J, 0); |
189 | 0 | if (n > top - 2) |
190 | 0 | n -= top - 2; |
191 | 0 | else |
192 | 0 | n = 0; |
193 | | |
194 | | /* Reuse target function's prototype for HasInstance check. */ |
195 | 0 | js_getproperty(J, 0, "prototype"); |
196 | 0 | js_newcconstructor(J, callbound, constructbound, "[bind]", n); |
197 | | |
198 | | /* target function */ |
199 | 0 | js_copy(J, 0); |
200 | 0 | js_defproperty(J, -2, "__TargetFunction__", JS_READONLY | JS_DONTENUM | JS_DONTCONF); |
201 | | |
202 | | /* bound this */ |
203 | 0 | js_copy(J, 1); |
204 | 0 | js_defproperty(J, -2, "__BoundThis__", JS_READONLY | JS_DONTENUM | JS_DONTCONF); |
205 | | |
206 | | /* bound arguments */ |
207 | 0 | js_newarray(J); |
208 | 0 | for (i = 2; i < top; ++i) { |
209 | 0 | js_copy(J, i); |
210 | 0 | js_setindex(J, -2, i - 2); |
211 | 0 | } |
212 | 0 | js_defproperty(J, -2, "__BoundArguments__", JS_READONLY | JS_DONTENUM | JS_DONTCONF); |
213 | 0 | } |
214 | | |
215 | | void jsB_initfunction(js_State *J) |
216 | 0 | { |
217 | 0 | J->Function_prototype->u.c.name = "Function.prototype"; |
218 | 0 | J->Function_prototype->u.c.function = jsB_Function_prototype; |
219 | 0 | J->Function_prototype->u.c.constructor = NULL; |
220 | 0 | J->Function_prototype->u.c.length = 0; |
221 | |
|
222 | 0 | js_pushobject(J, J->Function_prototype); |
223 | 0 | { |
224 | 0 | jsB_propf(J, "Function.prototype.toString", Fp_toString, 2); |
225 | 0 | jsB_propf(J, "Function.prototype.apply", Fp_apply, 2); |
226 | 0 | jsB_propf(J, "Function.prototype.call", Fp_call, 1); |
227 | 0 | jsB_propf(J, "Function.prototype.bind", Fp_bind, 1); |
228 | 0 | } |
229 | 0 | js_newcconstructor(J, jsB_Function, jsB_Function, "Function", 1); |
230 | 0 | js_defglobal(J, "Function", JS_DONTENUM); |
231 | 0 | } |