jscript: Added support for Function.arguments property.

This commit is contained in:
Jacek Caban 2010-07-27 11:31:01 +02:00 committed by Alexandre Julliard
parent 76c06a6d94
commit 922efb88bb
2 changed files with 76 additions and 22 deletions

View File

@ -35,6 +35,7 @@ typedef struct {
const WCHAR *src_str; const WCHAR *src_str;
DWORD src_len; DWORD src_len;
DWORD length; DWORD length;
DispatchEx *arguments;
} FunctionInstance; } FunctionInstance;
static inline FunctionInstance *function_from_vdisp(vdisp_t *vdisp) static inline FunctionInstance *function_from_vdisp(vdisp_t *vdisp)
@ -53,6 +54,7 @@ static const WCHAR lengthW[] = {'l','e','n','g','t','h',0};
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0}; static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
static const WCHAR applyW[] = {'a','p','p','l','y',0}; static const WCHAR applyW[] = {'a','p','p','l','y',0};
static const WCHAR callW[] = {'c','a','l','l',0}; static const WCHAR callW[] = {'c','a','l','l',0};
static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0};
static IDispatch *get_this(DISPPARAMS *dp) static IDispatch *get_this(DISPPARAMS *dp)
{ {
@ -157,29 +159,20 @@ static HRESULT create_arguments(script_ctx_t *ctx, IDispatch *calee, DISPPARAMS
return S_OK; return S_OK;
} }
static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp, jsexcept_t *ei, static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DispatchEx *arg_disp,
IServiceProvider *caller, DispatchEx **ret) DISPPARAMS *dp, jsexcept_t *ei, IServiceProvider *caller, DispatchEx **ret)
{ {
DispatchEx *var_disp, *arg_disp; DispatchEx *var_disp;
VARIANT var;
HRESULT hres; HRESULT hres;
static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0};
hres = create_dispex(ctx, NULL, NULL, &var_disp); hres = create_dispex(ctx, NULL, NULL, &var_disp);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = create_arguments(ctx, (IDispatch*)_IDispatchEx_(&function->dispex), V_VT(&var) = VT_DISPATCH;
dp, ei, caller, &arg_disp); V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(arg_disp);
if(SUCCEEDED(hres)) { hres = jsdisp_propput_name(var_disp, argumentsW, &var, ei, caller);
VARIANT var;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(arg_disp);
hres = jsdisp_propput_name(var_disp, argumentsW, &var, ei, caller);
jsdisp_release(arg_disp);
}
if(SUCCEEDED(hres)) if(SUCCEEDED(hres))
hres = init_parameters(var_disp, function, dp, ei, caller); hres = init_parameters(var_disp, function, dp, ei, caller);
if(FAILED(hres)) { if(FAILED(hres)) {
@ -194,7 +187,7 @@ static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DI
static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, DISPPARAMS *dp, static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{ {
DispatchEx *var_disp; DispatchEx *var_disp, *arg_disp;
exec_ctx_t *exec_ctx; exec_ctx_t *exec_ctx;
scope_chain_t *scope; scope_chain_t *scope;
HRESULT hres; HRESULT hres;
@ -204,21 +197,34 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis
return E_FAIL; return E_FAIL;
} }
hres = create_var_disp(ctx, function, dp, ei, caller, &var_disp); hres = create_arguments(ctx, (IDispatch*)_IDispatchEx_(&function->dispex),
dp, ei, caller, &arg_disp);
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
hres = create_var_disp(ctx, function, arg_disp, dp, ei, caller, &var_disp);
if(FAILED(hres)) {
jsdisp_release(arg_disp);
return hres;
}
hres = scope_push(function->scope_chain, var_disp, &scope); hres = scope_push(function->scope_chain, var_disp, &scope);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
hres = create_exec_ctx(ctx, this_obj, var_disp, scope, &exec_ctx); hres = create_exec_ctx(ctx, this_obj, var_disp, scope, &exec_ctx);
scope_release(scope); scope_release(scope);
} }
jsdisp_release(var_disp); jsdisp_release(var_disp);
if(FAILED(hres)) if(SUCCEEDED(hres)) {
return hres; DispatchEx *prev_args;
hres = exec_source(exec_ctx, function->parser, function->source, EXECT_FUNCTION, ei, retv); prev_args = function->arguments;
exec_release(exec_ctx); function->arguments = arg_disp;
hres = exec_source(exec_ctx, function->parser, function->source, EXECT_FUNCTION, ei, retv);
function->arguments = prev_args;
jsdisp_release(arg_disp);
exec_release(exec_ctx);
}
return hres; return hres;
} }
@ -531,6 +537,35 @@ HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAM
return S_OK; return S_OK;
} }
static HRESULT Function_arguments(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
FunctionInstance *function = (FunctionInstance*)jsthis->u.jsdisp;
HRESULT hres = S_OK;
TRACE("\n");
switch(flags) {
case DISPATCH_PROPERTYGET: {
if(function->arguments) {
IDispatchEx_AddRef(_IDispatchEx_(function->arguments));
V_VT(retv) = VT_DISPATCH;
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(function->arguments);
}else {
V_VT(retv) = VT_NULL;
}
break;
}
case DISPATCH_PROPERTYPUT:
break;
default:
FIXME("unimplemented flags %x\n", flags);
hres = E_NOTIMPL;
}
return hres;
}
static void Function_destructor(DispatchEx *dispex) static void Function_destructor(DispatchEx *dispex)
{ {
FunctionInstance *This = (FunctionInstance*)dispex; FunctionInstance *This = (FunctionInstance*)dispex;
@ -544,6 +579,7 @@ static void Function_destructor(DispatchEx *dispex)
static const builtin_prop_t Function_props[] = { static const builtin_prop_t Function_props[] = {
{applyW, Function_apply, PROPF_METHOD|2}, {applyW, Function_apply, PROPF_METHOD|2},
{argumentsW, Function_arguments, 0},
{callW, Function_call, PROPF_METHOD|1}, {callW, Function_call, PROPF_METHOD|1},
{lengthW, Function_length, 0}, {lengthW, Function_length, 0},
{toStringW, Function_toString, PROPF_METHOD} {toStringW, Function_toString, PROPF_METHOD}

View File

@ -69,11 +69,13 @@ function testFunc1(x, y) {
ok(arguments["0"] === true, "arguments[0] is not true"); ok(arguments["0"] === true, "arguments[0] is not true");
ok(arguments["1"] === "test", "arguments[1] is not \"test\""); ok(arguments["1"] === "test", "arguments[1] is not \"test\"");
ok(arguments.callee === testFunc1, "arguments.calee !== testFunc1"); ok(arguments.callee === testFunc1, "arguments.calee !== testFunc1");
ok(testFunc1.arguments === arguments, "testFunc1.arguments = " + testFunc1.arguments);
return true; return true;
} }
ok(testFunc1.length === 2, "testFunc1.length is not 2"); ok(testFunc1.length === 2, "testFunc1.length is not 2");
ok(testFunc1.arguments === null, "testFunc1.arguments = " + testFunc1.arguments);
ok(Object.prototype !== undefined, "Object.prototype is undefined"); ok(Object.prototype !== undefined, "Object.prototype is undefined");
ok(Object.prototype.prototype === undefined, "Object.prototype is not undefined"); ok(Object.prototype.prototype === undefined, "Object.prototype is not undefined");
@ -109,6 +111,22 @@ ok(typeof(this) === "object", "typeof(this) is not object");
ok(testFunc1(true, "test") === true, "testFunc1 not returned true"); ok(testFunc1(true, "test") === true, "testFunc1 not returned true");
ok(testFunc1.arguments === null, "testFunc1.arguments = " + testFunc1.arguments);
function testRecFunc(x) {
ok(testRecFunc.arguments === arguments, "testRecFunc.arguments = " + testRecFunc.arguments);
if(x) {
testRecFunc(false);
ok(testRecFunc.arguments === arguments, "testRecFunc.arguments = " + testRecFunc.arguments);
ok(testRecFunc.arguments[0] === true, "testRecFunc.arguments.x = " + testRecFunc.arguments[0]);
}
}
testRecFunc.arguments = 5;
ok(testRecFunc.arguments === null, "testRecFunc.arguments = " + testRecFunc.arguments);
testRecFunc(true);
ok(testRecFunc.arguments === null, "testRecFunc.arguments = " + testRecFunc.arguments);
tmp = (function() {1;})(); tmp = (function() {1;})();
ok(tmp === undefined, "tmp = " + tmp); ok(tmp === undefined, "tmp = " + tmp);
tmp = eval("1;"); tmp = eval("1;");