History

Implement Function.prototype.bind().

Tor Andersson committed 12 years ago

Commit c87898e1 parent 35cc7492 files · +90 −0Browse files

Unified · Split

2 files
  1. jsfunction.c +80 −0
  2. jsrun.c +10 −0
jsfunction.c+80−0
@@ -120,6 +120,85 @@ static void Fp_call(js_State *J, unsigned int argc) · 119 unmodified lines
120120 js_call(J, argc - 1);
121121 }
122122
123+static void callbound(js_State *J, unsigned int argc)
124+{
125+ unsigned int i, fun, args, n;
126+
127+ fun = js_gettop(J);
128+ js_currentfunction(J);
129+ js_getproperty(J, fun, "__TargetFunction__");
130+ js_getproperty(J, fun, "__BoundThis__");
131+
132+ args = js_gettop(J);
133+ js_getproperty(J, fun, "__BoundArguments__");
134+ n = js_getlength(J, args);
135+ for (i = 0; i < n; ++i)
136+ js_getindex(J, args, i);
137+ js_remove(J, args);
138+
139+ for (i = 1; i <= argc; ++i)
140+ js_copy(J, i);
141+
142+ js_call(J, n + argc);
143+}
144+
145+static void constructbound(js_State *J, unsigned int argc)
146+{
147+ unsigned int i, fun, args, n;
148+
149+ fun = js_gettop(J);
150+ js_currentfunction(J);
151+ js_getproperty(J, fun, "__TargetFunction__");
152+
153+ args = js_gettop(J);
154+ js_getproperty(J, fun, "__BoundArguments__");
155+ n = js_getlength(J, args);
156+ for (i = 0; i < n; ++i)
157+ js_getindex(J, args, i);
158+ js_remove(J, args);
159+
160+ for (i = 1; i <= argc; ++i)
161+ js_copy(J, i);
162+
163+ js_construct(J, n + argc);
164+}
165+
166+static void Fp_bind(js_State *J, unsigned int argc)
167+{
168+ unsigned int i, n;
169+
170+ if (!js_iscallable(J, 0))
171+ js_typeerror(J, "not a function");
172+
173+ n = js_getlength(J, 0);
174+ if (argc - 1 < n)
175+ n -= argc - 1;
176+ else
177+ n = 0;
178+
179+ js_newcconstructor(J, callbound, constructbound, n);
180+
181+ /* Reuse target function's prototype for HasInstance check. */
182+ js_getproperty(J, 0, "prototype");
183+ js_defproperty(J, -2, "prototype", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
184+
185+ /* target function */
186+ js_copy(J, 0);
187+ js_defproperty(J, -2, "__TargetFunction__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
188+
189+ /* bound this */
190+ js_copy(J, 1);
191+ js_defproperty(J, -2, "__BoundThis__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
192+
193+ /* bound arguments */
194+ js_newarray(J);
195+ for (i = 2; i <= argc; ++i) {
196+ js_copy(J, i);
197+ js_setindex(J, -2, i-2);
198+ }
199+ js_defproperty(J, -2, "__BoundArguments__", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
200+}
201+
123202 void jsB_initfunction(js_State *J)
124203 {
125204 J->Function_prototype->u.c.function = jsB_Function_prototype;
@@ -130,6 +209,7 @@ void jsB_initfunction(js_State *J) · 4 unmodified lines
130209 jsB_propf(J, "toString", Fp_toString, 2);
131210 jsB_propf(J, "apply", Fp_apply, 2);
132211 jsB_propf(J, "call", Fp_call, 1);
212+ jsB_propf(J, "bind", Fp_bind, 1);
133213 }
134214 js_newcconstructor(J, jsB_Function, jsB_Function, 1);
135215 js_defglobal(J, "Function", JS_DONTENUM);
jsrun.c+10−0
@@ -307,6 +307,16 @@ void js_pop(js_State *J, int n) · 306 unmodified lines
307307 }
308308 }
309309
310+void js_remove(js_State *J, int idx)
311+{
312+ idx = idx < 0 ? TOP + idx : BOT + idx;
313+ if (idx < BOT || idx >= TOP)
314+ js_error(J, "stack error!");
315+ for (;idx < TOP - 1; ++idx)
316+ STACK[idx] = STACK[idx+1];
317+ --TOP;
318+}
319+
310320 void js_copy(js_State *J, int idx)
311321 {
312322 CHECKSTACK(1);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t