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