[PATCH 02/10] jscript: Store the necessary function and variable info in the TypeInfo.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Mon Dec 9 11:12:42 CST 2019
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
dlls/jscript/dispex.c | 109 ++++++++++++++++++++++++++++++++++++++++
dlls/jscript/function.c | 5 ++
dlls/jscript/jscript.h | 1 +
3 files changed, 115 insertions(+)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 92e9b96..5710fdd 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -70,6 +70,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 +604,21 @@ static HRESULT fill_protrefs(jsdisp_t *This)
return S_OK;
}
+struct typeinfo_func {
+ dispex_prop_t *prop;
+ jsdisp_t *disp;
+};
+
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 +658,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--;)
+ IDispatchEx_Release(&This->funcs[i].disp->IDispatchEx_iface);
+ IDispatchEx_Release(&This->jsdisp->IDispatchEx_iface);
+ heap_free(This->funcs);
+ heap_free(This->vars);
heap_free(This);
}
return ref;
@@ -897,17 +929,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;
ScriptTypeInfo *typeinfo;
+ jsdisp_t *fn;
+ 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))
+ {
+ fn = impl_from_IDispatchEx((IDispatchEx*)get_object(prop->u.val));
+ if (is_source_function(fn)) 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))
+ {
+ fn = impl_from_IDispatchEx((IDispatchEx*)get_object(prop->u.val));
+ if (!is_source_function(fn)) continue;
+
+ typefunc->prop = prop;
+ typefunc->disp = fn;
+ typefunc++;
+
+ /* The function's object may be deleted, so keep it alive */
+ IDispatchEx_AddRef(&fn->IDispatchEx_iface);
+ }
+ 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..98d1259 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -803,6 +803,11 @@ HRESULT create_source_function(script_ctx_t *ctx, bytecode_t *code, function_cod
return S_OK;
}
+BOOL is_source_function(jsdisp_t *jsdisp)
+{
+ return function_from_jsdisp(jsdisp)->vtbl == &InterpretedFunctionVtbl;
+}
+
static HRESULT BindFunction_call(script_ctx_t *ctx, FunctionInstance *func, IDispatch *this_obj, unsigned flags,
unsigned argc, jsval_t *argv, jsval_t *r)
{
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 5d635b7..91923f8 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -303,6 +303,7 @@ HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,const WCHAR*,cons
jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
HRESULT create_builtin_constructor(script_ctx_t*,builtin_invoke_t,const WCHAR*,const builtin_info_t*,DWORD,
jsdisp_t*,jsdisp_t**) DECLSPEC_HIDDEN;
+BOOL is_source_function(jsdisp_t*) DECLSPEC_HIDDEN;
HRESULT Function_invoke(jsdisp_t*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
HRESULT Function_value(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
--
2.21.0
More information about the wine-devel
mailing list