[PATCH v3 03/11] jscript: Store the necessary function and variable info in the TypeInfo.

Gabriel Ivăncescu gabrielopcode at gmail.com
Wed Dec 11 08:08:24 CST 2019


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/jscript/dispex.c | 110 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 110 insertions(+)

diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 92e9b96..a6e8a1f 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(impl_from_IDispatchEx((IDispatchEx*)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(impl_from_IDispatchEx((IDispatchEx*)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;
-- 
2.21.0




More information about the wine-devel mailing list