From: Jacek Caban jacek@codeweavers.com
Based on patch by Gabriel Ivăncescu. --- dlls/jscript/function.c | 125 +++++++++++++++++++++++++++++++++++++++ dlls/jscript/jscript.c | 8 +++ dlls/jscript/jscript.h | 1 + dlls/jscript/jsdisp.idl | 2 + dlls/mshtml/dispex.c | 11 ++++ dlls/mshtml/htmlwindow.c | 10 ++++ 6 files changed, 157 insertions(+)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index ceaf50e8538..c814f8fd4f6 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -70,6 +70,11 @@ typedef struct { UINT32 iid; } HostFunction;
+typedef struct { + FunctionInstance function; + IWineJSDispatchHost *host_iface; +} HostConstructor; + typedef struct { jsdisp_t jsdisp; jsval_t *buf; @@ -1083,6 +1088,126 @@ HRESULT create_host_function(script_ctx_t *ctx, const struct property_info *desc return S_OK; }
+static ULONG HostConstructor_addref(jsdisp_t *jsdisp) +{ + HostConstructor *constr = (HostConstructor*)jsdisp; + return IWineJSDispatchHost_AddRef(constr->host_iface); +} + +static ULONG HostConstructor_release(jsdisp_t *jsdisp) +{ + HostConstructor *constr = (HostConstructor*)jsdisp; + return IWineJSDispatchHost_Release(constr->host_iface); +} + +static HRESULT HostConstructor_lookup_prop(jsdisp_t *jsdisp, const WCHAR *name, unsigned flags, struct property_info *desc) +{ + HostConstructor *constr = (HostConstructor*)jsdisp; + HRESULT hres = IWineJSDispatchHost_LookupProperty(constr->host_iface, name, flags, desc); + assert(hres != S_OK || desc->func_iid); /* external properties are not allowed */ + return hres; +} + +static const builtin_info_t HostConstructor_info = { + .class = JSCLASS_FUNCTION, + .addref = HostConstructor_addref, + .release = HostConstructor_release, + .call = Function_value, + .destructor = Function_destructor, + .gc_traverse = Function_gc_traverse, + .lookup_prop = HostConstructor_lookup_prop, +}; + +static HRESULT HostConstructor_call(script_ctx_t *ctx, FunctionInstance *func, jsval_t vthis, unsigned flags, + unsigned argc, jsval_t *argv, jsval_t *r) +{ + HostConstructor *function = (HostConstructor*)func; + VARIANT buf[6], ret; + DISPPARAMS dp = { .cArgs = argc, .rgvarg = buf }; + EXCEPINFO ei = { 0 }; + HRESULT hres; + unsigned i; + + flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; + if(argc > ARRAYSIZE(buf) && !(dp.rgvarg = malloc(argc * sizeof(*dp.rgvarg)))) + return E_OUTOFMEMORY; + + for(i = 0; i < argc; i++) { + hres = jsval_to_variant(argv[i], &dp.rgvarg[dp.cArgs - i - 1]); + if(FAILED(hres)) + break; + } + + if(SUCCEEDED(hres)) { + V_VT(&ret) = VT_EMPTY; + hres = IWineJSDispatchHost_Construct(function->host_iface, ctx->lcid, flags, &dp, &ret, &ei, + &ctx->jscaller->IServiceProvider_iface); + if(hres == DISP_E_EXCEPTION) + handle_dispatch_exception(ctx, &ei); + if(SUCCEEDED(hres) && r) { + hres = variant_to_jsval(ctx, &ret, r); + VariantClear(&ret); + } + } + + while(i--) + VariantClear(&dp.rgvarg[dp.cArgs - i - 1]); + if(dp.rgvarg != buf) + free(dp.rgvarg); + return hres; +} + +static HRESULT HostConstructor_toString(FunctionInstance *function, jsstr_t **ret) +{ + *ret = jsstr_alloc(L"\nfunction() {\n [native code]\n}\n"); + return *ret ? S_OK : E_OUTOFMEMORY; +} + +static function_code_t *HostConstructor_get_code(FunctionInstance *function) +{ + return NULL; +} + +static void HostConstructor_destructor(FunctionInstance *func) +{ +} + +static HRESULT HostConstructor_gc_traverse(struct gc_ctx *gc_ctx, enum gc_traverse_op op, FunctionInstance *func) +{ + return S_OK; +} + +static const function_vtbl_t HostConstructorVtbl = { + HostConstructor_call, + HostConstructor_toString, + HostConstructor_get_code, + HostConstructor_destructor, + HostConstructor_gc_traverse +}; + +HRESULT init_host_constructor(script_ctx_t *ctx, IWineJSDispatchHost *host_constr, IWineJSDispatch *prototype, + IWineJSDispatch **ret) +{ + HostConstructor *function; + HRESULT hres; + + hres = create_function(ctx, &HostConstructor_info, &HostConstructorVtbl, sizeof(*function), PROPF_METHOD, + FALSE, NULL, (void**)&function); + if(FAILED(hres)) + return hres; + function->host_iface = host_constr; + + hres = jsdisp_define_data_property(&function->function.dispex, L"prototype", PROPF_WRITABLE | PROPF_CONFIGURABLE, + jsval_disp((IDispatch *)prototype)); + if(FAILED(hres)) { + IWineJSDispatch_Free(&function->function.dispex.IWineJSDispatch_iface); + return hres; + } + + *ret = &function->function.dispex.IWineJSDispatch_iface; + return S_OK; +} + static HRESULT BindFunction_get_arguments(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) { return JS_E_INVALID_ACTION; diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 5822cf1222f..c42109b4143 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -1458,11 +1458,19 @@ static HRESULT WINAPI WineJScript_InitHostObject(IWineJScript *iface, IWineJSDis return init_host_object(This->ctx, host_obj, prototype, flags, ret); }
+static HRESULT WINAPI WineJScript_InitHostConstructor(IWineJScript *iface, IWineJSDispatchHost *constr, + IWineJSDispatch *prototype, IWineJSDispatch **ret) +{ + JScript *This = impl_from_IWineJScript(iface); + return init_host_constructor(This->ctx, constr, prototype, ret); +} + static const IWineJScriptVtbl WineJScriptVtbl = { WineJScript_QueryInterface, WineJScript_AddRef, WineJScript_Release, WineJScript_InitHostObject, + WineJScript_InitHostConstructor, };
HRESULT create_jscript_object(BOOL is_encode, REFIID riid, void **ppv) diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 5e3640b69b7..b413b4d1ae9 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -244,6 +244,7 @@ HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,jsdisp_t*,jsdisp_t**); HRESULT init_dispex(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*); HRESULT init_dispex_from_constr(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*); HRESULT init_host_object(script_ctx_t*,IWineJSDispatchHost*,IWineJSDispatch*,UINT32,IWineJSDispatch**); +HRESULT init_host_constructor(script_ctx_t*,IWineJSDispatchHost*,IWineJSDispatch*,IWineJSDispatch**);
HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*); HRESULT disp_call_name(script_ctx_t*,IDispatch*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*); diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index a1b63579fce..bae00d40a3d 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -66,6 +66,7 @@ interface IWineJSDispatchHost : IDispatchEx HRESULT DeleteProperty(DISPID id); HRESULT ConfigureProperty(DISPID id, UINT32 flags); HRESULT CallFunction(DISPID id, UINT32 iid, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); + HRESULT Construct(LCID lcid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); HRESULT GetOuterDispatch(IWineJSDispatchHost **ret); HRESULT ToString(BSTR *str); } @@ -78,4 +79,5 @@ interface IWineJSDispatchHost : IDispatchEx interface IWineJScript : IUnknown { HRESULT InitHostObject(IWineJSDispatchHost *host_obj, IWineJSDispatch *prototype, UINT32 flags, IWineJSDispatch **ret); + HRESULT InitHostConstructor(IWineJSDispatchHost *constr, IWineJSDispatch *prototype, IWineJSDispatch **ret); } diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 817547581e3..d4c560bab75 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2551,6 +2551,16 @@ static HRESULT WINAPI JSDispatchHost_CallFunction(IWineJSDispatchHost *iface, DI return call_builtin_function(This, func, dp, ret, ei, caller); }
+static HRESULT WINAPI JSDispatchHost_Construct(IWineJSDispatchHost *iface, LCID lcid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, + EXCEPINFO *ei, IServiceProvider *caller) +{ + DispatchEx *This = impl_from_IWineJSDispatchHost(iface); + + TRACE("%s (%p)->(%p %p %p %p)\n", This->info->name, This, dp, ret, ei, caller); + + return dispex_prop_call(This, DISPID_VALUE, lcid, flags, dp, ret, ei, caller); +} + static HRESULT WINAPI JSDispatchHost_GetOuterDispatch(IWineJSDispatchHost *iface, IWineJSDispatchHost **ret) { DispatchEx *This = impl_from_IWineJSDispatchHost(iface); @@ -2592,6 +2602,7 @@ static IWineJSDispatchHostVtbl JSDispatchHostVtbl = { JSDispatchHost_DeleteProperty, JSDispatchHost_ConfigureProperty, JSDispatchHost_CallFunction, + JSDispatchHost_Construct, JSDispatchHost_GetOuterDispatch, JSDispatchHost_ToString, }; diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index a2afcdfdfbc..c9ad3dbd0c3 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3505,6 +3505,15 @@ static HRESULT WINAPI WindowDispEx_CallFunction(IWineJSDispatchHost *iface, DISP id, iid, dp, ret, ei, caller); }
+static HRESULT WINAPI WindowDispEx_Construct(IWineJSDispatchHost *iface, LCID lcid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, + EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); + + return IWineJSDispatchHost_Construct(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, + lcid, flags, dp, ret, ei, caller); +} + static HRESULT WINAPI WindowDispEx_GetOuterDispatch(IWineJSDispatchHost *iface, IWineJSDispatchHost **ret) { HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface); @@ -3545,6 +3554,7 @@ static const IWineJSDispatchHostVtbl WindowDispExVtbl = { WindowDispEx_DeleteProperty, WindowDispEx_ConfigureProperty, WindowDispEx_CallFunction, + WindowDispEx_Construct, WindowDispEx_GetOuterDispatch, WindowDispEx_ToString, };