Jacek Caban : jscript: Added support for Function.arguments property.

Alexandre Julliard julliard at winehq.org
Wed Jul 28 10:45:03 CDT 2010


Module: wine
Branch: master
Commit: 922efb88bbdb56fa12149bdd6bd377934f8b3b3b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=922efb88bbdb56fa12149bdd6bd377934f8b3b3b

Author: Jacek Caban <jacek at 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;");




More information about the wine-cvs mailing list