Module: wine Branch: master Commit: 922efb88bbdb56fa12149bdd6bd377934f8b3b3b URL: http://source.winehq.org/git/wine.git/?a=commit;h=922efb88bbdb56fa12149bdd6b...
Author: Jacek Caban jacek@codeweavers.com Date: Tue Jul 27 11:31:01 2010 +0200
jscript: Added support for Function.arguments property.
---
dlls/jscript/function.c | 80 ++++++++++++++++++++++++++++++++------------ dlls/jscript/tests/lang.js | 18 ++++++++++ 2 files changed, 76 insertions(+), 22 deletions(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index df46f1d..9f5fb3b 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -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; + + 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;
- hres = exec_source(exec_ctx, function->parser, function->source, EXECT_FUNCTION, ei, retv); - exec_release(exec_ctx); + 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} diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index 36a75f5..c3059be 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -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;");