Jacek Caban : jscript: Added Function.[[call]] implementation.
Alexandre Julliard
julliard at winehq.org
Thu Sep 11 08:00:44 CDT 2008
Module: wine
Branch: master
Commit: dd9f8f7dbc7a9010a610dee25567cee384d57cfd
URL: http://source.winehq.org/git/wine.git/?a=commit;h=dd9f8f7dbc7a9010a610dee25567cee384d57cfd
Author: Jacek Caban <jacek at codeweavers.com>
Date: Wed Sep 10 21:06:09 2008 +0200
jscript: Added Function.[[call]] implementation.
---
dlls/jscript/engine.c | 24 +++++++++
dlls/jscript/function.c | 121 ++++++++++++++++++++++++++++++++++++++++++-
dlls/jscript/tests/lang.js | 2 +
3 files changed, 144 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index fa15b40..275943a 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -120,6 +120,30 @@ static void exprval_set_idref(exprval_t *val, IDispatch *disp, DISPID id)
IDispatch_AddRef(disp);
}
+HRESULT scope_push(scope_chain_t *scope, DispatchEx *obj, scope_chain_t **ret)
+{
+ scope_chain_t *new_scope;
+
+ new_scope = heap_alloc(sizeof(scope_chain_t));
+ if(!new_scope)
+ return E_OUTOFMEMORY;
+
+ new_scope->ref = 1;
+
+ IDispatchEx_AddRef(_IDispatchEx_(obj));
+ new_scope->obj = obj;
+
+ if(scope) {
+ scope_addref(scope);
+ new_scope->next = scope;
+ }else {
+ new_scope->next = NULL;
+ }
+
+ *ret = new_scope;
+ return S_OK;
+}
+
void scope_release(scope_chain_t *scope)
{
if(--scope->ref)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c
index a9c61e0..3cd63f5 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -46,6 +46,99 @@ static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p',
static const WCHAR propertyIsEnumerableW[] = {'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
+static IDispatch *get_this(DISPPARAMS *dp)
+{
+ DWORD i;
+
+ for(i=0; i < dp->cNamedArgs; i++) {
+ if(dp->rgdispidNamedArgs[i] == DISPID_THIS) {
+ if(V_VT(dp->rgvarg+i) == VT_DISPATCH)
+ return V_DISPATCH(dp->rgvarg+i);
+
+ WARN("This is not VT_DISPATCH\n");
+ return NULL;
+ }
+ }
+
+ TRACE("no this passed\n");
+ return NULL;
+}
+
+static HRESULT create_var_disp(FunctionInstance *function, LCID lcid, DISPPARAMS *dp, jsexcept_t *ei,
+ IServiceProvider *caller, DispatchEx **ret)
+{
+ DispatchEx *var_disp;
+ HRESULT hres;
+
+ hres = create_dispex(function->dispex.ctx, NULL, NULL, &var_disp);
+ if(FAILED(hres))
+ return hres;
+
+ *ret = var_disp;
+ return S_OK;
+}
+
+static HRESULT invoke_source(FunctionInstance *function, IDispatch *this_obj, LCID lcid, DISPPARAMS *dp,
+ VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+ DispatchEx *var_disp;
+ exec_ctx_t *exec_ctx;
+ scope_chain_t *scope;
+ HRESULT hres;
+
+ if(!function->source) {
+ FIXME("no source\n");
+ return E_FAIL;
+ }
+
+ hres = create_var_disp(function, lcid, dp, ei, caller, &var_disp);
+ if(FAILED(hres))
+ return hres;
+
+ hres = scope_push(function->scope_chain, var_disp, &scope);
+ if(SUCCEEDED(hres)) {
+ hres = create_exec_ctx(this_obj, var_disp, scope, &exec_ctx);
+ scope_release(scope);
+ }
+ if(FAILED(hres))
+ return hres;
+
+ hres = exec_source(exec_ctx, function->parser, function->source, ei, retv);
+ exec_release(exec_ctx);
+
+ return hres;
+}
+
+static HRESULT invoke_function(FunctionInstance *function, LCID lcid, DISPPARAMS *dp,
+ VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+ IDispatch *this_obj;
+
+ if(!(this_obj = get_this(dp)))
+ this_obj = (IDispatch*)_IDispatchEx_(function->dispex.ctx->script_disp);
+
+ return invoke_source(function, this_obj, lcid, dp, retv, ei, caller);
+}
+
+static HRESULT invoke_value_proc(FunctionInstance *function, LCID lcid, WORD flags, DISPPARAMS *dp,
+ VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
+{
+ DispatchEx *this_obj = NULL;
+ IDispatch *this_disp;
+ HRESULT hres;
+
+ this_disp = get_this(dp);
+ if(this_disp)
+ this_obj = iface_to_jsdisp((IUnknown*)this_disp);
+
+ hres = function->value_proc(this_obj ? this_obj : function->dispex.ctx->script_disp, lcid,
+ flags, dp, retv, ei, caller);
+
+ if(this_obj)
+ jsdisp_release(this_obj);
+ return hres;
+}
+
static HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
{
@@ -123,10 +216,32 @@ static HRESULT Function_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags,
}
static HRESULT Function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
+ VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
- FIXME("\n");
- return E_NOTIMPL;
+ FunctionInstance *function;
+
+ TRACE("\n");
+
+ if(dispex->builtin_info->class != JSCLASS_FUNCTION) {
+ ERR("dispex is not a function\n");
+ return E_FAIL;
+ }
+
+ function = (FunctionInstance*)dispex;
+
+ switch(flags) {
+ case DISPATCH_METHOD:
+ if(function->value_proc)
+ return invoke_value_proc(function, lcid, flags, dp, retv, ei, caller);
+
+ return invoke_function(function, lcid, dp, retv, ei, caller);
+
+ default:
+ FIXME("not implemented flags %x\n", flags);
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
}
static void Function_destructor(DispatchEx *dispex)
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index 4c26c2f..b21a9e8 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -70,4 +70,6 @@ ok(typeof(String) === "function", "typeof(String) is not function");
ok(typeof(ScriptEngine) === "function", "typeof(ScriptEngine) is not function");
ok(typeof(this) === "object", "typeof(this) is not object");
+ok(testFunc1(true, "test") === true, "testFunc1 not returned true");
+
reportSuccess();
More information about the wine-cvs
mailing list