From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 6 ++-- dlls/mshtml/htmlimg.c | 17 +++++----- dlls/mshtml/htmlwindow.c | 56 +++++++++++++++---------------- dlls/mshtml/mshtml_private.h | 18 +++++++--- dlls/mshtml/tests/documentmode.js | 12 ++++++- 5 files changed, 65 insertions(+), 44 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 95cddfd9c17..3015e3e3b0f 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2978,6 +2978,7 @@ dispex_static_data_t *object_descriptors[] = { NULL, #define X(name) &name ## _dispex, ALL_PROTOTYPES + ALL_ALT_CTORS #undef X };
@@ -3124,8 +3125,6 @@ HRESULT get_constructor(HTMLInnerWindow *script_global, prototype_id_t id, Dispa { dispex_static_data_t *info;
- assert(script_global->doc->document_mode >= COMPAT_MODE_IE9); - if(script_global->constructors[id]) { *ret = script_global->constructors[id]; return S_OK; @@ -3138,6 +3137,9 @@ HRESULT get_constructor(HTMLInnerWindow *script_global, prototype_id_t id, Dispa return hres; }else { struct constructor *constr; + + assert(script_global->doc->document_mode >= COMPAT_MODE_IE9); + if(!(constr = calloc(sizeof(*constr), 1))) return E_OUTOFMEMORY;
diff --git a/dlls/mshtml/htmlimg.c b/dlls/mshtml/htmlimg.c index 5716bbd7ac4..55eac4252b9 100644 --- a/dlls/mshtml/htmlimg.c +++ b/dlls/mshtml/htmlimg.c @@ -878,15 +878,16 @@ static const dispex_static_data_vtbl_t HTMLImageElementFactory_dispex_vtbl = { .value = HTMLImageElementFactory_value, };
-static dispex_static_data_t HTMLImageElementFactory_dispex = { - .name = "Function", - .constructor_id = PROT_HTMLImageElement, - .vtbl = &HTMLImageElementFactory_dispex_vtbl, - .disp_tid = IHTMLImageElementFactory_tid, - .init_info = HTMLImageElementFactory_init_dispex_info, +dispex_static_data_t HTMLImageElementFactory_dispex = { + .name = "Function", + .constructor_id = PROT_HTMLImageElement, + .init_constructor = HTMLImageElementFactory_Create, + .vtbl = &HTMLImageElementFactory_dispex_vtbl, + .disp_tid = IHTMLImageElementFactory_tid, + .init_info = HTMLImageElementFactory_init_dispex_info, };
-HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow *window, HTMLImageElementFactory **ret_val) +HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow *window, DispatchEx **ret_val) { HTMLImageElementFactory *ret;
@@ -901,6 +902,6 @@ HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow *window, HTMLImageElement init_dispatch(&ret->dispex, &HTMLImageElementFactory_dispex, window, dispex_compat_mode(&window->event_target.dispex));
- *ret_val = ret; + *ret_val = &ret->dispex; return S_OK; } diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index c7e45439545..562e6b279a3 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -673,21 +673,16 @@ static HRESULT WINAPI HTMLWindow2_get_Image(IHTMLWindow2 *iface, IHTMLImageEleme { HTMLWindow *This = impl_from_IHTMLWindow2(iface); HTMLInnerWindow *window = This->inner_window; + DispatchEx *constr; + HRESULT hres;
TRACE("(%p)->(%p)\n", This, p);
- if(!window->image_factory) { - HRESULT hres; - - hres = HTMLImageElementFactory_Create(window, &window->image_factory); - if(FAILED(hres)) - return hres; - } - - *p = &window->image_factory->IHTMLImageElementFactory_iface; - IHTMLImageElementFactory_AddRef(*p); + hres = get_constructor(window, CTOR_HTMLImageElementFactory, &constr); + if(FAILED(hres)) + return hres;
- return S_OK; + return IWineJSDispatchHost_QueryInterface(&constr->IWineJSDispatchHost_iface, &IID_IHTMLImageElementFactory, (void**)p); }
static HRESULT WINAPI HTMLWindow2_get_location(IHTMLWindow2 *iface, IHTMLLocation **p) @@ -3700,8 +3695,6 @@ static void HTMLWindow_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCa note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "doc", cb); if(This->console) note_cc_edge((nsISupports*)This->console, "console", cb); - if(This->image_factory) - note_cc_edge((nsISupports*)&This->image_factory->IHTMLImageElementFactory_iface, "image_factory", cb); if(This->option_factory) note_cc_edge((nsISupports*)&This->option_factory->IHTMLOptionElementFactory_iface, "option_factory", cb); if(This->screen) @@ -3742,11 +3735,6 @@ static void HTMLWindow_unlink(DispatchEx *dispex)
release_event_target(&This->event_target);
- if(This->image_factory) { - HTMLImageElementFactory *image_factory = This->image_factory; - This->image_factory = NULL; - IHTMLImageElementFactory_Release(&image_factory->IHTMLImageElementFactory_iface); - } if(This->option_factory) { HTMLOptionElementFactory *option_factory = This->option_factory; This->option_factory = NULL; @@ -3818,18 +3806,24 @@ static int CDECL cmp_name(const void *x, const void *y)
static HRESULT HTMLWindow_find_dispid(DispatchEx *dispex, const WCHAR *name, DWORD grfdex, DISPID *dispid) { + compat_mode_t compat_mode = dispex_compat_mode(dispex); HTMLInnerWindow *This = impl_from_DispatchEx(dispex); HTMLOuterWindow *frame; global_prop_t *prop; HTMLElement *elem; HRESULT hres;
- if(dispex_compat_mode(dispex) >= COMPAT_MODE_IE9) { + if(compat_mode >= COMPAT_MODE_IE9) { const WCHAR **constr_name = bsearch(&name, constructor_names, ARRAYSIZE(constructor_names) , sizeof(constructor_names[0]), cmp_name); - if(constr_name) { - prototype_id_t id = constr_name - constructor_names + 1; - compat_mode_t compat_mode = dispex_compat_mode(dispex); + prototype_id_t id = 0; + + if(constr_name) + id = constr_name - constructor_names + 1; + else if(!wcscmp(name, L"Image")) + id = CTOR_HTMLImageElementFactory; + + if(id) { DispatchEx *constr; VARIANT v;
@@ -4188,15 +4182,18 @@ static HRESULT IHTMLWindow6_postMessage_hook(DispatchEx *dispex, WORD flags, DIS
static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode) { - static const dispex_hook_t window2_hooks[] = { - {DISPID_IHTMLWINDOW2_LOCATION, IHTMLWindow2_location_hook}, - {DISPID_UNKNOWN} - }; static const dispex_hook_t window2_ie11_hooks[] = { - {DISPID_IHTMLWINDOW2_LOCATION, IHTMLWindow2_location_hook}, - {DISPID_IHTMLWINDOW2_EXECSCRIPT, NULL}, + {DISPID_IHTMLWINDOW2_EXECSCRIPT}, + + /* IE9+ */ + {DISPID_IHTMLWINDOW2_IMAGE}, + + /* Common for all modes */ + {DISPID_IHTMLWINDOW2_LOCATION, IHTMLWindow2_location_hook}, {DISPID_UNKNOWN} }; + const dispex_hook_t *const window2_ie9_hooks = window2_ie11_hooks + 1; + const dispex_hook_t *const window2_hooks = window2_ie9_hooks + 1; static const dispex_hook_t window3_hooks[] = { {DISPID_IHTMLWINDOW3_SETTIMEOUT, IHTMLWindow3_setTimeout_hook}, {DISPID_UNKNOWN} @@ -4228,7 +4225,8 @@ static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compa dispex_info_add_interface(info, IHTMLWindow5_tid, NULL); dispex_info_add_interface(info, IHTMLWindow4_tid, compat_mode >= COMPAT_MODE_IE11 ? window4_ie11_hooks : NULL); dispex_info_add_interface(info, IHTMLWindow3_tid, compat_mode >= COMPAT_MODE_IE11 ? window3_ie11_hooks : window3_hooks); - dispex_info_add_interface(info, IHTMLWindow2_tid, compat_mode >= COMPAT_MODE_IE11 ? window2_ie11_hooks : window2_hooks); + dispex_info_add_interface(info, IHTMLWindow2_tid, compat_mode >= COMPAT_MODE_IE11 ? window2_ie11_hooks : + compat_mode >= COMPAT_MODE_IE9 ? window2_ie9_hooks : window2_hooks); EventTarget_init_dispex_info(info, compat_mode); }
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index f306cff68c6..58dad8a68e0 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -504,12 +504,22 @@ typedef struct { X(Window) \ X(XMLHttpRequest)
+/* Extra constructors without new prototypes */ +#define ALL_ALT_CTORS \ + X(HTMLImageElementFactory) + typedef enum { PROT_NONE, #define X(name) PROT_##name, ALL_PROTOTYPES #undef X PROT_LAST, + + PROT_LAST_ = PROT_LAST - 1, /* align alt ctors enum */ +#define X(name) CTOR_##name, + ALL_ALT_CTORS +#undef X + CTOR_LAST } prototype_id_t;
struct dispex_static_data_t { @@ -533,9 +543,10 @@ struct dispex_static_data_t {
#define X(name) extern dispex_static_data_t name ## _dispex; ALL_PROTOTYPES +ALL_ALT_CTORS #undef X
-extern dispex_static_data_t *object_descriptors[PROT_LAST]; +extern dispex_static_data_t *object_descriptors[CTOR_LAST];
typedef HRESULT (*dispex_hook_invoke_t)(DispatchEx*,WORD,DISPPARAMS*,VARIANT*, EXCEPINFO*,IServiceProvider*); @@ -771,7 +782,6 @@ struct HTMLInnerWindow {
IHTMLEventObj *event;
- HTMLImageElementFactory *image_factory; HTMLOptionElementFactory *option_factory; IHTMLScreen *screen; OmHistory *history; @@ -801,7 +811,7 @@ struct HTMLInnerWindow { ULONG redirect_count;
DispatchEx *prototypes[PROT_LAST]; - DispatchEx *constructors[PROT_LAST]; + DispatchEx *constructors[CTOR_LAST];
ULONGLONG navigation_start_time; ULONGLONG unload_event_start_time; @@ -1170,7 +1180,7 @@ HRESULT update_window_doc(HTMLInnerWindow*); HTMLOuterWindow *mozwindow_to_window(const mozIDOMWindowProxy*); void get_top_window(HTMLOuterWindow*,HTMLOuterWindow**); HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,HTMLOptionElementFactory**); -HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,HTMLImageElementFactory**); +HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,DispatchEx**); HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,DispatchEx**); HRESULT create_location(HTMLOuterWindow*,HTMLLocation**); HRESULT create_navigator(HTMLInnerWindow*,IOmNavigator**); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 332c4c6192c..a5ba8bed94d 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -4012,10 +4012,20 @@ sync_test("prototype props", function() { });
sync_test("constructors", function() { - var v = document.documentMode; + var v = document.documentMode, i, r; if(v < 9) return;
+ var ctors = [ "Image", "MutationObserver", "XMLHttpRequest" ]; + for(i = 0; i < ctors.length; i++) { + r = ctors[i]; + if(!(r in window)) + continue; + ok(window.hasOwnProperty(r), r + " not prop of window"); + ok(!Object.getPrototypeOf(window).hasOwnProperty(r), r + " is a prop of window's prototype"); + } + ok(window.Image.prototype === window.HTMLImageElement.prototype, "Image.prototype != HTMLImageElement.prototype"); + ok(XMLHttpRequest.create() instanceof XMLHttpRequest, "XMLHttpRequest.create did not return XMLHttpRequest instance"); ok(XMLHttpRequest.create.call(Object) instanceof XMLHttpRequest, "XMLHttpRequest.create with Object 'this' did not return XMLHttpRequest instance"); try {