From: Jacek Caban jacek@codeweavers.com
And use it for HTMLBodyElement prototype. --- dlls/mshtml/dispex.c | 32 +++++++++++++++++++++++++------ dlls/mshtml/htmlbody.c | 1 + dlls/mshtml/htmlelem.c | 13 +++++++------ dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/tests/documentmode.js | 1 + dlls/mshtml/tests/es5.js | 4 ++++ 6 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 1848fef01f2..ff3ed946284 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -501,10 +501,24 @@ static BOOL find_prototype_member(const dispex_data_t *info, DISPID id)
if(compat_mode < COMPAT_MODE_IE9) return FALSE; - if(!(info = info->desc->prototype_info[compat_mode - COMPAT_MODE_IE9])) - return FALSE; - if(bsearch(&id, info->funcs, info->func_cnt, sizeof(info->funcs[0]), dispid_cmp)) - return TRUE; + + if(!info->is_prototype) { + if(!info->desc->id) + return FALSE; + info = info->desc->prototype_info[compat_mode - COMPAT_MODE_IE9]; + }else { + if(!info->desc->prototype_id) + return FALSE; + info = object_descriptors[info->desc->prototype_id]->prototype_info[compat_mode - COMPAT_MODE_IE9]; + } + + for(;;) { + if(bsearch(&id, info->funcs, info->func_cnt, sizeof(info->funcs[0]), dispid_cmp)) + return TRUE; + if(!info->desc->prototype_id) + break; + info = object_descriptors[info->desc->prototype_id]->prototype_info[compat_mode - COMPAT_MODE_IE9]; + } return FALSE; }
@@ -2805,8 +2819,8 @@ static const dispex_static_data_vtbl_t prototype_dispex_vtbl = { static HRESULT get_prototype(HTMLInnerWindow *script_global, prototype_id_t id, DispatchEx **ret) { compat_mode_t compat_mode = dispex_compat_mode(&script_global->event_target.dispex); + DispatchEx *prototype, *prot_prototype = NULL; dispex_static_data_t *desc; - DispatchEx *prototype; dispex_data_t *info;
if(script_global->prototypes[id]) { @@ -2815,6 +2829,12 @@ static HRESULT get_prototype(HTMLInnerWindow *script_global, prototype_id_t id, }
desc = object_descriptors[id]; + if(desc->prototype_id) { + HRESULT hres = get_prototype(script_global, desc->prototype_id, &prot_prototype); + if(FAILED(hres)) + ERR("Failed to get a prototype: %08lx\n", hres); + } + info = desc->prototype_info[compat_mode - COMPAT_MODE_IE9]; if(!info) { EnterCriticalSection(&cs_dispex_static_data); @@ -2836,7 +2856,7 @@ static HRESULT get_prototype(HTMLInnerWindow *script_global, prototype_id_t id,
if(!(prototype = calloc(sizeof(*prototype), 1))) return E_OUTOFMEMORY; - init_dispatch_from_desc(prototype, info, script_global, NULL); + init_dispatch_from_desc(prototype, info, script_global, prot_prototype); *ret = script_global->prototypes[id] = prototype; return S_OK; } diff --git a/dlls/mshtml/htmlbody.c b/dlls/mshtml/htmlbody.c index 576c0d1fd0f..5e91ddd4fd5 100644 --- a/dlls/mshtml/htmlbody.c +++ b/dlls/mshtml/htmlbody.c @@ -896,6 +896,7 @@ static const tid_t HTMLBodyElement_iface_tids[] = { dispex_static_data_t HTMLBodyElement_dispex = { .name = "HTMLBodyElement", .id = PROT_HTMLBodyElement, + .prototype_id = PROT_HTMLElement, .vtbl = &HTMLBodyElement_event_target_vtbl.dispex_vtbl, .disp_tid = DispHTMLBody_tid, .iface_tids = HTMLBodyElement_iface_tids, diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index f6be9c8d35e..9a86c7f2f65 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -7235,12 +7235,13 @@ static const IWineHTMLElementPrivateVtbl WineHTMLElementPrivateVtbl = { htmlelement_private_get_classList, };
-static dispex_static_data_t HTMLElement_dispex = { - "HTMLElement", - &HTMLElement_event_target_vtbl.dispex_vtbl, - DispHTMLUnknownElement_tid, - HTMLElement_iface_tids, - HTMLElement_init_dispex_info +dispex_static_data_t HTMLElement_dispex = { + .name = "HTMLElement", + .id = PROT_HTMLElement, + .vtbl = &HTMLElement_event_target_vtbl.dispex_vtbl, + .disp_tid = DispHTMLUnknownElement_tid, + .iface_tids = HTMLElement_iface_tids, + .init_info = HTMLElement_init_dispex_info, };
static dispex_static_data_t HTMLUnknownElement_dispex = { diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index c2f8d508e5c..78387532fb5 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -409,6 +409,7 @@ typedef struct { #define ALL_PROTOTYPES \ X(DOMImplementation) \ X(HTMLBodyElement) \ + X(HTMLElement) \ X(Navigator)
typedef enum { @@ -429,6 +430,7 @@ typedef struct { dispex_data_t *prototype_info[COMPAT_MODE_CNT - COMPAT_MODE_IE9]; dispex_data_t *delayed_init_info; prototype_id_t id; + prototype_id_t prototype_id; UINT32 js_flags; char prototype_name[64]; } dispex_static_data_t; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index e8905374dcd..96e3aa878fa 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3123,4 +3123,5 @@ sync_test("prototypes", function() { check(window.navigator, Navigator.prototype, "navigator"); check(Navigator.prototype, Object.prototype, "navigator prototype"); check(document.body, HTMLBodyElement.prototype, "body element"); + check(HTMLBodyElement.prototype, HTMLElement.prototype, "body prototype"); }); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index 98d5ec37cb4..ec05974432c 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2753,8 +2753,12 @@ sync_test("prototypes", function() { ok(DOMImplementation === 1, "DOMImplementation = " + DOMImplementation + " expected 1"); DOMImplementation = constr;
+ ok(!HTMLBodyElement.prototype.hasOwnProperty("click"), "HTMLBodyElement prototype has own click property"); + ok(HTMLElement.prototype.hasOwnProperty("click"), "HTMLElement prototype does not have own click property"); + ok(document.implementation instanceof DOMImplementation, "document.implementation is not an instance of DOMImplementation"); ok(navigator instanceof Navigator, "navigator is not an instance of Navigator"); ok(!(navigator instanceof DOMImplementation), "navigator is an instance of DOMImplementation"); ok(document.body instanceof HTMLBodyElement, "body is not an instance of HTMLBodyElement"); + ok(document.body instanceof HTMLElement, "body is not an instance of HTMLElement"); });