Jacek Caban : mshtml: Added delayed DispatchEx init support and use it to expose IHTMLDOMNode3 from document node.

Alexandre Julliard julliard at winehq.org
Wed Aug 23 19:54:07 CDT 2017


Module: wine
Branch: master
Commit: 856dc7eda432517d6e3c9b0c64e7e12ae4e38895
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=856dc7eda432517d6e3c9b0c64e7e12ae4e38895

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Aug 21 21:35:57 2017 +0200

mshtml: Added delayed DispatchEx init support and use it to expose IHTMLDOMNode3 from document node.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mshtml/dispex.c              | 63 ++++++++++++++++++++++++++++++++-------
 dlls/mshtml/htmldoc.c             | 14 ++++++++-
 dlls/mshtml/htmlelem.c            |  1 +
 dlls/mshtml/htmlwindow.c          |  1 +
 dlls/mshtml/mshtml_private.h      |  2 ++
 dlls/mshtml/tests/documentmode.js | 17 +++++++++++
 dlls/mshtml/tests/elements.js     |  2 ++
 dlls/mshtml/xmlhttprequest.c      |  1 +
 8 files changed, 90 insertions(+), 11 deletions(-)

diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c
index baf251a..95c17b8 100644
--- a/dlls/mshtml/dispex.c
+++ b/dlls/mshtml/dispex.c
@@ -62,7 +62,7 @@ typedef struct {
 } func_info_t;
 
 struct dispex_data_t {
-    const dispex_static_data_t *desc;
+    dispex_static_data_t *desc;
 
     DWORD func_cnt;
     DWORD func_size;
@@ -379,7 +379,7 @@ static int func_name_cmp(const void *p1, const void *p2)
     return strcmpiW((*(func_info_t* const*)p1)->name, (*(func_info_t* const*)p2)->name);
 }
 
-static dispex_data_t *preprocess_dispex_data(const dispex_static_data_t *desc, compat_mode_t compat_mode)
+static dispex_data_t *preprocess_dispex_data(dispex_static_data_t *desc, compat_mode_t compat_mode)
 {
     const tid_t *tid;
     dispex_data_t *data;
@@ -1346,6 +1346,27 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
     }
 }
 
