Module: wine Branch: master Commit: 856dc7eda432517d6e3c9b0c64e7e12ae4e38895 URL: http://source.winehq.org/git/wine.git/?a=commit;h=856dc7eda432517d6e3c9b0c64...
Author: Jacek Caban jacek@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@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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 };