mirror of
git://source.winehq.org/git/wine.git
synced 2024-07-21 09:04:10 +00:00
jscript: Implement Function.prototype.bind's thisArg
properly.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
parent
0e49547c7a
commit
35a6555929
|
@ -57,7 +57,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
FunctionInstance function;
|
||||
FunctionInstance *target;
|
||||
IDispatch *this;
|
||||
jsval_t this;
|
||||
unsigned argc;
|
||||
jsval_t args[1];
|
||||
} BindFunction;
|
||||
|
@ -70,7 +70,7 @@ typedef struct {
|
|||
unsigned argc;
|
||||
} ArgumentsInstance;
|
||||
|
||||
static HRESULT create_bind_function(script_ctx_t*,FunctionInstance*,IDispatch*,unsigned,jsval_t*,jsdisp_t**r);
|
||||
static HRESULT create_bind_function(script_ctx_t*,FunctionInstance*,jsval_t,unsigned,jsval_t*,jsdisp_t**r);
|
||||
|
||||
static inline FunctionInstance *function_from_jsdisp(jsdisp_t *jsdisp)
|
||||
{
|
||||
|
@ -448,7 +448,7 @@ static HRESULT Function_call(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig
|
|||
static HRESULT Function_bind(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
|
||||
jsval_t *r)
|
||||
{
|
||||
IDispatch *bound_this = NULL;
|
||||
jsval_t bound_this = jsval_undefined();
|
||||
FunctionInstance *function;
|
||||
jsdisp_t *new_function;
|
||||
HRESULT hres;
|
||||
|
@ -459,18 +459,19 @@ static HRESULT Function_bind(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig
|
|||
return JS_E_FUNCTION_EXPECTED;
|
||||
|
||||
if(argc < 1) {
|
||||
FIXME("no this argument\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if(is_object_instance(argv[0])) {
|
||||
bound_this = get_object(argv[0]);
|
||||
}else if(!is_null(argv[0])) {
|
||||
FIXME("%s is not an object instance\n", debugstr_jsval(argv[0]));
|
||||
return E_NOTIMPL;
|
||||
argc = 1;
|
||||
}else if(is_null(argv[0])) {
|
||||
bound_this = argv[0];
|
||||
}else if(!is_undefined(argv[0])) {
|
||||
IDispatch *obj;
|
||||
hres = to_object(ctx, argv[0], &obj);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
bound_this = jsval_disp(obj);
|
||||
}
|
||||
|
||||
hres = create_bind_function(ctx, function, bound_this, argc - 1, argv + 1, &new_function);
|
||||
jsval_release(bound_this);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
|
@ -849,8 +850,7 @@ static HRESULT BindFunction_call(script_ctx_t *ctx, FunctionInstance *func, jsva
|
|||
memcpy(call_args + function->argc, argv, argc * sizeof(*call_args));
|
||||
}
|
||||
|
||||
hres = function->target->vtbl->call(ctx, function->target, function->this ? jsval_disp(function->this) : jsval_null(),
|
||||
flags, call_argc, call_args, r);
|
||||
hres = function->target->vtbl->call(ctx, function->target, function->this, flags, call_argc, call_args, r);
|
||||
|
||||
heap_free(call_args);
|
||||
return hres;
|
||||
|
@ -877,8 +877,7 @@ static void BindFunction_destructor(FunctionInstance *func)
|
|||
for(i = 0; i < function->argc; i++)
|
||||
jsval_release(function->args[i]);
|
||||
jsdisp_release(&function->target->dispex);
|
||||
if(function->this)
|
||||
IDispatch_Release(function->this);
|
||||
jsval_release(function->this);
|
||||
}
|
||||
|
||||
static const function_vtbl_t BindFunctionVtbl = {
|
||||
|
@ -888,7 +887,7 @@ static const function_vtbl_t BindFunctionVtbl = {
|
|||
BindFunction_destructor
|
||||
};
|
||||
|
||||
static HRESULT create_bind_function(script_ctx_t *ctx, FunctionInstance *target, IDispatch *bound_this, unsigned argc,
|
||||
static HRESULT create_bind_function(script_ctx_t *ctx, FunctionInstance *target, jsval_t bound_this, unsigned argc,
|
||||
jsval_t *argv, jsdisp_t **ret)
|
||||
{
|
||||
BindFunction *function;
|
||||
|
@ -902,8 +901,11 @@ static HRESULT create_bind_function(script_ctx_t *ctx, FunctionInstance *target,
|
|||
jsdisp_addref(&target->dispex);
|
||||
function->target = target;
|
||||
|
||||
if(bound_this)
|
||||
IDispatch_AddRef(function->this = bound_this);
|
||||
hres = jsval_copy(bound_this, &function->this);
|
||||
if(FAILED(hres)) {
|
||||
jsdisp_release(&function->function.dispex);
|
||||
return hres;
|
||||
}
|
||||
|
||||
for(function->argc = 0; function->argc < argc; function->argc++) {
|
||||
hres = jsval_copy(argv[function->argc], function->args + function->argc);
|
||||
|
|
|
@ -1188,6 +1188,23 @@ sync_test("bind", function() {
|
|||
ok(t != a, "t == a");
|
||||
|
||||
ok(Function.prototype.bind.length === 1, "Function.prototype.bind.length = " + Function.prototype.bind.length);
|
||||
|
||||
((function() { ok(this === window, "bind() this = " + this); }).bind())();
|
||||
((function() { ok(this === window, "bind(undefined) = " + this); }).bind(undefined))();
|
||||
((function() { ok(this === window, "bind(nullDisp) = " + this); }).bind(external.nullDisp))();
|
||||
((function() {
|
||||
ok(typeof(this) === "object", "bind(42) typeof(this) = " + typeof(this));
|
||||
ok(this.valueOf() === 42, "bind(42) this = " + this);
|
||||
}).bind(42))();
|
||||
|
||||
r = (Object.prototype.toString.bind())();
|
||||
ok(r === "[object Undefined]", "toString.bind() returned " + r);
|
||||
r = (Object.prototype.toString.bind(undefined))();
|
||||
ok(r === "[object Undefined]", "toString.bind(undefined) returned " + r);
|
||||
r = (Object.prototype.toString.bind(null))();
|
||||
ok(r === "[object Null]", "toString.bind(null) returned " + r);
|
||||
r = (Object.prototype.toString.bind(external.nullDisp))();
|
||||
ok(r === "[object Null]", "toString.bind(nullDisp) returned " + r);
|
||||
});
|
||||
|
||||
sync_test("keys", function() {
|
||||
|
|
Loading…
Reference in a new issue