+static dispex_data_t *ensure_dispex_info(dispex_static_data_t *desc, compat_mode_t compat_mode)
+{
+    if(!desc->info_cache[compat_mode]) {
+        EnterCriticalSection(&cs_dispex_static_data);
+        if(!desc->info_cache[compat_mode])
+            desc->info_cache[compat_mode] = preprocess_dispex_data(desc, compat_mode);
+        LeaveCriticalSection(&cs_dispex_static_data);
+    }
+    return desc->info_cache[compat_mode];
+}
+
+static BOOL ensure_real_info(DispatchEx *dispex)
+{
+    if(dispex->info != dispex->info->desc->delayed_init_info)
+        return TRUE;
+
+    dispex->info = ensure_dispex_info(dispex->info->desc,
+                                      dispex->info->desc->vtbl->get_compat_mode(dispex));
+    return dispex->info != NULL;
+}
+
 static inline DispatchEx *impl_from_IDispatchEx(IDispatchEx *iface)
 {
     return CONTAINING_RECORD(iface, DispatchEx, IDispatchEx_iface);
@@ -1442,6 +1463,9 @@ static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
     if(grfdex & ~(fdexNameCaseSensitive|fdexNameCaseInsensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK))
         FIXME("Unsupported grfdex %x\n", grfdex);
 
+    if(!ensure_real_info(This))
+        return E_OUTOFMEMORY;
+
     hres = get_builtin_id(This, bstrName, grfdex, pid);
     if(hres != DISP_E_UNKNOWNNAME)
         return hres;
@@ -1462,6 +1486,9 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
 
     TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
 
+    if(!ensure_real_info(This))
+        return E_OUTOFMEMORY;
+
     if(wFlags == (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF))
         wFlags = DISPATCH_PROPERTYPUT;
 
@@ -1572,6 +1599,9 @@ static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BS
 
     TRACE("(%p)->(%x %p)\n", This, id, pbstrName);
 
+    if(!ensure_real_info(This))
+        return E_OUTOFMEMORY;
+
     if(is_dynamic_dispid(id)) {
         DWORD idx = id - DISPID_DYNPROP_0;
 
@@ -1617,6 +1647,9 @@ static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex,
 
     TRACE("(%p)->(%x %x %p)\n", This, grfdex, id, pid);
 
+    if(!ensure_real_info(This))
+        return E_OUTOFMEMORY;
+
     if(is_dynamic_dispid(id)) {
         DWORD idx = id - DISPID_DYNPROP_0;
 
@@ -1770,15 +1803,25 @@ void init_dispex_with_compat_mode(DispatchEx *dispex, IUnknown *outer, dispex_st
 {
     assert(compat_mode < COMPAT_MODE_CNT);
 
-    if(!data->info_cache[compat_mode]) {
-        EnterCriticalSection(&cs_dispex_static_data);
-        if(!data->info_cache[compat_mode])
-            data->info_cache[compat_mode] = preprocess_dispex_data(data, compat_mode);
-        LeaveCriticalSection(&cs_dispex_static_data);
-    }
-
     dispex->IDispatchEx_iface.lpVtbl = &DispatchExVtbl;
     dispex->outer = outer;
-    dispex->info = data->info_cache[compat_mode];
     dispex->dynamic_data = NULL;
+
+    if(data->vtbl && data->vtbl->get_compat_mode) {
+        /* delayed init */
+        if(!data->delayed_init_info) {
+            EnterCriticalSection(&cs_dispex_static_data);
+            if(!data->delayed_init_info) {
+                dispex_data_t *info = heap_alloc_zero(sizeof(*data->delayed_init_info));
+                if(info) {
+                    info->desc = data;
+                    data->delayed_init_info = info;
+                }
+            }
+            LeaveCriticalSection(&cs_dispex_static_data);
+        }
+        dispex->info = data->delayed_init_info;
+    }else {
+        dispex->info = ensure_dispex_info(data, compat_mode);
+    }
 }
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c
index 3c16d2c..a8d104e 100644
--- a/dlls/mshtml/htmldoc.c
+++ b/dlls/mshtml/htmldoc.c
@@ -4813,6 +4813,16 @@ static HRESULT HTMLDocumentNode_invoke(DispatchEx *dispex, DISPID id, LCID lcid,
     return S_OK;
 }
 
+static compat_mode_t HTMLDocumentNode_get_compat_mode(DispatchEx *dispex)
+{
+    HTMLDocumentNode *This = impl_from_DispatchEx(dispex);
+
+    TRACE("(%p) returning %u\n", This, This->document_mode);
+
+    This->document_mode_locked = TRUE;
+    return This->document_mode;
+}
+
 static void HTMLDocumentNode_bind_event(DispatchEx *dispex, int eid)
 {
     HTMLDocumentNode *This = impl_from_DispatchEx(dispex);
@@ -4823,6 +4833,7 @@ static const dispex_static_data_vtbl_t HTMLDocumentNode_dispex_vtbl = {
     NULL,
     NULL,
     HTMLDocumentNode_invoke,
+    HTMLDocumentNode_get_compat_mode,
     NULL,
     NULL,
     HTMLDocumentNode_bind_event
@@ -4851,7 +4862,8 @@ static const tid_t HTMLDocumentNode_iface_tids[] = {
 static dispex_static_data_t HTMLDocumentNode_dispex = {
     &HTMLDocumentNode_dispex_vtbl,
     DispHTMLDocument_tid,
-    HTMLDocumentNode_iface_tids
+    HTMLDocumentNode_iface_tids,
+    HTMLDOMNode_init_dispex_info
 };
 
 static HTMLDocumentNode *alloc_doc_node(HTMLDocumentObj *doc_obj, HTMLInnerWindow *window)
diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index 927541b..247948c 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -5319,6 +5319,7 @@ static dispex_static_data_vtbl_t HTMLElement_dispex_vtbl = {
     NULL,
     HTMLElement_get_dispid,
     HTMLElement_invoke,
+    NULL,
     HTMLElement_populate_props,
     HTMLElement_get_event_target,
     HTMLElement_bind_event
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index 5853220..dc18f84 100644
--- a/dlls/mshtml/htmlwindow.c
+++ b/dlls/mshtml/htmlwindow.c
@@ -3019,6 +3019,7 @@ static const dispex_static_data_vtbl_t HTMLWindow_dispex_vtbl = {
     NULL,
     HTMLWindow_invoke,
     NULL,
+    NULL,
     HTMLWindow_get_event_target,
     HTMLWindow_bind_event
 };
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index 2ee34c1..f10a793 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -267,6 +267,7 @@ typedef struct {
     HRESULT (*value)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
     HRESULT (*get_dispid)(DispatchEx*,BSTR,DWORD,DISPID*);
     HRESULT (*invoke)(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
+    compat_mode_t (*get_compat_mode)(DispatchEx*);
     HRESULT (*populate_props)(DispatchEx*);
     /* We abuse this vtbl for EventTarget functions to avoid separated vtbl. */
     EventTarget *(*get_event_target)(DispatchEx*);
@@ -279,6 +280,7 @@ typedef struct {
     const tid_t* const iface_tids;
     void (*init_info)(dispex_data_t*,compat_mode_t);
     dispex_data_t *info_cache[COMPAT_MODE_CNT];
+    dispex_data_t *delayed_init_info;
 } dispex_static_data_t;
 
 struct DispatchEx {
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index 69ec6a3..4224dfe 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -39,6 +39,22 @@ function test_elem_props() {
     next_test();
 }
 
+function test_doc_props() {
+    function test_exposed(prop, expect) {
+        if(expect)
+            ok(prop in document, prop + " not found in document.");
+        else
+            ok(!(prop in document), prop + " found in document.");
+    }
+
+    var v = document.documentMode;
+
+    test_exposed("textContent", v >= 9);
+    test_exposed("prefix", v >= 9);
+
+    next_test();
+}
+
 function test_doc_mode() {
     compat_version = parseInt(document.location.search.substring(1));
 
@@ -99,5 +115,6 @@ function test_conditional_comments() {
 var tests = [
     test_doc_mode,
     test_elem_props,
+    test_doc_props,
     test_conditional_comments
 ];
diff --git a/dlls/mshtml/tests/elements.js b/dlls/mshtml/tests/elements.js
index b7db0bc..ac1e2d0 100644
--- a/dlls/mshtml/tests/elements.js
+++ b/dlls/mshtml/tests/elements.js
@@ -77,6 +77,8 @@ function test_textContent() {
     ok(div.textContent === "", "div.textContent = " + div.textContent);
     ok(div.childNodes.length === 0, "div.childNodes.length = " + div.childNodes.length);
 
+    ok(document.textContent === null, "document.textContent = " + document.textContent);
+
     next_test();
 }
 
diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c
index 1565f9b..35e91fc 100644
--- a/dlls/mshtml/xmlhttprequest.c
+++ b/dlls/mshtml/xmlhttprequest.c
@@ -778,6 +778,7 @@ static dispex_static_data_vtbl_t HTMLXMLHttpRequest_dispex_vtbl = {
     NULL,
     NULL,
     NULL,
+    NULL,
     HTMLXMLHttpRequest_bind_event
 };
 




More information about the wine-cvs mailing list