diff --git a/dlls/jscript/Makefile.in b/dlls/jscript/Makefile.in index ac64b7f0b18..0288b4c7279 100644 --- a/dlls/jscript/Makefile.in +++ b/dlls/jscript/Makefile.in @@ -10,6 +10,7 @@ RC_SRCS = rsrc.rc C_SRCS = \ dispex.c \ engine.c \ + function.c \ global.c \ jscript.c \ jscript_main.c \ diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 7d24699e82f..ae32f1a0118 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -292,8 +292,16 @@ static HRESULT prop_get(DispatchEx *This, dispex_prop_t *prop, LCID lcid, DISPPA switch(prop->type) { case PROP_BUILTIN: if(prop->u.p->flags & PROPF_METHOD) { - FIXME("function objects not supported\n"); - return E_NOTIMPL; + DispatchEx *obj; + hres = create_builtin_function(This->ctx, prop->u.p->invoke, prop->u.p->flags, NULL, &obj); + if(FAILED(hres)) + break; + + prop->type = PROP_VARIANT; + V_VT(&prop->u.var) = VT_DISPATCH; + V_DISPATCH(&prop->u.var) = (IDispatch*)_IDispatchEx_(obj); + + hres = VariantCopy(retv, &prop->u.var); }else { hres = prop->u.p->invoke(This, lcid, DISPATCH_PROPERTYGET, dp, retv, ei, caller); } @@ -688,7 +696,7 @@ static IDispatchExVtbl DispatchExVtbl = { DispatchEx_GetNameSpaceParent }; -static HRESULT jsdisp_set_prot_prop(DispatchEx *dispex, DispatchEx *prototype) +HRESULT jsdisp_set_prototype(DispatchEx *dispex, DispatchEx *prototype) { VARIANT *var; @@ -705,7 +713,7 @@ static HRESULT jsdisp_set_prot_prop(DispatchEx *dispex, DispatchEx *prototype) return S_OK; } -static HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype) +HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype) { static const WCHAR prototypeW[] = {'p','r','o','t','o','t','y','p','e',0}; @@ -740,7 +748,7 @@ static HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx, const builtin_ if(prototype) { HRESULT hres; - hres = jsdisp_set_prot_prop(dispex, prototype); + hres = jsdisp_set_prototype(dispex, prototype); if(FAILED(hres)) { IDispatchEx_Release(_IDispatchEx_(dispex)); return hres; diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c new file mode 100644 index 00000000000..13a6711fba8 --- /dev/null +++ b/dlls/jscript/function.c @@ -0,0 +1,182 @@ +/* + * Copyright 2008 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "jscript.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(jscript); + +typedef struct { + DispatchEx dispex; + builtin_invoke_t value_proc; + DWORD flags; + DWORD length; +} FunctionInstance; + +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 toLocaleStringW[] = {'t','o','L','o','c','a','l','e','S','t','r','i','n','g',0}; +static const WCHAR valueOfW[] = {'v','a','l','u','e','O','f',0}; +static const WCHAR applyW[] = {'a','p','p','l','y',0}; +static const WCHAR callW[] = {'c','a','l','l',0}; +static const WCHAR hasOwnPropertyW[] = {'h','a','s','O','w','n','P','r','o','p','e','r','t','y',0}; +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 HRESULT Function_length(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Function_toString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Function_toLocaleString(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Function_valueOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Function_apply(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Function_call(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Function_hasOwnProperty(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Function_propertyIsEnumerable(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Function_isPrototypeOf(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static HRESULT Function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + FIXME("\n"); + return E_NOTIMPL; +} + +static void Function_destructor(DispatchEx *dispex) +{ + FunctionInstance *This = (FunctionInstance*)dispex; + + heap_free(This); +} + +static const builtin_prop_t Function_props[] = { + {applyW, Function_apply, PROPF_METHOD}, + {callW, Function_call, PROPF_METHOD}, + {hasOwnPropertyW, Function_hasOwnProperty, PROPF_METHOD}, + {isPrototypeOfW, Function_isPrototypeOf, PROPF_METHOD}, + {lengthW, Function_length, 0}, + {propertyIsEnumerableW, Function_propertyIsEnumerable, PROPF_METHOD}, + {toLocaleStringW, Function_toLocaleString, PROPF_METHOD}, + {toStringW, Function_toString, PROPF_METHOD}, + {valueOfW, Function_valueOf, PROPF_METHOD} +}; + +static const builtin_info_t Function_info = { + JSCLASS_FUNCTION, + {NULL, Function_value, 0}, + sizeof(Function_props)/sizeof(*Function_props), + Function_props, + Function_destructor, + NULL +}; + +static HRESULT create_function(script_ctx_t *ctx, DWORD flags, DispatchEx *prototype, FunctionInstance **ret) +{ + FunctionInstance *function; + HRESULT hres; + + function = heap_alloc_zero(sizeof(FunctionInstance)); + if(!function) + return E_OUTOFMEMORY; + + hres = init_dispex(&function->dispex, ctx, &Function_info, NULL); + if(FAILED(hres)) + return hres; + + function->flags = flags; + function->length = flags & PROPF_ARGMASK; + + if(prototype) { + hres = jsdisp_set_prototype(&function->dispex, prototype); + if(FAILED(hres)) { + IDispatchEx_Release(_IDispatchEx_(&function->dispex)); + return hres; + } + } + + *ret = function; + return S_OK; +} + +HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc, DWORD flags, + DispatchEx *prototype, DispatchEx **ret) +{ + FunctionInstance *function; + HRESULT hres; + + hres = create_function(ctx, flags, prototype, &function); + if(FAILED(hres)) + return hres; + + function->value_proc = value_proc; + + *ret = &function->dispex; + return S_OK; +} diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 31812bf7d20..a8fc37914d3 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -49,6 +49,7 @@ typedef struct DispatchEx DispatchEx; typedef enum { JSCLASS_NONE, + JSCLASS_FUNCTION, JSCLASS_GLOBAL } jsclass_t; @@ -87,10 +88,14 @@ struct DispatchEx { #define _IDispatchEx_(x) ((IDispatchEx*) &(x)->lpIDispatchExVtbl) HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,DispatchEx*,DispatchEx**); +HRESULT init_dispex(DispatchEx*,script_ctx_t*,const builtin_info_t*,DispatchEx*); HRESULT disp_call(IDispatch*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,jsexcept_t*,IServiceProvider*); HRESULT disp_propget(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); HRESULT disp_propput(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); HRESULT jsdisp_propput_name(DispatchEx*,const WCHAR*,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); +HRESULT jsdisp_set_prototype(DispatchEx*,DispatchEx*); + +HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,DWORD,DispatchEx*,DispatchEx**); HRESULT to_boolean(VARIANT*,VARIANT_BOOL*);