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>
This commit is contained in:
Jacek Caban 2017-08-21 21:35:57 +02:00 committed by Alexandre Julliard
parent 53253aa6a4
commit 856dc7eda4
8 changed files with 90 additions and 11 deletions

View File

@ -62,7 +62,7 @@ typedef struct {
} func_info_t; } func_info_t;
struct dispex_data_t { struct dispex_data_t {
const dispex_static_data_t *desc; dispex_static_data_t *desc;
DWORD func_cnt; DWORD func_cnt;
DWORD func_size; 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); 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; const tid_t *tid;
dispex_data_t *data; 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) static inline DispatchEx *impl_from_IDispatchEx(IDispatchEx *iface)
{ {
return CONTAINING_RECORD(iface, DispatchEx, 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)) if(grfdex & ~(fdexNameCaseSensitive|fdexNameCaseInsensitive|fdexNameEnsure|fdexNameImplicit|FDEX_VERSION_MASK))
FIXME("Unsupported grfdex %x\n", grfdex); FIXME("Unsupported grfdex %x\n", grfdex);
if(!ensure_real_info(This))
return E_OUTOFMEMORY;
hres = get_builtin_id(This, bstrName, grfdex, pid); hres = get_builtin_id(This, bstrName, grfdex, pid);
if(hres != DISP_E_UNKNOWNNAME) if(hres != DISP_E_UNKNOWNNAME)
return hres; 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); 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)) if(wFlags == (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF))
wFlags = DISPATCH_PROPERTYPUT; 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); TRACE("(%p)->(%x %p)\n", This, id, pbstrName);
if(!ensure_real_info(This))
return E_OUTOFMEMORY;
if(is_dynamic_dispid(id)) { if(is_dynamic_dispid(id)) {
DWORD idx = id - DISPID_DYNPROP_0; 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); TRACE("(%p)->(%x %x %p)\n", This, grfdex, id, pid);
if(!ensure_real_info(This))
return E_OUTOFMEMORY;
if(is_dynamic_dispid(id)) { if(is_dynamic_dispid(id)) {
DWORD idx = id - DISPID_DYNPROP_0; 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); 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->IDispatchEx_iface.lpVtbl = &DispatchExVtbl;
dispex->outer = outer; dispex->outer = outer;
dispex->info = data->info_cache[compat_mode];
dispex->dynamic_data = NULL; 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);
}
} }

View File

@ -4813,6 +4813,16 @@ static HRESULT HTMLDocumentNode_invoke(DispatchEx *dispex, DISPID id, LCID lcid,
return S_OK; 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) static void HTMLDocumentNode_bind_event(DispatchEx *dispex, int eid)
{ {
HTMLDocumentNode *This = impl_from_DispatchEx(dispex); HTMLDocumentNode *This = impl_from_DispatchEx(dispex);
@ -4823,6 +4833,7 @@ static const dispex_static_data_vtbl_t HTMLDocumentNode_dispex_vtbl = {
NULL, NULL,
NULL, NULL,
HTMLDocumentNode_invoke, HTMLDocumentNode_invoke,
HTMLDocumentNode_get_compat_mode,
NULL, NULL,
NULL, NULL,
HTMLDocumentNode_bind_event HTMLDocumentNode_bind_event
@ -4851,7 +4862,8 @@ static const tid_t HTMLDocumentNode_iface_tids[] = {
static dispex_static_data_t HTMLDocumentNode_dispex = { static dispex_static_data_t HTMLDocumentNode_dispex = {
&HTMLDocumentNode_dispex_vtbl, &HTMLDocumentNode_dispex_vtbl,
DispHTMLDocument_tid, DispHTMLDocument_tid,
HTMLDocumentNode_iface_tids HTMLDocumentNode_iface_tids,
HTMLDOMNode_init_dispex_info
}; };
static HTMLDocumentNode *alloc_doc_node(HTMLDocumentObj *doc_obj, HTMLInnerWindow *window) static HTMLDocumentNode *alloc_doc_node(HTMLDocumentObj *doc_obj, HTMLInnerWindow *window)

View File

@ -5319,6 +5319,7 @@ static dispex_static_data_vtbl_t HTMLElement_dispex_vtbl = {
NULL, NULL,
HTMLElement_get_dispid, HTMLElement_get_dispid,
HTMLElement_invoke, HTMLElement_invoke,
NULL,
HTMLElement_populate_props, HTMLElement_populate_props,
HTMLElement_get_event_target, HTMLElement_get_event_target,
HTMLElement_bind_event HTMLElement_bind_event

View File

@ -3019,6 +3019,7 @@ static const dispex_static_data_vtbl_t HTMLWindow_dispex_vtbl = {
NULL, NULL,
HTMLWindow_invoke, HTMLWindow_invoke,
NULL, NULL,
NULL,
HTMLWindow_get_event_target, HTMLWindow_get_event_target,
HTMLWindow_bind_event HTMLWindow_bind_event
}; };

View File

@ -267,6 +267,7 @@ typedef struct {
HRESULT (*value)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); HRESULT (*value)(DispatchEx*,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
HRESULT (*get_dispid)(DispatchEx*,BSTR,DWORD,DISPID*); HRESULT (*get_dispid)(DispatchEx*,BSTR,DWORD,DISPID*);
HRESULT (*invoke)(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*); HRESULT (*invoke)(DispatchEx*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,IServiceProvider*);
compat_mode_t (*get_compat_mode)(DispatchEx*);
HRESULT (*populate_props)(DispatchEx*); HRESULT (*populate_props)(DispatchEx*);
/* We abuse this vtbl for EventTarget functions to avoid separated vtbl. */ /* We abuse this vtbl for EventTarget functions to avoid separated vtbl. */
EventTarget *(*get_event_target)(DispatchEx*); EventTarget *(*get_event_target)(DispatchEx*);
@ -279,6 +280,7 @@ typedef struct {
const tid_t* const iface_tids; const tid_t* const iface_tids;
void (*init_info)(dispex_data_t*,compat_mode_t); void (*init_info)(dispex_data_t*,compat_mode_t);
dispex_data_t *info_cache[COMPAT_MODE_CNT]; dispex_data_t *info_cache[COMPAT_MODE_CNT];
dispex_data_t *delayed_init_info;
} dispex_static_data_t; } dispex_static_data_t;
struct DispatchEx { struct DispatchEx {

View File

@ -39,6 +39,22 @@ function test_elem_props() {
next_test(); 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() { function test_doc_mode() {
compat_version = parseInt(document.location.search.substring(1)); compat_version = parseInt(document.location.search.substring(1));
@ -99,5 +115,6 @@ function test_conditional_comments() {
var tests = [ var tests = [
test_doc_mode, test_doc_mode,
test_elem_props, test_elem_props,
test_doc_props,
test_conditional_comments test_conditional_comments
]; ];

View File

@ -77,6 +77,8 @@ function test_textContent() {
ok(div.textContent === "", "div.textContent = " + div.textContent); ok(div.textContent === "", "div.textContent = " + div.textContent);
ok(div.childNodes.length === 0, "div.childNodes.length = " + div.childNodes.length); ok(div.childNodes.length === 0, "div.childNodes.length = " + div.childNodes.length);
ok(document.textContent === null, "document.textContent = " + document.textContent);
next_test(); next_test();
} }

View File

@ -778,6 +778,7 @@ static dispex_static_data_vtbl_t HTMLXMLHttpRequest_dispex_vtbl = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
HTMLXMLHttpRequest_bind_event HTMLXMLHttpRequest_bind_event
}; };