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