jscript: Added support for Function.arguments property.

oldstable
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;
DWORD src_len;
DWORD length;
DispatchEx *arguments;
} FunctionInstance;
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 applyW[] = {'a','p','p','l','y',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)
{
@ -157,29 +159,20 @@ static HRESULT create_arguments(script_ctx_t *ctx, IDispatch *calee, DISPPARAMS
return S_OK;
}
static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp, jsexcept_t *ei,
IServiceProvider *caller, DispatchEx **ret)
static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DispatchEx *arg_disp,
DISPPARAMS *dp, jsexcept_t *ei, IServiceProvider *caller, DispatchEx **ret)
{
DispatchEx *var_disp, *arg_disp;
DispatchEx *var_disp;
VARIANT var;
HRESULT hres;
static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0};
hres = create_dispex(ctx, NULL, NULL, &var_disp);
if(FAILED(hres))
return hres;
hres = create_arguments(ctx, (IDispatch*)_IDispatchEx_(&function->dispex),
dp, ei, caller, &arg_disp);
if(SUCCEEDED(hres)) {
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);
}
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(arg_disp);
hres = jsdisp_propput_name(var_disp, argumentsW, &var, ei, caller);
if(SUCCEEDED(hres))
hres = init_parameters(var_disp, function, dp, ei, caller);
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,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
DispatchEx *var_disp;
DispatchEx *var_disp, *arg_disp;
exec_ctx_t *exec_ctx;
scope_chain_t *scope;
HRESULT hres;
@ -204,21 +197,34 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis
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))
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);
if(SUCCEEDED(hres)) {
hres = create_exec_ctx(ctx, this_obj, var_disp, scope, &exec_ctx);
scope_release(scope);
}
jsdisp_release(var_disp);
if(FAILED(hres))
return hres;
if(SUCCEEDED(hres)) {
DispatchEx *prev_args;
hres = exec_source(exec_ctx, function->parser, function->source, EXECT_FUNCTION, ei, retv);
exec_release(exec_ctx);
prev_args = function->arguments;
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;
}
@ -531,6 +537,35 @@ HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAM
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)
{
FunctionInstance *This = (FunctionInstance*)dispex;
@ -544,6 +579,7 @@ static void Function_destructor(DispatchEx *dispex)
static const builtin_prop_t Function_props[] = {
{applyW, Function_apply, PROPF_METHOD|2},
{argumentsW, Function_arguments, 0},
{callW, Function_call, PROPF_METHOD|1},
{lengthW, Function_length, 0},
{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["1"] === "test", "arguments[1] is not \"test\"");
ok(arguments.callee === testFunc1, "arguments.calee !== testFunc1");
ok(testFunc1.arguments === arguments, "testFunc1.arguments = " + testFunc1.arguments);
return true;
}
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.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.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;})();
ok(tmp === undefined, "tmp = " + tmp);
tmp = eval("1;");