Showing the changes to jsfunction.c (1 of 2 files). Show all
Unified · Split
| @@ -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); |