| @@ -120,6 +120,85 @@ static void Fp_call(js_State *J, unsigned int argc) · 119 unmodified lines |
| 120 | 120 | js_call(J, argc - 1); |
| 121 | 121 | } |
| 122 | 122 | |
| 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 | + |
| 123 | 202 | void jsB_initfunction(js_State *J) |
| 124 | 203 | { |
| 125 | 204 | J->Function_prototype->u.c.function = jsB_Function_prototype; |
| @@ -130,6 +209,7 @@ void jsB_initfunction(js_State *J) · 4 unmodified lines |
| 130 | 209 | jsB_propf(J, "toString", Fp_toString, 2); |
| 131 | 210 | jsB_propf(J, "apply", Fp_apply, 2); |
| 132 | 211 | jsB_propf(J, "call", Fp_call, 1); |
| 212 | + jsB_propf(J, "bind", Fp_bind, 1); |
| 133 | 213 | } |
| 134 | 214 | js_newcconstructor(J, jsB_Function, jsB_Function, 1); |
| 135 | 215 | js_defglobal(J, "Function", JS_DONTENUM); |