jscript: Added Function.[[call]] implementation.

This commit is contained in:
Jacek Caban 2008-09-10 21:06:09 +02:00 committed by Alexandre Julliard
parent a273e35f9b
commit dd9f8f7dbc
3 changed files with 144 additions and 3 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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();