The TypeInfo is built when it is retrieved and frozen at that moment, even if the script changes after that and more identifiers are added to it, or existing ones deleted.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 110 ++++++++++++++++++++++++++++++++++++++++ dlls/jscript/function.c | 31 +++++++++++ dlls/jscript/jscript.h | 1 + 3 files changed, 142 insertions(+)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 92e9b96..6c6d25a 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -19,6 +19,7 @@ #include <assert.h>
#include "jscript.h" +#include "engine.h"
#include "wine/debug.h"
@@ -70,6 +71,20 @@ static inline dispex_prop_t *get_prop(jsdisp_t *This, DISPID id) return This->props+id; }
+static inline BOOL is_function_prop(dispex_prop_t *prop) +{ + BOOL ret = FALSE; + + if (is_object_instance(prop->u.val)) + { + jsdisp_t *jsdisp = iface_to_jsdisp(get_object(prop->u.val)); + + if (jsdisp) ret = is_class(jsdisp, JSCLASS_FUNCTION); + jsdisp_release(jsdisp); + } + return ret; +} + static DWORD get_flags(jsdisp_t *This, dispex_prop_t *prop) { if(prop->type == PROP_PROTREF) { @@ -590,9 +605,21 @@ static HRESULT fill_protrefs(jsdisp_t *This) return S_OK; }
+struct typeinfo_func { + dispex_prop_t *prop; + function_code_t *code; +}; + typedef struct { ITypeInfo ITypeInfo_iface; LONG ref; + + UINT num_funcs; + UINT num_vars; + struct typeinfo_func *funcs; + dispex_prop_t **vars; + + jsdisp_t *jsdisp; } ScriptTypeInfo;
static inline ScriptTypeInfo *ScriptTypeInfo_from_ITypeInfo(ITypeInfo *iface) @@ -632,11 +659,17 @@ static ULONG WINAPI ScriptTypeInfo_Release(ITypeInfo *iface) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); LONG ref = InterlockedDecrement(&This->ref); + UINT i;
TRACE("(%p) ref=%d\n", This, ref);
if (!ref) { + for (i = This->num_funcs; i--;) + release_bytecode(This->funcs[i].code->bytecode); + IDispatchEx_Release(&This->jsdisp->IDispatchEx_iface); + heap_free(This->funcs); + heap_free(This->vars); heap_free(This); } return ref; @@ -897,17 +930,94 @@ static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LC ITypeInfo **ppTInfo) { jsdisp_t *This = impl_from_IDispatchEx(iface); + dispex_prop_t *prop, *cur, *end, **typevar; + UINT num_funcs = 0, num_vars = 0; + struct typeinfo_func *typefunc; + function_code_t *func_code; ScriptTypeInfo *typeinfo; + unsigned pos;
TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
if (iTInfo != 0) return DISP_E_BADINDEX;
+ for (prop = This->props, end = prop + This->prop_cnt; prop != end; prop++) + { + if (!prop->name || prop->type != PROP_JSVAL || !(prop->flags & PROPF_ENUMERABLE)) + continue; + + /* If two identifiers differ only by case, the TypeInfo fails */ + pos = This->props[get_props_idx(This, prop->hash)].bucket_head; + while (pos) + { + cur = This->props + pos; + + if (prop->hash == cur->hash && prop != cur && + cur->type == PROP_JSVAL && (cur->flags & PROPF_ENUMERABLE) && + !wcsicmp(prop->name, cur->name)) + { + return TYPE_E_AMBIGUOUSNAME; + } + pos = cur->bucket_next; + } + + if (is_function_prop(prop)) + { + if (Function_get_code(as_jsdisp(get_object(prop->u.val)))) + num_funcs++; + } + else num_vars++; + } + if (!(typeinfo = heap_alloc(sizeof(*typeinfo)))) return E_OUTOFMEMORY;
typeinfo->ITypeInfo_iface.lpVtbl = &ScriptTypeInfoVtbl; typeinfo->ref = 1; + typeinfo->num_vars = num_vars; + typeinfo->num_funcs = num_funcs; + typeinfo->jsdisp = This; + + typeinfo->funcs = heap_alloc(sizeof(*typeinfo->funcs) * num_funcs); + if (!typeinfo->funcs) + { + heap_free(typeinfo); + return E_OUTOFMEMORY; + } + + typeinfo->vars = heap_alloc(sizeof(*typeinfo->vars) * num_vars); + if (!typeinfo->vars) + { + heap_free(typeinfo->funcs); + heap_free(typeinfo); + return E_OUTOFMEMORY; + } + + typefunc = typeinfo->funcs; + typevar = typeinfo->vars; + for (prop = This->props; prop != end; prop++) + { + if (!prop->name || prop->type != PROP_JSVAL || !(prop->flags & PROPF_ENUMERABLE)) + continue; + + if (is_function_prop(prop)) + { + func_code = Function_get_code(as_jsdisp(get_object(prop->u.val))); + if (!func_code) continue; + + typefunc->prop = prop; + typefunc->code = func_code; + typefunc++; + + /* The function may be deleted, so keep a ref */ + bytecode_addref(func_code->bytecode); + } + else + *typevar++ = prop; + } + + /* Keep a ref to the props and their names */ + IDispatchEx_AddRef(&This->IDispatchEx_iface);
*ppTInfo = &typeinfo->ITypeInfo_iface; return S_OK; diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 7a44f50..52c1267 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -37,6 +37,7 @@ typedef struct { struct _function_vtbl_t { HRESULT (*call)(script_ctx_t*,FunctionInstance*,IDispatch*,unsigned,unsigned,jsval_t*,jsval_t*); HRESULT (*toString)(FunctionInstance*,jsstr_t**); + function_code_t* (*get_code)(FunctionInstance*); void (*destructor)(FunctionInstance*); };
@@ -524,6 +525,16 @@ static HRESULT Function_get_arguments(script_ctx_t *ctx, jsdisp_t *jsthis, jsval return S_OK; }
+function_code_t *Function_get_code(jsdisp_t *jsthis) +{ + FunctionInstance *function; + + assert(is_class(jsthis, JSCLASS_FUNCTION)); + function = function_from_jsdisp(jsthis); + + return function->vtbl->get_code(function); +} + static void Function_destructor(jsdisp_t *dispex) { FunctionInstance *function = function_from_jsdisp(dispex); @@ -638,6 +649,11 @@ static HRESULT NativeFunction_toString(FunctionInstance *func, jsstr_t **ret) return S_OK; }
+static function_code_t *NativeFunction_get_code(FunctionInstance *function) +{ + return NULL; +} + static void NativeFunction_destructor(FunctionInstance *function) { } @@ -645,6 +661,7 @@ static void NativeFunction_destructor(FunctionInstance *function) static const function_vtbl_t NativeFunctionVtbl = { NativeFunction_call, NativeFunction_toString, + NativeFunction_get_code, NativeFunction_destructor };
@@ -749,6 +766,13 @@ static HRESULT InterpretedFunction_toString(FunctionInstance *func, jsstr_t **re return *ret ? S_OK : E_OUTOFMEMORY; }
+static function_code_t *InterpretedFunction_get_code(FunctionInstance *func) +{ + InterpretedFunction *function = (InterpretedFunction*)func; + + return function->func_code; +} + static void InterpretedFunction_destructor(FunctionInstance *func) { InterpretedFunction *function = (InterpretedFunction*)func; @@ -761,6 +785,7 @@ static void InterpretedFunction_destructor(FunctionInstance *func) static const function_vtbl_t InterpretedFunctionVtbl = { InterpretedFunction_call, InterpretedFunction_toString, + InterpretedFunction_get_code, InterpretedFunction_destructor };
@@ -842,6 +867,11 @@ static HRESULT BindFunction_toString(FunctionInstance *function, jsstr_t **ret) return *ret ? S_OK : E_OUTOFMEMORY; }
+static function_code_t *BindFunction_get_code(FunctionInstance *function) +{ + return NULL; +} + static void BindFunction_destructor(FunctionInstance *func) { BindFunction *function = (BindFunction*)func; @@ -858,6 +888,7 @@ static void BindFunction_destructor(FunctionInstance *func) static const function_vtbl_t BindFunctionVtbl = { BindFunction_call, BindFunction_toString, + BindFunction_get_code, BindFunction_destructor };
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 5d635b7..7174db8 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -307,6 +307,7 @@ HRESULT Function_invoke(jsdisp_t*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*) DE
HRESULT Function_value(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN; HRESULT Function_get_value(script_ctx_t*,jsdisp_t*,jsval_t*) DECLSPEC_HIDDEN; +struct _function_code_t *Function_get_code(jsdisp_t*) DECLSPEC_HIDDEN; #define DEFAULT_FUNCTION_VALUE {NULL, Function_value,0, Function_get_value}
HRESULT throw_eval_error(script_ctx_t*,HRESULT,const WCHAR*) DECLSPEC_HIDDEN;
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 6c6d25a..ef002e4 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -25,6 +25,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(jscript);
+static const GUID GUID_JScriptTypeInfo = {0xc59c6b12,0xf6c1,0x11cf,{0x88,0x35,0x00,0xa0,0xc9,0x11,0xe8,0xb2}}; + #define FDEX_VERSION_MASK 0xf0000000 #define GOLDEN_RATIO 0x9E3779B9U
@@ -678,10 +680,32 @@ static ULONG WINAPI ScriptTypeInfo_Release(ITypeInfo *iface) static HRESULT WINAPI ScriptTypeInfo_GetTypeAttr(ITypeInfo *iface, TYPEATTR **ppTypeAttr) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); - - FIXME("(%p)->(%p)\n", This, ppTypeAttr); - - return E_NOTIMPL; + TYPEATTR *attr; + + TRACE("(%p)->(%p)\n", This, ppTypeAttr); + + if (!ppTypeAttr) return E_INVALIDARG; + + attr = heap_alloc_zero(sizeof(*attr)); + if (!attr) return E_OUTOFMEMORY; + + attr->guid = GUID_JScriptTypeInfo; + attr->lcid = LOCALE_USER_DEFAULT; + attr->memidConstructor = MEMBERID_NIL; + attr->memidDestructor = MEMBERID_NIL; + attr->cbSizeInstance = 4; + attr->typekind = TKIND_DISPATCH; + attr->cFuncs = This->num_funcs; + attr->cVars = This->num_vars; + attr->cImplTypes = 1; + attr->cbSizeVft = sizeof(IDispatchVtbl); + attr->cbAlignment = 4; + attr->wTypeFlags = TYPEFLAG_FDISPATCHABLE; + attr->wMajorVerNum = JSCRIPT_MAJOR_VERSION; + attr->wMinorVerNum = JSCRIPT_MINOR_VERSION; + + *ppTypeAttr = attr; + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_GetTypeComp(ITypeInfo *iface, ITypeComp **ppTComp) @@ -829,7 +853,9 @@ static void WINAPI ScriptTypeInfo_ReleaseTypeAttr(ITypeInfo *iface, TYPEATTR *pT { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%p)\n", This, pTypeAttr); + TRACE("(%p)->(%p)\n", This, pTypeAttr); + + heap_free(pTypeAttr); }
static void WINAPI ScriptTypeInfo_ReleaseFuncDesc(ITypeInfo *iface, FUNCDESC *pFuncDesc)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62024
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1039:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1039:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The wow64 build failed
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index ef002e4..1f062fe 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -720,10 +720,33 @@ static HRESULT WINAPI ScriptTypeInfo_GetTypeComp(ITypeInfo *iface, ITypeComp **p static HRESULT WINAPI ScriptTypeInfo_GetFuncDesc(ITypeInfo *iface, UINT index, FUNCDESC **ppFuncDesc) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + struct typeinfo_func *func; + FUNCDESC *desc; + unsigned i;
- FIXME("(%p)->(%u %p)\n", This, index, ppFuncDesc); + TRACE("(%p)->(%u %p)\n", This, index, ppFuncDesc);
- return E_NOTIMPL; + if (!ppFuncDesc) return E_INVALIDARG; + if (index >= This->num_funcs) return TYPE_E_ELEMENTNOTFOUND; + func = &This->funcs[index]; + + /* Store the parameter array after the FUNCDESC structure */ + desc = heap_alloc_zero(sizeof(*desc) + sizeof(ELEMDESC) * func->code->param_cnt); + if (!desc) return E_OUTOFMEMORY; + + desc->memid = prop_to_id(This->jsdisp, func->prop); + desc->funckind = FUNC_DISPATCH; + desc->invkind = INVOKE_FUNC; + desc->callconv = CC_STDCALL; + desc->cParams = func->code->param_cnt; + desc->elemdescFunc.tdesc.vt = VT_VARIANT; + + if (func->code->param_cnt) desc->lprgelemdescParam = (ELEMDESC*)(desc + 1); + for (i = 0; i < func->code->param_cnt; i++) + desc->lprgelemdescParam[i].tdesc.vt = VT_VARIANT; + + *ppFuncDesc = desc; + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_GetVarDesc(ITypeInfo *iface, UINT index, VARDESC **ppVarDesc) @@ -862,7 +885,9 @@ static void WINAPI ScriptTypeInfo_ReleaseFuncDesc(ITypeInfo *iface, FUNCDESC *pF { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%p)\n", This, pFuncDesc); + TRACE("(%p)->(%p)\n", This, pFuncDesc); + + heap_free(pFuncDesc); }
static void WINAPI ScriptTypeInfo_ReleaseVarDesc(ITypeInfo *iface, VARDESC *pVarDesc)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62025
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1064:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1064:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The wow64 build failed
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 1f062fe..df87aed 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -752,10 +752,22 @@ static HRESULT WINAPI ScriptTypeInfo_GetFuncDesc(ITypeInfo *iface, UINT index, F static HRESULT WINAPI ScriptTypeInfo_GetVarDesc(ITypeInfo *iface, UINT index, VARDESC **ppVarDesc) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + VARDESC *desc;
- FIXME("(%p)->(%u %p)\n", This, index, ppVarDesc); + TRACE("(%p)->(%u %p)\n", This, index, ppVarDesc);
- return E_NOTIMPL; + if (!ppVarDesc) return E_INVALIDARG; + if (index >= This->num_vars) return TYPE_E_ELEMENTNOTFOUND; + + desc = heap_alloc_zero(sizeof(*desc)); + if (!desc) return E_OUTOFMEMORY; + + desc->memid = prop_to_id(This->jsdisp, This->vars[index]); + desc->varkind = VAR_DISPATCH; + desc->elemdescVar.tdesc.vt = VT_VARIANT; + + *ppVarDesc = desc; + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_GetNames(ITypeInfo *iface, MEMBERID memid, BSTR *rgBstrNames, @@ -894,7 +906,9 @@ static void WINAPI ScriptTypeInfo_ReleaseVarDesc(ITypeInfo *iface, VARDESC *pVar { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%p)\n", This, pVarDesc); + TRACE("(%p)->(%p)\n", This, pVarDesc); + + heap_free(pVarDesc); }
static const ITypeInfoVtbl ScriptTypeInfoVtbl = {
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62026
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1078:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1078:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The wow64 build failed
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 47 +++++++++++++++++++++++++++++++++++-- dlls/jscript/jscript.h | 1 + dlls/jscript/jscript_main.c | 25 ++++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index df87aed..1ac747b 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -802,10 +802,53 @@ static HRESULT WINAPI ScriptTypeInfo_GetIDsOfNames(ITypeInfo *iface, LPOLESTR *r MEMBERID *pMemId) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface); + ITypeInfo *disp_typeinfo; + const WCHAR *name; + HRESULT hr = S_OK; + int i, j, arg;
- FIXME("(%p)->(%p %u %p)\n", This, rgszNames, cNames, pMemId); + TRACE("(%p)->(%p %u %p)\n", This, rgszNames, cNames, pMemId);
- return E_NOTIMPL; + if (!rgszNames || !cNames || !pMemId) return E_INVALIDARG; + + for (i = 0; i < cNames; i++) pMemId[i] = MEMBERID_NIL; + name = rgszNames[0]; + + for (i = 0; i < This->num_funcs; i++) + { + struct typeinfo_func *func = &This->funcs[i]; + + if (wcsicmp(name, func->prop->name)) continue; + pMemId[0] = prop_to_id(This->jsdisp, func->prop); + + for (j = 1; j < cNames; j++) + { + name = rgszNames[j]; + for (arg = func->code->param_cnt; --arg >= 0;) + if (!wcsicmp(name, func->code->params[arg])) + break; + if (arg >= 0) + pMemId[j] = arg; + else + hr = DISP_E_UNKNOWNNAME; + } + return hr; + } + + for (i = 0; i < This->num_vars; i++) + { + dispex_prop_t *var = This->vars[i]; + + if (wcsicmp(name, var->name)) continue; + pMemId[0] = prop_to_id(This->jsdisp, var); + return S_OK; + } + + /* Look into the inherited IDispatch */ + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + return ITypeInfo_GetIDsOfNames(disp_typeinfo, rgszNames, cNames, pMemId); }
static HRESULT WINAPI ScriptTypeInfo_Invoke(ITypeInfo *iface, PVOID pvInstance, MEMBERID memid, WORD wFlags, diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 7174db8..4ec5004 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -87,6 +87,7 @@ static inline LPWSTR heap_strdupW(LPCWSTR str) typedef struct jsdisp_t jsdisp_t;
extern HINSTANCE jscript_hinstance DECLSPEC_HIDDEN; +HRESULT get_dispatch_typeinfo(ITypeInfo**) DECLSPEC_HIDDEN;
#define PROPF_ARGMASK 0x00ff #define PROPF_METHOD 0x0100 diff --git a/dlls/jscript/jscript_main.c b/dlls/jscript/jscript_main.c index 9f9f412..532cdf9 100644 --- a/dlls/jscript/jscript_main.c +++ b/dlls/jscript/jscript_main.c @@ -37,6 +37,30 @@ LONG module_ref = 0; DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
HINSTANCE jscript_hinstance; +static ITypeInfo *dispatch_typeinfo; + +HRESULT get_dispatch_typeinfo(ITypeInfo **out) +{ + ITypeInfo *typeinfo; + ITypeLib *typelib; + HRESULT hr; + + if (!dispatch_typeinfo) + { + hr = LoadRegTypeLib(&IID_StdOle, STDOLE_MAJORVERNUM, STDOLE_MINORVERNUM, STDOLE_LCID, &typelib); + if (FAILED(hr)) return hr; + + hr = ITypeLib_GetTypeInfoOfGuid(typelib, &IID_IDispatch, &typeinfo); + ITypeLib_Release(typelib); + if (FAILED(hr)) return hr; + + if (InterlockedCompareExchangePointer((void**)&dispatch_typeinfo, typeinfo, NULL)) + ITypeInfo_Release(typeinfo); + } + + *out = dispatch_typeinfo; + return S_OK; +}
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) { @@ -145,6 +169,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) break; case DLL_PROCESS_DETACH: if (lpv) break; + if (dispatch_typeinfo) ITypeInfo_Release(dispatch_typeinfo); free_strings(); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62027
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1121:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:671:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1121:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The wow64 build failed
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 64 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 1ac747b..fb636b4 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -614,6 +614,7 @@ struct typeinfo_func {
typedef struct { ITypeInfo ITypeInfo_iface; + ITypeComp ITypeComp_iface; LONG ref;
UINT num_funcs; @@ -629,12 +630,19 @@ static inline ScriptTypeInfo *ScriptTypeInfo_from_ITypeInfo(ITypeInfo *iface) return CONTAINING_RECORD(iface, ScriptTypeInfo, ITypeInfo_iface); }
+static inline ScriptTypeInfo *ScriptTypeInfo_from_ITypeComp(ITypeComp *iface) +{ + return CONTAINING_RECORD(iface, ScriptTypeInfo, ITypeComp_iface); +} + static HRESULT WINAPI ScriptTypeInfo_QueryInterface(ITypeInfo *iface, REFIID riid, void **ppv) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
if (IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITypeInfo, riid)) *ppv = &This->ITypeInfo_iface; + else if (IsEqualGUID(&IID_ITypeComp, riid)) + *ppv = &This->ITypeComp_iface; else { WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); @@ -712,9 +720,13 @@ static HRESULT WINAPI ScriptTypeInfo_GetTypeComp(ITypeInfo *iface, ITypeComp **p { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
- FIXME("(%p)->(%p)\n", This, ppTComp); + TRACE("(%p)->(%p)\n", This, ppTComp);
- return E_NOTIMPL; + if (!ppTComp) return E_INVALIDARG; + + *ppTComp = &This->ITypeComp_iface; + ITypeInfo_AddRef(iface); + return S_OK; }
static HRESULT WINAPI ScriptTypeInfo_GetFuncDesc(ITypeInfo *iface, UINT index, FUNCDESC **ppFuncDesc) @@ -979,6 +991,53 @@ static const ITypeInfoVtbl ScriptTypeInfoVtbl = { ScriptTypeInfo_ReleaseVarDesc };
+static HRESULT WINAPI ScriptTypeComp_QueryInterface(ITypeComp *iface, REFIID riid, void **ppv) +{ + ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface); + return ITypeInfo_QueryInterface(&This->ITypeInfo_iface, riid, ppv); +} + +static ULONG WINAPI ScriptTypeComp_AddRef(ITypeComp *iface) +{ + ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface); + return ITypeInfo_AddRef(&This->ITypeInfo_iface); +} + +static ULONG WINAPI ScriptTypeComp_Release(ITypeComp *iface) +{ + ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface); + return ITypeInfo_Release(&This->ITypeInfo_iface); +} + +static HRESULT WINAPI ScriptTypeComp_Bind(ITypeComp *iface, LPOLESTR szName, ULONG lHashVal, WORD wFlags, + ITypeInfo **ppTInfo, DESCKIND *pDescKind, BINDPTR *pBindPtr) +{ + ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface); + + FIXME("(%p)->(%s %08x %d %p %p %p)\n", This, debugstr_w(szName), lHashVal, + wFlags, ppTInfo, pDescKind, pBindPtr); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ScriptTypeComp_BindType(ITypeComp *iface, LPOLESTR szName, ULONG lHashVal, + ITypeInfo **ppTInfo, ITypeComp **ppTComp) +{ + ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface); + + FIXME("(%p)->(%s %08x %p %p)\n", This, debugstr_w(szName), lHashVal, ppTInfo, ppTComp); + + return E_NOTIMPL; +} + +static const ITypeCompVtbl ScriptTypeCompVtbl = { + ScriptTypeComp_QueryInterface, + ScriptTypeComp_AddRef, + ScriptTypeComp_Release, + ScriptTypeComp_Bind, + ScriptTypeComp_BindType +}; + static inline jsdisp_t *impl_from_IDispatchEx(IDispatchEx *iface) { return CONTAINING_RECORD(iface, jsdisp_t, IDispatchEx_iface); @@ -1081,6 +1140,7 @@ static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, LC return E_OUTOFMEMORY;
typeinfo->ITypeInfo_iface.lpVtbl = &ScriptTypeInfoVtbl; + typeinfo->ITypeComp_iface.lpVtbl = &ScriptTypeCompVtbl; typeinfo->ref = 1; typeinfo->num_vars = num_vars; typeinfo->num_funcs = num_funcs;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62028
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1181:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1181:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The wow64 build failed
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 49 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index fb636b4..6576605 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -1013,11 +1013,56 @@ static HRESULT WINAPI ScriptTypeComp_Bind(ITypeComp *iface, LPOLESTR szName, ULO ITypeInfo **ppTInfo, DESCKIND *pDescKind, BINDPTR *pBindPtr) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface); + UINT flags = wFlags ? wFlags : ~0; + ITypeInfo *disp_typeinfo; + ITypeComp *disp_typecomp; + HRESULT hr; + UINT i;
- FIXME("(%p)->(%s %08x %d %p %p %p)\n", This, debugstr_w(szName), lHashVal, + TRACE("(%p)->(%s %08x %d %p %p %p)\n", This, debugstr_w(szName), lHashVal, wFlags, ppTInfo, pDescKind, pBindPtr);
- return E_NOTIMPL; + if (!szName || !ppTInfo || !pDescKind || !pBindPtr) + return E_INVALIDARG; + + for (i = 0; i < This->num_funcs; i++) + { + if (wcsicmp(szName, This->funcs[i].prop->name)) continue; + if (!(flags & INVOKE_FUNC)) return TYPE_E_TYPEMISMATCH; + + hr = ITypeInfo_GetFuncDesc(&This->ITypeInfo_iface, i, &pBindPtr->lpfuncdesc); + if (FAILED(hr)) return hr; + + *pDescKind = DESCKIND_FUNCDESC; + *ppTInfo = &This->ITypeInfo_iface; + ITypeInfo_AddRef(*ppTInfo); + return S_OK; + } + + for (i = 0; i < This->num_vars; i++) + { + if (wcsicmp(szName, This->vars[i]->name)) continue; + if (!(flags & INVOKE_PROPERTYGET)) return TYPE_E_TYPEMISMATCH; + + hr = ITypeInfo_GetVarDesc(&This->ITypeInfo_iface, i, &pBindPtr->lpvardesc); + if (FAILED(hr)) return hr; + + *pDescKind = DESCKIND_VARDESC; + *ppTInfo = &This->ITypeInfo_iface; + ITypeInfo_AddRef(*ppTInfo); + return S_OK; + } + + /* Look into the inherited IDispatch */ + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + hr = ITypeInfo_GetTypeComp(disp_typeinfo, &disp_typecomp); + if (FAILED(hr)) return hr; + + hr = ITypeComp_Bind(disp_typecomp, szName, lHashVal, wFlags, ppTInfo, pDescKind, pBindPtr); + ITypeComp_Release(disp_typecomp); + return hr; }
static HRESULT WINAPI ScriptTypeComp_BindType(ITypeComp *iface, LPOLESTR szName, ULONG lHashVal,
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62029
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1226:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1226:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The wow64 build failed
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 6576605..6cc6df5 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -1069,10 +1069,25 @@ static HRESULT WINAPI ScriptTypeComp_BindType(ITypeComp *iface, LPOLESTR szName, ITypeInfo **ppTInfo, ITypeComp **ppTComp) { ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeComp(iface); + ITypeInfo *disp_typeinfo; + ITypeComp *disp_typecomp; + HRESULT hr;
- FIXME("(%p)->(%s %08x %p %p)\n", This, debugstr_w(szName), lHashVal, ppTInfo, ppTComp); + TRACE("(%p)->(%s %08x %p %p)\n", This, debugstr_w(szName), lHashVal, ppTInfo, ppTComp);
- return E_NOTIMPL; + if (!szName || !ppTInfo || !ppTComp) + return E_INVALIDARG; + + /* Look into the inherited IDispatch */ + hr = get_dispatch_typeinfo(&disp_typeinfo); + if (FAILED(hr)) return hr; + + hr = ITypeInfo_GetTypeComp(disp_typeinfo, &disp_typecomp); + if (FAILED(hr)) return hr; + + hr = ITypeComp_BindType(disp_typecomp, szName, lHashVal, ppTInfo, ppTComp); + ITypeComp_Release(disp_typecomp); + return hr; }
static const ITypeCompVtbl ScriptTypeCompVtbl = {
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62030
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1241:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1241:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The wow64 build failed
Signed-off-by: Jacek Caban jacek@codeweavers.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/tests/jscript.c | 362 +++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+)
diff --git a/dlls/jscript/tests/jscript.c b/dlls/jscript/tests/jscript.c index 0904374..e608367 100644 --- a/dlls/jscript/tests/jscript.c +++ b/dlls/jscript/tests/jscript.c @@ -33,6 +33,8 @@ #define IActiveScriptParse_Release IActiveScriptParse64_Release #define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew #define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText +#define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_64_Release +#define IActiveScriptParseProcedure2_ParseProcedureText IActiveScriptParseProcedure2_64_ParseProcedureText
#else
@@ -40,10 +42,13 @@ #define IActiveScriptParse_Release IActiveScriptParse32_Release #define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew #define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText +#define IActiveScriptParseProcedure2_Release IActiveScriptParseProcedure2_32_Release +#define IActiveScriptParseProcedure2_ParseProcedureText IActiveScriptParseProcedure2_32_ParseProcedureText
#endif
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); +DEFINE_GUID(IID_IScriptTypeInfo, 0xc59c6b12, 0xf6c1, 0x11cf, 0x88,0x35, 0x00,0xa0,0xc9,0x11,0xe8,0xb2);
static const CLSID CLSID_JScript = {0xf414c260,0x6ac0,0x11cf,{0xb6,0xd1,0x00,0xaa,0x00,0xbb,0xbb,0x58}}; @@ -274,6 +279,20 @@ static IDispatchEx *get_script_dispatch(IActiveScript *script) return dispex; }
+static void parse_script(IActiveScriptParse *parser, const WCHAR *src) +{ + HRESULT hres; + + SET_EXPECT(OnEnterScript); + SET_EXPECT(OnLeaveScript); + + hres = IActiveScriptParse_ParseScriptText(parser, src, NULL, NULL, NULL, 0, 0, 0, NULL, NULL); + ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres); + + CHECK_CALLED(OnEnterScript); + CHECK_CALLED(OnLeaveScript); +} + #define get_disp_id(a,b,c,d) _get_disp_id(__LINE__,a,b,c,d) static void _get_disp_id(unsigned line, IDispatchEx *dispex, const WCHAR *name, HRESULT exhr, DISPID *id) { @@ -907,6 +926,347 @@ static void test_code_persistence(void) CHECK_CALLED(OnStateChange_CLOSED); }
+static void test_typeinfo(const WCHAR *parse_func_name) +{ + static struct + { + const WCHAR *name; + UINT num_args; + } func[] = + { + { L"emptyfn", 0 }, + { L"voidfn", 0 }, + { L"math", 2 }, + { L"foobar", 1 }, + { L"C", 0 }, + { L"funcvar", 2 }, + { L"f1", 1 }, + { L"f2", 1 } + }; + static struct + { + const WCHAR *name; + } var[] = + { + { L"global_var" }, + { L"uninit" }, + { L"obj" } + }; + const WCHAR *source = L"" + "var global_var = 42;\n" + + "function emptyfn() { }\n" + "function voidfn() { return void(0); }\n" + "function math(x, y) { return x - y; }\n" + "function foobar(x) { return "foobar"; }\n" + + "function C() {\n" + " this.x;\n" + " this.strret = function() { return "ret"; }\n" + "}\n" + + "var uninit;\n" + "var obj = new C();\n" + + "var funcvar = function(x, y) { return x * y; };\n" + "var native_func = decodeURI;\n" + + "(function() {\n" + " f1 = function infuncexpr(x) { return 1; }\n" + " f2 = function infuncexpr(x) { return 2; }\n" + "})();\n"; + UINT expected_funcs_cnt = parse_func_name ? 0 : ARRAY_SIZE(func); + UINT expected_vars_cnt = parse_func_name ? 0 : ARRAY_SIZE(var); + + ITypeInfo *typeinfo, *typeinfo2; + ITypeComp *typecomp, *typecomp2; + IActiveScriptParse *parser; + IActiveScript *script; + FUNCDESC *funcdesc; + VARDESC *vardesc; + IDispatchEx *disp; + DESCKIND desckind; + BINDPTR bindptr; + MEMBERID memid; + TYPEATTR *attr; + UINT index; + HRESULT hr; + WCHAR str[64], *names = str; + int i; + + if (parse_func_name) + trace("Testing TypeInfo for function %s...\n", wine_dbgstr_w(parse_func_name)); + else + trace("Testing TypeInfo for script dispatch...\n"); + + script = create_jscript(); + + hr = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parser); + ok(hr == S_OK, "Could not get IActiveScriptParse iface: %08x\n", hr); + + SET_EXPECT(GetLCID); + hr = IActiveScript_SetScriptSite(script, &ActiveScriptSite); + ok(hr == S_OK, "SetScriptSite failed: %08x\n", hr); + CHECK_CALLED(GetLCID); + + SET_EXPECT(OnStateChange_INITIALIZED); + hr = IActiveScriptParse_InitNew(parser); + ok(hr == S_OK, "InitNew failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_INITIALIZED); + + SET_EXPECT(OnStateChange_CONNECTED); + hr = IActiveScript_SetScriptState(script, SCRIPTSTATE_CONNECTED); + ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_CONNECTED); + + if (parse_func_name) + { + IActiveScriptParseProcedure2 *parse_proc; + IDispatch *proc_disp; + + hr = IActiveScript_QueryInterface(script, &IID_IActiveScriptParseProcedure2, (void**)&parse_proc); + ok(hr == S_OK, "Could not get IActiveScriptParse: %08x\n", hr); + + hr = IActiveScriptParseProcedure2_ParseProcedureText(parse_proc, source, NULL, parse_func_name, + NULL, NULL, NULL, 0, 0, SCRIPTPROC_IMPLICIT_THIS | SCRIPTPROC_IMPLICIT_PARENTS, &proc_disp); + ok(hr == S_OK, "ParseProcedureText failed: %08x\n", hr); + IActiveScriptParseProcedure2_Release(parse_proc); + + hr = IDispatch_QueryInterface(proc_disp, &IID_IDispatchEx, (void**)&disp); + ok(hr == S_OK, "Could not get IDispatchEx: %08x\n", hr); + IDispatch_Release(proc_disp); + } + else + { + parse_script(parser, source); + disp = get_script_dispatch(script); + } + + hr = IDispatchEx_QueryInterface(disp, &IID_ITypeInfo, (void**)&typeinfo); + ok(hr == E_NOINTERFACE, "QueryInterface(IID_ITypeInfo) returned: %08x\n", hr); + hr = IDispatchEx_GetTypeInfo(disp, 1, LOCALE_USER_DEFAULT, &typeinfo); + ok(hr == DISP_E_BADINDEX, "GetTypeInfo returned: %08x\n", hr); + hr = IDispatchEx_GetTypeInfo(disp, 0, LOCALE_USER_DEFAULT, &typeinfo); + ok(hr == S_OK, "GetTypeInfo failed: %08x\n", hr); + hr = IDispatchEx_GetTypeInfo(disp, 0, LOCALE_USER_DEFAULT, &typeinfo2); + ok(hr == S_OK, "GetTypeInfo failed: %08x\n", hr); + ok(typeinfo != typeinfo2, "TypeInfo was not supposed to be shared.\n"); + ITypeInfo_Release(typeinfo2); + + hr = ITypeInfo_GetTypeAttr(typeinfo, &attr); + ok(hr == S_OK, "GetTypeAttr failed: %08x\n", hr); + ok(IsEqualGUID(&attr->guid, &IID_IScriptTypeInfo), "Unexpected GUID %s\n", wine_dbgstr_guid(&attr->guid)); + ok(attr->lcid == LOCALE_USER_DEFAULT, "Unexpected LCID %u\n", attr->lcid); + ok(attr->memidConstructor == MEMBERID_NIL, "Unexpected constructor memid %u\n", attr->memidConstructor); + ok(attr->memidDestructor == MEMBERID_NIL, "Unexpected destructor memid %u\n", attr->memidDestructor); + ok(attr->cbSizeInstance == 4, "Unexpected cbSizeInstance %u\n", attr->cbSizeInstance); + ok(attr->typekind == TKIND_DISPATCH, "Unexpected typekind %u\n", attr->typekind); + ok(attr->cFuncs == expected_funcs_cnt, "Unexpected cFuncs %u\n", attr->cFuncs); + ok(attr->cVars == expected_vars_cnt, "Unexpected cVars %u\n", attr->cVars); + ok(attr->cImplTypes == 1, "Unexpected cImplTypes %u\n", attr->cImplTypes); + ok(attr->cbSizeVft == sizeof(IDispatchVtbl), "Unexpected cbSizeVft %u\n", attr->cbSizeVft); + ok(attr->cbAlignment == 4, "Unexpected cbAlignment %u\n", attr->cbAlignment); + ok(attr->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "Unexpected wTypeFlags 0x%x\n", attr->wTypeFlags); + ok(attr->tdescAlias.vt == VT_EMPTY, "Unexpected tdescAlias.vt %d\n", attr->tdescAlias.vt); + ok(attr->idldescType.wIDLFlags == IDLFLAG_NONE, "Unexpected idldescType.wIDLFlags 0x%x\n", attr->idldescType.wIDLFlags); + ITypeInfo_ReleaseTypeAttr(typeinfo, attr); + + /* GetIDsOfNames looks into the inherited types as well */ + wcscpy(str, L"queryinterface"); + hr = ITypeInfo_GetIDsOfNames(typeinfo, NULL, 1, &memid); + ok(hr == E_INVALIDARG, "GetIDsOfNames returned: %08x\n", hr); + hr = ITypeInfo_GetIDsOfNames(typeinfo, &names, 1, NULL); + ok(hr == E_INVALIDARG, "GetIDsOfNames returned: %08x\n", hr); + hr = ITypeInfo_GetIDsOfNames(typeinfo, &names, 0, &memid); + ok(hr == E_INVALIDARG, "GetIDsOfNames returned: %08x\n", hr); + hr = ITypeInfo_GetIDsOfNames(typeinfo, &names, 1, &memid); + ok(hr == S_OK, "GetIDsOfNames failed: %08x\n", hr); + ok(!lstrcmpW(str, L"queryinterface"), "Unexpected string %s\n", wine_dbgstr_w(str)); + if (expected_funcs_cnt) + { + wcscpy(str, L"Math"); + hr = ITypeInfo_GetIDsOfNames(typeinfo, &names, 1, &memid); + ok(hr == S_OK, "GetIDsOfNames failed: %08x\n", hr); + ok(!lstrcmpW(str, L"Math"), "Unexpected string %s\n", wine_dbgstr_w(str)); + } + + /* Check variable descriptions */ + hr = ITypeInfo_GetVarDesc(typeinfo, 0, NULL); + ok(hr == E_INVALIDARG, "GetVarDesc returned: %08x\n", hr); + hr = ITypeInfo_GetVarDesc(typeinfo, 1337, &vardesc); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetVarDesc returned: %08x\n", hr); + for (i = 0; i < expected_vars_cnt; i++) + { + hr = ITypeInfo_GetVarDesc(typeinfo, i, &vardesc); + ok(hr == S_OK, "GetVarDesc(%u) failed: %08x\n", i, hr); + ok(vardesc->memid <= 0xFFFF, "[%u] Unexpected memid 0x%x\n", i, vardesc->memid); + ok(vardesc->lpstrSchema == NULL, "[%u] Unexpected lpstrSchema %p\n", i, vardesc->lpstrSchema); + ok(vardesc->oInst == 0, "[%u] Unexpected oInst %u\n", i, vardesc->oInst); + ok(vardesc->varkind == VAR_DISPATCH, "[%u] Unexpected varkind %d\n", i, vardesc->varkind); + ok(vardesc->wVarFlags == 0, "[%u] Unexpected wVarFlags 0x%x\n", i, vardesc->wVarFlags); + ok(vardesc->elemdescVar.tdesc.vt == VT_VARIANT, + "[%u] Unexpected variable type vt %d (expected %d)\n", i, vardesc->elemdescVar.tdesc.vt, 0); + ok(vardesc->elemdescVar.paramdesc.pparamdescex == NULL, + "[%u] Unexpected variable type pparamdescex %p\n", i, vardesc->elemdescVar.paramdesc.pparamdescex); + ok(vardesc->elemdescVar.paramdesc.wParamFlags == PARAMFLAG_NONE, + "[%u] Unexpected variable type wParamFlags 0x%x\n", i, vardesc->elemdescVar.paramdesc.wParamFlags); + ITypeInfo_ReleaseVarDesc(typeinfo, vardesc); + } + + /* Check function descriptions */ + hr = ITypeInfo_GetFuncDesc(typeinfo, 0, NULL); + ok(hr == E_INVALIDARG, "GetFuncDesc returned: %08x\n", hr); + hr = ITypeInfo_GetFuncDesc(typeinfo, 1337, &funcdesc); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetFuncDesc returned: %08x\n", hr); + for (i = 0; i < expected_funcs_cnt; i++) + { + hr = ITypeInfo_GetFuncDesc(typeinfo, i, &funcdesc); + ok(hr == S_OK, "GetFuncDesc(%u) failed: %08x\n", i, hr); + ok(funcdesc->memid <= 0xFFFF, "[%u] Unexpected memid 0x%x\n", i, funcdesc->memid); + ok(funcdesc->lprgscode == NULL, "[%u] Unexpected lprgscode %p\n", i, funcdesc->lprgscode); + ok(func[i].num_args ? (funcdesc->lprgelemdescParam != NULL) : (funcdesc->lprgelemdescParam == NULL), + "[%u] Unexpected lprgelemdescParam %p\n", i, funcdesc->lprgelemdescParam); + ok(funcdesc->funckind == FUNC_DISPATCH, "[%u] Unexpected funckind %u\n", i, funcdesc->funckind); + ok(funcdesc->invkind == INVOKE_FUNC, "[%u] Unexpected invkind %u\n", i, funcdesc->invkind); + ok(funcdesc->callconv == CC_STDCALL, "[%u] Unexpected callconv %u\n", i, funcdesc->callconv); + ok(funcdesc->cParams == func[i].num_args, "[%u] Unexpected cParams %d (expected %d)\n", + i, funcdesc->cParams, func[i].num_args); + ok(funcdesc->cParamsOpt == 0, "[%u] Unexpected cParamsOpt %d\n", i, funcdesc->cParamsOpt); + ok(funcdesc->cScodes == 0, "[%u] Unexpected cScodes %d\n", i, funcdesc->cScodes); + ok(funcdesc->wFuncFlags == 0, "[%u] Unexpected wFuncFlags 0x%x\n", i, funcdesc->wFuncFlags); + ok(funcdesc->elemdescFunc.tdesc.vt == VT_VARIANT, + "[%u] Unexpected return type vt %d\n", i, funcdesc->elemdescFunc.tdesc.vt); + ok(funcdesc->elemdescFunc.paramdesc.pparamdescex == NULL, + "[%u] Unexpected return type pparamdescex %p\n", i, funcdesc->elemdescFunc.paramdesc.pparamdescex); + ok(funcdesc->elemdescFunc.paramdesc.wParamFlags == PARAMFLAG_NONE, + "[%u] Unexpected return type wParamFlags 0x%x\n", i, funcdesc->elemdescFunc.paramdesc.wParamFlags); + if (funcdesc->lprgelemdescParam) + for (index = 0; index < funcdesc->cParams; index++) + { + ok(funcdesc->lprgelemdescParam[index].tdesc.vt == VT_VARIANT, + "[%u] Unexpected parameter %u vt %d\n", i, index, funcdesc->lprgelemdescParam[index].tdesc.vt); + ok(funcdesc->lprgelemdescParam[index].paramdesc.pparamdescex == NULL, + "[%u] Unexpected parameter %u pparamdescex %p\n", i, index, funcdesc->lprgelemdescParam[index].paramdesc.pparamdescex); + ok(funcdesc->lprgelemdescParam[index].paramdesc.wParamFlags == PARAMFLAG_NONE, + "[%u] Unexpected parameter %u wParamFlags 0x%x\n", i, index, funcdesc->lprgelemdescParam[index].paramdesc.wParamFlags); + } + ITypeInfo_ReleaseFuncDesc(typeinfo, funcdesc); + } + + /* Test TypeComp Binds */ + hr = ITypeInfo_QueryInterface(typeinfo, &IID_ITypeComp, (void**)&typecomp); + ok(hr == S_OK, "QueryInterface(IID_ITypeComp) failed: %08x\n", hr); + hr = ITypeInfo_GetTypeComp(typeinfo, NULL); + ok(hr == E_INVALIDARG, "GetTypeComp returned: %08x\n", hr); + hr = ITypeInfo_GetTypeComp(typeinfo, &typecomp2); + ok(hr == S_OK, "GetTypeComp failed: %08x\n", hr); + ok(typecomp == typecomp2, "QueryInterface(IID_ITypeComp) and GetTypeComp returned different TypeComps\n"); + ITypeComp_Release(typecomp2); + wcscpy(str, L"not_found"); + hr = ITypeComp_Bind(typecomp, NULL, 0, 0, &typeinfo2, &desckind, &bindptr); + ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr); + hr = ITypeComp_Bind(typecomp, str, 0, 0, NULL, &desckind, &bindptr); + ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr); + hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, NULL, &bindptr); + ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr); + hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, NULL); + ok(hr == E_INVALIDARG, "Bind returned: %08x\n", hr); + hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, &bindptr); + ok(hr == S_OK, "Bind failed: %08x\n", hr); + ok(desckind == DESCKIND_NONE, "Unexpected desckind %u\n", desckind); + wcscpy(str, L"addRef"); + hr = ITypeComp_Bind(typecomp, str, 0, 0, &typeinfo2, &desckind, &bindptr); + ok(hr == S_OK, "Bind failed: %08x\n", hr); + ok(desckind == DESCKIND_FUNCDESC, "Unexpected desckind %u\n", desckind); + ok(!lstrcmpW(str, L"addRef"), "Unexpected string %s\n", wine_dbgstr_w(str)); + ITypeInfo_ReleaseFuncDesc(typeinfo2, bindptr.lpfuncdesc); + ITypeInfo_Release(typeinfo2); + for (i = 0; i < expected_vars_cnt; i++) + { + wcscpy(str, var[i].name); + hr = ITypeComp_Bind(typecomp, str, 0, INVOKE_PROPERTYGET, &typeinfo2, &desckind, &bindptr); + ok(hr == S_OK, "Bind failed: %08x\n", hr); + ok(desckind == DESCKIND_VARDESC, "Unexpected desckind %u\n", desckind); + ITypeInfo_ReleaseVarDesc(typeinfo2, bindptr.lpvardesc); + ITypeInfo_Release(typeinfo2); + } + for (i = 0; i < expected_funcs_cnt; i++) + { + wcscpy(str, func[i].name); + hr = ITypeComp_Bind(typecomp, str, 0, INVOKE_FUNC, &typeinfo2, &desckind, &bindptr); + ok(hr == S_OK, "Bind failed: %08x\n", hr); + ok(desckind == DESCKIND_FUNCDESC, "Unexpected desckind %u\n", desckind); + ITypeInfo_ReleaseFuncDesc(typeinfo2, bindptr.lpfuncdesc); + ITypeInfo_Release(typeinfo2); + } + wcscpy(str, L"JScriptTypeInfo"); + hr = ITypeComp_BindType(typecomp, NULL, 0, &typeinfo2, &typecomp2); + ok(hr == E_INVALIDARG, "BindType returned: %08x\n", hr); + hr = ITypeComp_BindType(typecomp, str, 0, NULL, &typecomp2); + ok(hr == E_INVALIDARG, "BindType returned: %08x\n", hr); + hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, NULL); + ok(hr == E_INVALIDARG, "BindType returned: %08x\n", hr); + hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, &typecomp2); + ok(hr == S_OK, "BindType failed: %08x\n", hr); + ok(!typeinfo2, "Unexpected TypeInfo %p (expected null)\n", typeinfo2); + ok(!typecomp2, "Unexpected TypeComp %p (expected null)\n", typecomp2); + wcscpy(str, L"C"); + hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, &typecomp2); + ok(hr == S_OK, "BindType failed: %08x\n", hr); + ok(!typeinfo2, "Unexpected TypeInfo %p (expected null)\n", typeinfo2); + ok(!typecomp2, "Unexpected TypeComp %p (expected null)\n", typecomp2); + wcscpy(str, L"IDispatch"); + hr = ITypeComp_BindType(typecomp, str, 0, &typeinfo2, &typecomp2); + ok(hr == S_OK, "BindType failed: %08x\n", hr); + ok(!typeinfo2, "Unexpected TypeInfo %p (expected null)\n", typeinfo2); + ok(!typecomp2, "Unexpected TypeComp %p (expected null)\n", typecomp2); + ITypeComp_Release(typecomp); + + /* Updating the script won't update the typeinfo obtained before, + but it will be reflected in any typeinfo obtained afterwards. */ + if (!parse_func_name) + { + parse_script(parser, L"" + "var new_var;\n" + "function new_func() { }\n"); + + hr = IDispatchEx_GetTypeInfo(disp, 0, LOCALE_USER_DEFAULT, &typeinfo2); + ok(hr == S_OK, "GetTypeInfo failed: %08x\n", hr); + hr = ITypeInfo_GetTypeAttr(typeinfo, &attr); + ok(hr == S_OK, "GetTypeAttr failed: %08x\n", hr); + ok(attr->cFuncs == expected_funcs_cnt, "Unexpected cFuncs %u\n", attr->cFuncs); + ok(attr->cVars == expected_vars_cnt, "Unexpected cVars %u\n", attr->cVars); + ITypeInfo_ReleaseTypeAttr(typeinfo, attr); + hr = ITypeInfo_GetTypeAttr(typeinfo2, &attr); + ok(hr == S_OK, "GetTypeAttr failed: %08x\n", hr); + ok(attr->cFuncs == expected_funcs_cnt + 1, "Unexpected cFuncs %u\n", attr->cFuncs); + ok(attr->cVars == expected_vars_cnt + 1, "Unexpected cVars %u\n", attr->cVars); + ITypeInfo_ReleaseTypeAttr(typeinfo2, attr); + ITypeInfo_Release(typeinfo2); + + /* Adding an identifier that differs only in case gives an error + when retrieving the TypeInfo, even though it is valid jscript. */ + parse_script(parser, L"var NEW_FUNC;\n"); + hr = IDispatchEx_GetTypeInfo(disp, 0, LOCALE_USER_DEFAULT, &typeinfo2); + ok(hr == TYPE_E_AMBIGUOUSNAME, "GetTypeInfo returned: %08x\n", hr); + } + + ITypeInfo_Release(typeinfo); + IDispatchEx_Release(disp); + IActiveScriptParse_Release(parser); + + SET_EXPECT(OnStateChange_DISCONNECTED); + SET_EXPECT(OnStateChange_INITIALIZED); + SET_EXPECT(OnStateChange_CLOSED); + hr = IActiveScript_Close(script); + ok(hr == S_OK, "Close failed: %08x\n", hr); + CHECK_CALLED(OnStateChange_DISCONNECTED); + CHECK_CALLED(OnStateChange_INITIALIZED); + CHECK_CALLED(OnStateChange_CLOSED); + + IActiveScript_Release(script); +} + static BOOL check_jscript(void) { IActiveScriptProperty *script_prop; @@ -931,6 +1291,8 @@ START_TEST(jscript) test_jscript_uninitializing(); test_aggregation(); test_code_persistence(); + test_typeinfo(NULL); + test_typeinfo(L"some_func_name");
trace("Testing JScriptEncode object...\n"); engine_clsid = &CLSID_JScriptEncode;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62031
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1241:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:679:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1241:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The wow64 build failed
Signed-off-by: Jacek Caban jacek@codeweavers.com
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62023
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:669:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1013:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:669:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1013:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The wow64 build failed
Was the testbot not synced with wine master? The bytecode field patch should have been committed yesterday, AFAIK.
On 12/12/19 3:01 PM, Marvin wrote:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=62023
Your paranoid android.
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:669:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1013:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The win32 build failed
=== debian10 (build log) ===
../../../wine/dlls/jscript/dispex.c:669:49: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ ../../../wine/dlls/jscript/dispex.c:1013:38: error: ‘function_code_t’ {aka ‘struct _function_code_t’} has no member named ‘bytecode’ Task: The wow64 build failed
On Thu, 12 Dec 2019, Gabriel Ivăncescu wrote:
Was the testbot not synced with wine master? The bytecode field patch should have been committed yesterday, AFAIK.
Yes. The change in the wine-gecko package name broke the update. I sent a patch to fix this and I'm going to manually update the debian VM shortly.
On Thu, 12 Dec 2019, Francois Gouget wrote:
On Thu, 12 Dec 2019, Gabriel Ivăncescu wrote:
Was the testbot not synced with wine master? The bytecode field patch should have been committed yesterday, AFAIK.
Yes. The change in the wine-gecko package name broke the update. I sent a patch to fix this and I'm going to manually update the debian VM shortly.
Done.