-- v5: mshtml: Validate builtin host functions in IE9+ using prototype_id rather mshtml: Store the prototype_id of the last member that contains the needed mshtml: Define "create" from XMLHttpRequest constructor as a jscript prop mshtml: Consolidate the functional constructors into a common struct mshtml: Rename struct constructor to stub_constructor. mshtml: Use get_constructor in window's get_XMLHttpRequest. mshtml: Move Option constructor to the window rather than the prototype. mshtml: Move Image constructor to the window rather than the prototype. mshtml: Don't expose "create" from Option constructor in IE9+ modes. mshtml: Don't expose "create" from Image constructor in IE9+ modes.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlimg.c | 11 ++++++----- dlls/mshtml/tests/documentmode.js | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/dlls/mshtml/htmlimg.c b/dlls/mshtml/htmlimg.c index f6a4b992ab6..5716bbd7ac4 100644 --- a/dlls/mshtml/htmlimg.c +++ b/dlls/mshtml/htmlimg.c @@ -864,10 +864,11 @@ static HRESULT HTMLImageElementFactory_value(DispatchEx *dispex, LCID lcid, return S_OK; }
-static const tid_t HTMLImageElementFactory_iface_tids[] = { - IHTMLImageElementFactory_tid, - 0 -}; +static void HTMLImageElementFactory_init_dispex_info(dispex_data_t *info, compat_mode_t mode) +{ + if(mode < COMPAT_MODE_IE9) + dispex_info_add_interface(info, IHTMLImageElementFactory_tid, NULL); +}
static const dispex_static_data_vtbl_t HTMLImageElementFactory_dispex_vtbl = { .query_interface = HTMLImageElementFactory_query_interface, @@ -882,7 +883,7 @@ static dispex_static_data_t HTMLImageElementFactory_dispex = { .constructor_id = PROT_HTMLImageElement, .vtbl = &HTMLImageElementFactory_dispex_vtbl, .disp_tid = IHTMLImageElementFactory_tid, - .iface_tids = HTMLImageElementFactory_iface_tids, + .init_info = HTMLImageElementFactory_init_dispex_info, };
HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow *window, HTMLImageElementFactory **ret_val) diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 5bbd8b098f6..cb1bafe034c 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -906,6 +906,20 @@ sync_test("style_props", function() { } });
+sync_test("constructor props", function() { + function test_exposed(constructor, prop, expect) { + if(expect) + ok(prop in window[constructor], prop + " not found in " + constructor + " constructor."); + else + ok(!(prop in window[constructor]), prop + " found in " + constructor + " constructor."); + } + var v = document.documentMode; + + test_exposed("Image", "create", v < 9); + test_exposed("XMLHttpRequest", "create", true); + if(v >= 11) test_exposed("MutationObserver", "create", false); +}); + sync_test("createElement_inline_attr", function() { var v = document.documentMode, e, s;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlselect.c | 11 ++++++----- dlls/mshtml/tests/documentmode.js | 1 + 2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/dlls/mshtml/htmlselect.c b/dlls/mshtml/htmlselect.c index 2d02589db38..3bae8fe958b 100644 --- a/dlls/mshtml/htmlselect.c +++ b/dlls/mshtml/htmlselect.c @@ -510,10 +510,11 @@ static HRESULT HTMLOptionElementFactory_value(DispatchEx *dispex, LCID lcid, return S_OK; }
-static const tid_t HTMLOptionElementFactory_iface_tids[] = { - IHTMLOptionElementFactory_tid, - 0 -}; +static void HTMLImageElementFactory_init_dispex_info(dispex_data_t *info, compat_mode_t mode) +{ + if(mode < COMPAT_MODE_IE9) + dispex_info_add_interface(info, IHTMLOptionElementFactory_tid, NULL); +}
static const dispex_static_data_vtbl_t HTMLOptionElementFactory_dispex_vtbl = { .query_interface = HTMLOptionElementFactory_query_interface, @@ -528,7 +529,7 @@ static dispex_static_data_t HTMLOptionElementFactory_dispex = { .constructor_id = PROT_HTMLOptionElement, .vtbl = &HTMLOptionElementFactory_dispex_vtbl, .disp_tid = IHTMLOptionElementFactory_tid, - .iface_tids = HTMLOptionElementFactory_iface_tids, + .init_info = HTMLImageElementFactory_init_dispex_info, };
HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, HTMLOptionElementFactory **ret_ptr) diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index cb1bafe034c..bb53a1a010f 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -916,6 +916,7 @@ sync_test("constructor props", function() { var v = document.documentMode;
test_exposed("Image", "create", v < 9); + test_exposed("Option", "create", v < 9); test_exposed("XMLHttpRequest", "create", true); if(v >= 11) test_exposed("MutationObserver", "create", false); });
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 | 19 ++++++----- dlls/mshtml/htmlwindow.c | 56 +++++++++++++++---------------- dlls/mshtml/mshtml_private.h | 17 +++++++--- dlls/mshtml/tests/documentmode.js | 16 +++++++++ 5 files changed, 71 insertions(+), 43 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 77eec049912..b6e898f8c26 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -2970,6 +2970,7 @@ dispex_static_data_t *object_descriptors[] = { NULL, #define X(name) &name ## _dispex, ALL_PROTOTYPES + ALL_ALT_CTORS #undef X };
@@ -3116,8 +3117,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; @@ -3130,6 +3129,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..518aae46213 100644 --- a/dlls/mshtml/htmlimg.c +++ b/dlls/mshtml/htmlimg.c @@ -878,15 +878,18 @@ 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, +static HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,DispatchEx**); + +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) +static HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow *window, DispatchEx **ret_val) { HTMLImageElementFactory *ret;
@@ -901,6 +904,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 ffcaf86a361..30cdcce4020 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..c0320af733a 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,6 @@ 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 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 bb53a1a010f..4119453687b 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3996,3 +3996,19 @@ sync_test("prototype props", function() { check(Text, [ "removeNode", "replaceNode", "replaceWholeText", "splitText", "swapNode", "wholeText" ], [ "replaceWholeText", "wholeText" ]); check(UIEvent, [ "detail", "initUIEvent", "view" ], null, [ "deviceSessionId" ]); }); + +sync_test("constructors", function() { + 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"); +});
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlselect.c | 19 +++++++++++-------- dlls/mshtml/htmlwindow.c | 29 ++++++++++------------------- dlls/mshtml/mshtml_private.h | 5 ++--- dlls/mshtml/tests/documentmode.js | 3 ++- 4 files changed, 25 insertions(+), 31 deletions(-)
diff --git a/dlls/mshtml/htmlselect.c b/dlls/mshtml/htmlselect.c index 3bae8fe958b..bc45718349c 100644 --- a/dlls/mshtml/htmlselect.c +++ b/dlls/mshtml/htmlselect.c @@ -524,15 +524,18 @@ static const dispex_static_data_vtbl_t HTMLOptionElementFactory_dispex_vtbl = { .value = HTMLOptionElementFactory_value, };
-static dispex_static_data_t HTMLOptionElementFactory_dispex = { - .name = "Function", - .constructor_id = PROT_HTMLOptionElement, - .vtbl = &HTMLOptionElementFactory_dispex_vtbl, - .disp_tid = IHTMLOptionElementFactory_tid, - .init_info = HTMLImageElementFactory_init_dispex_info, +static HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,DispatchEx**); + +dispex_static_data_t HTMLOptionElementFactory_dispex = { + .name = "Function", + .constructor_id = PROT_HTMLOptionElement, + .init_constructor = HTMLOptionElementFactory_Create, + .vtbl = &HTMLOptionElementFactory_dispex_vtbl, + .disp_tid = IHTMLOptionElementFactory_tid, + .init_info = HTMLImageElementFactory_init_dispex_info, };
-HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, HTMLOptionElementFactory **ret_ptr) +static HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, DispatchEx **ret_ptr) { HTMLOptionElementFactory *ret;
@@ -547,7 +550,7 @@ HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, HTMLOptionEleme init_dispatch(&ret->dispex, &HTMLOptionElementFactory_dispex, window, dispex_compat_mode(&window->event_target.dispex));
- *ret_ptr = ret; + *ret_ptr = &ret->dispex; return S_OK; }
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 30cdcce4020..af1ece068f2 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -1226,21 +1226,16 @@ static HRESULT WINAPI HTMLWindow2_get_Option(IHTMLWindow2 *iface, IHTMLOptionEle { HTMLWindow *This = impl_from_IHTMLWindow2(iface); HTMLInnerWindow *window = This->inner_window; + DispatchEx *constr; + HRESULT hres;
TRACE("(%p)->(%p)\n", This, p);
- if(!window->option_factory) { - HRESULT hres; - - hres = HTMLOptionElementFactory_Create(window, &window->option_factory); - if(FAILED(hres)) - return hres; - } - - *p = &window->option_factory->IHTMLOptionElementFactory_iface; - IHTMLOptionElementFactory_AddRef(*p); + hres = get_constructor(window, CTOR_HTMLOptionElementFactory, &constr); + if(FAILED(hres)) + return hres;
- return S_OK; + return IWineJSDispatchHost_QueryInterface(&constr->IWineJSDispatchHost_iface, &IID_IHTMLOptionElementFactory, (void**)p); }
static HRESULT WINAPI HTMLWindow2_focus(IHTMLWindow2 *iface) @@ -3695,8 +3690,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->option_factory) - note_cc_edge((nsISupports*)&This->option_factory->IHTMLOptionElementFactory_iface, "option_factory", cb); if(This->screen) note_cc_edge((nsISupports*)This->screen, "screen", cb); if(This->history) @@ -3735,11 +3728,6 @@ static void HTMLWindow_unlink(DispatchEx *dispex)
release_event_target(&This->event_target);
- if(This->option_factory) { - HTMLOptionElementFactory *option_factory = This->option_factory; - This->option_factory = NULL; - IHTMLOptionElementFactory_Release(&option_factory->IHTMLOptionElementFactory_iface); - } unlink_ref(&This->screen); if(This->history) { OmHistory *history = This->history; @@ -3822,6 +3810,8 @@ static HRESULT HTMLWindow_find_dispid(DispatchEx *dispex, const WCHAR *name, DWO id = constr_name - constructor_names + 1; else if(!wcscmp(name, L"Image")) id = CTOR_HTMLImageElementFactory; + else if(!wcscmp(name, L"Option")) + id = CTOR_HTMLOptionElementFactory;
if(id) { DispatchEx *constr; @@ -4187,13 +4177,14 @@ static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compa
/* IE9+ */ {DISPID_IHTMLWINDOW2_IMAGE}, + {DISPID_IHTMLWINDOW2_OPTION},
/* 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; + const dispex_hook_t *const window2_hooks = window2_ie9_hooks + 2; static const dispex_hook_t window3_hooks[] = { {DISPID_IHTMLWINDOW3_SETTIMEOUT, IHTMLWindow3_setTimeout_hook}, {DISPID_UNKNOWN} diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index c0320af733a..fcfaae60bff 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -506,7 +506,8 @@ typedef struct {
/* Extra constructors without new prototypes */ #define ALL_ALT_CTORS \ - X(HTMLImageElementFactory) + X(HTMLImageElementFactory) \ + X(HTMLOptionElementFactory)
typedef enum { PROT_NONE, @@ -782,7 +783,6 @@ struct HTMLInnerWindow {
IHTMLEventObj *event;
- HTMLOptionElementFactory *option_factory; IHTMLScreen *screen; OmHistory *history; IOmNavigator *navigator; @@ -1179,7 +1179,6 @@ HRESULT create_outer_window(GeckoBrowser*,mozIDOMWindowProxy*,HTMLOuterWindow*,H HRESULT update_window_doc(HTMLInnerWindow*); HTMLOuterWindow *mozwindow_to_window(const mozIDOMWindowProxy*); void get_top_window(HTMLOuterWindow*,HTMLOuterWindow**); -HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,HTMLOptionElementFactory**); 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 4119453687b..7fba7150230 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -4002,7 +4002,7 @@ sync_test("constructors", function() { if(v < 9) return;
- var ctors = [ "Image", "MutationObserver", "XMLHttpRequest" ]; + var ctors = [ "Image", "MutationObserver", "Option", "XMLHttpRequest" ]; for(i = 0; i < ctors.length; i++) { r = ctors[i]; if(!(r in window)) @@ -4011,4 +4011,5 @@ sync_test("constructors", function() { 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(window.Option.prototype === window.HTMLOptionElement.prototype, "Option.prototype != HTMLOptionElement.prototype"); });
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlwindow.c | 14 ++++++-------- dlls/mshtml/mshtml_private.h | 1 - dlls/mshtml/xmlhttprequest.c | 4 +++- 3 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index af1ece068f2..79cf3a48898 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -1902,6 +1902,8 @@ static HRESULT WINAPI HTMLWindow5_get_XMLHttpRequest(IHTMLWindow5 *iface, VARIAN { HTMLWindow *This = impl_from_IHTMLWindow5(iface); HTMLInnerWindow *window = This->inner_window; + DispatchEx *constr; + HRESULT hres;
TRACE("(%p)->(%p)\n", This, p);
@@ -1910,16 +1912,12 @@ static HRESULT WINAPI HTMLWindow5_get_XMLHttpRequest(IHTMLWindow5 *iface, VARIAN return S_OK; }
- if(!window->constructors[PROT_XMLHttpRequest]) { - HRESULT hres; - - hres = HTMLXMLHttpRequestFactory_Create(window, &window->constructors[PROT_XMLHttpRequest]); - if(FAILED(hres)) - return hres; - } + hres = get_constructor(window, PROT_XMLHttpRequest, &constr); + if(FAILED(hres)) + return hres;
V_VT(p) = VT_DISPATCH; - V_DISPATCH(p) = (IDispatch*)&window->constructors[PROT_XMLHttpRequest]->IWineJSDispatchHost_iface; + V_DISPATCH(p) = (IDispatch*)&constr->IWineJSDispatchHost_iface; IDispatch_AddRef(V_DISPATCH(p));
return S_OK; diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index fcfaae60bff..d5e93d2ef56 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1179,7 +1179,6 @@ HRESULT create_outer_window(GeckoBrowser*,mozIDOMWindowProxy*,HTMLOuterWindow*,H HRESULT update_window_doc(HTMLInnerWindow*); HTMLOuterWindow *mozwindow_to_window(const mozIDOMWindowProxy*); void get_top_window(HTMLOuterWindow*,HTMLOuterWindow**); -HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,DispatchEx**); HRESULT create_location(HTMLOuterWindow*,HTMLLocation**); HRESULT create_navigator(HTMLInnerWindow*,IOmNavigator**); HRESULT create_html_screen(HTMLInnerWindow*,IHTMLScreen**); diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index c2730d4f7cd..cadf2909a07 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -1489,6 +1489,8 @@ static const event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = { .bind_event = HTMLXMLHttpRequest_bind_event };
+static HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,DispatchEx**); + static const tid_t HTMLXMLHttpRequest_iface_tids[] = { IHTMLXMLHttpRequest2_tid, 0 @@ -1674,7 +1676,7 @@ static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = { .iface_tids = HTMLXMLHttpRequestFactory_iface_tids, };
-HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow* window, DispatchEx **ret_ptr) +static HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow *window, DispatchEx **ret_ptr) { HTMLXMLHttpRequestFactory *ret;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index b6e898f8c26..1d369ce08ad 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -3053,26 +3053,26 @@ HRESULT get_prototype(HTMLInnerWindow *script_global, prototype_id_t id, Dispatc return S_OK; }
-struct constructor +struct stub_constructor { DispatchEx dispex; prototype_id_t id; };
-static inline struct constructor *constr_from_DispatchEx(DispatchEx *iface) +static inline struct stub_constructor *stub_constructor_from_DispatchEx(DispatchEx *iface) { - return CONTAINING_RECORD(iface, struct constructor, dispex); + return CONTAINING_RECORD(iface, struct stub_constructor, dispex); }
-static void constructor_destructor(DispatchEx *dispex) +static void stub_constructor_destructor(DispatchEx *dispex) { - struct constructor *constr = constr_from_DispatchEx(dispex); + struct stub_constructor *constr = stub_constructor_from_DispatchEx(dispex); free(constr); }
-static HRESULT constructor_find_dispid(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID *dispid) +static HRESULT stub_constructor_find_dispid(DispatchEx *dispex, const WCHAR *name, DWORD flags, DISPID *dispid) { - struct constructor *constr = constr_from_DispatchEx(dispex); + struct stub_constructor *constr = stub_constructor_from_DispatchEx(dispex); HTMLInnerWindow *script_global; DispatchEx *prototype; HRESULT hres; @@ -3095,21 +3095,21 @@ static HRESULT constructor_find_dispid(DispatchEx *dispex, const WCHAR *name, DW return hres; }
-static const char *constructor_get_name(DispatchEx *dispex) +static const char *stub_constructor_get_name(DispatchEx *dispex) { - struct constructor *constr = constr_from_DispatchEx(dispex); + struct stub_constructor *constr = stub_constructor_from_DispatchEx(dispex); return object_names[constr->id - 1]; }
-static const dispex_static_data_vtbl_t constructor_dispex_vtbl = { - .destructor = constructor_destructor, - .find_dispid = constructor_find_dispid, - .get_name = constructor_get_name, +static const dispex_static_data_vtbl_t stub_constructor_dispex_vtbl = { + .destructor = stub_constructor_destructor, + .find_dispid = stub_constructor_find_dispid, + .get_name = stub_constructor_get_name, };
-static dispex_static_data_t constructor_dispex = { +static dispex_static_data_t stub_constructor_dispex = { .name = "Constructor", - .vtbl = &constructor_dispex_vtbl, + .vtbl = &stub_constructor_dispex_vtbl, .js_flags = HOSTOBJ_CONSTRUCTOR, };
@@ -3128,14 +3128,14 @@ HRESULT get_constructor(HTMLInnerWindow *script_global, prototype_id_t id, Dispa if(FAILED(hres)) return hres; }else { - struct constructor *constr; + struct stub_constructor *constr;
assert(script_global->doc->document_mode >= COMPAT_MODE_IE9);
if(!(constr = calloc(sizeof(*constr), 1))) return E_OUTOFMEMORY;
- init_dispatch(&constr->dispex, &constructor_dispex, script_global, + init_dispatch(&constr->dispex, &stub_constructor_dispex, script_global, dispex_compat_mode(&script_global->event_target.dispex)); constr->id = id; script_global->constructors[id] = &constr->dispex;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com ---
Simplifies the code as well as future code, reduces boilerplate, and allows making an extra constructor duplicate from "create" without introducing a new object at all. --- dlls/mshtml/dispex.c | 43 +++++++++++++++++-- dlls/mshtml/htmlimg.c | 74 ++++++-------------------------- dlls/mshtml/htmlselect.c | 74 ++++++-------------------------- dlls/mshtml/mshtml_private.h | 31 +++++++------- dlls/mshtml/mutation.c | 39 +++-------------- dlls/mshtml/xmlhttprequest.c | 82 ++++++------------------------------ 6 files changed, 98 insertions(+), 245 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 1d369ce08ad..e6966a1390a 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -3053,6 +3053,31 @@ HRESULT get_prototype(HTMLInnerWindow *script_global, prototype_id_t id, Dispatc return S_OK; }
+void constructor_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) +{ + struct constructor *This = constructor_from_DispatchEx(dispex); + + if(This->window) + note_cc_edge((nsISupports*)&This->window->base.IHTMLWindow2_iface, "window", cb); +} + +void constructor_unlink(DispatchEx *dispex) +{ + struct constructor *This = constructor_from_DispatchEx(dispex); + + if(This->window) { + HTMLInnerWindow *window = This->window; + This->window = NULL; + IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); + } +} + +void constructor_destructor(DispatchEx *dispex) +{ + struct constructor *This = constructor_from_DispatchEx(dispex); + free(This); +} + struct stub_constructor { DispatchEx dispex; @@ -3123,10 +3148,20 @@ HRESULT get_constructor(HTMLInnerWindow *script_global, prototype_id_t id, Dispa }
info = object_descriptors[id]; - if(info->init_constructor) { - HRESULT hres = info->init_constructor(script_global, &script_global->constructors[id]); - if(FAILED(hres)) - return hres; + if(info->constructor_info) { + struct constructor *constr = malloc(sizeof(*constr)); + + if(!constr) + return E_OUTOFMEMORY; + + constr->iface.lpVtbl = info->constructor_vtbl; + constr->window = script_global; + IHTMLWindow2_AddRef(&script_global->base.IHTMLWindow2_iface); + + init_dispatch(&constr->dispex, info->constructor_info, script_global, + dispex_compat_mode(&script_global->event_target.dispex)); + + script_global->constructors[id] = &constr->dispex; }else { struct stub_constructor *constr;
diff --git a/dlls/mshtml/htmlimg.c b/dlls/mshtml/htmlimg.c index 518aae46213..965f6fa54a0 100644 --- a/dlls/mshtml/htmlimg.c +++ b/dlls/mshtml/htmlimg.c @@ -707,9 +707,9 @@ HRESULT HTMLImgElement_Create(HTMLDocumentNode *doc, nsIDOMElement *nselem, HTML return S_OK; }
-static inline HTMLImageElementFactory *impl_from_IHTMLImageElementFactory(IHTMLImageElementFactory *iface) +static inline struct constructor *impl_from_IHTMLImageElementFactory(IHTMLImageElementFactory *iface) { - return CONTAINING_RECORD(iface, HTMLImageElementFactory, IHTMLImageElementFactory_iface); + return CONTAINING_RECORD(iface, struct constructor, iface); }
DISPEX_IDISPATCH_IMPL(HTMLImageElementFactory, IHTMLImageElementFactory, @@ -742,7 +742,7 @@ static LONG var_to_size(const VARIANT *v) static HRESULT WINAPI HTMLImageElementFactory_create(IHTMLImageElementFactory *iface, VARIANT width, VARIANT height, IHTMLImgElement **img_elem) { - HTMLImageElementFactory *This = impl_from_IHTMLImageElementFactory(iface); + struct constructor *This = impl_from_IHTMLImageElementFactory(iface); HTMLDocumentNode *doc = This->window->doc; IHTMLImgElement *img; HTMLElement *elem; @@ -796,51 +796,21 @@ static const IHTMLImageElementFactoryVtbl HTMLImageElementFactoryVtbl = { HTMLImageElementFactory_create };
-static inline HTMLImageElementFactory *impl_from_DispatchEx(DispatchEx *iface) -{ - return CONTAINING_RECORD(iface, HTMLImageElementFactory, dispex); -} - static void *HTMLImageElementFactory_query_interface(DispatchEx *dispex, REFIID riid) { - HTMLImageElementFactory *This = impl_from_DispatchEx(dispex); + struct constructor *This = constructor_from_DispatchEx(dispex);
if(IsEqualGUID(&IID_IHTMLImageElementFactory, riid)) - return &This->IHTMLImageElementFactory_iface; + return &This->iface;
return NULL; }
-static void HTMLImageElementFactory_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) -{ - HTMLImageElementFactory *This = impl_from_DispatchEx(dispex); - - if(This->window) - note_cc_edge((nsISupports*)&This->window->base.IHTMLWindow2_iface, "window", cb); -} - -static void HTMLImageElementFactory_unlink(DispatchEx *dispex) -{ - HTMLImageElementFactory *This = impl_from_DispatchEx(dispex); - - if(This->window) { - HTMLInnerWindow *window = This->window; - This->window = NULL; - IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); - } -} - -static void HTMLImageElementFactory_destructor(DispatchEx *dispex) -{ - HTMLImageElementFactory *This = impl_from_DispatchEx(dispex); - free(This); -} - static HRESULT HTMLImageElementFactory_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { - HTMLImageElementFactory *This = impl_from_DispatchEx(dispex); + struct constructor *This = constructor_from_DispatchEx(dispex); IHTMLImgElement *img; VARIANT empty, *width, *height; HRESULT hres; @@ -853,7 +823,7 @@ static HRESULT HTMLImageElementFactory_value(DispatchEx *dispex, LCID lcid, width = argc >= 1 ? params->rgvarg + (params->cArgs - 1) : ∅ height = argc >= 2 ? params->rgvarg + (params->cArgs - 2) : ∅
- hres = IHTMLImageElementFactory_create(&This->IHTMLImageElementFactory_iface, *width, *height, + hres = IHTMLImageElementFactory_create((IHTMLImageElementFactory*)&This->iface, *width, *height, &img); if(FAILED(hres)) return hres; @@ -872,38 +842,18 @@ static void HTMLImageElementFactory_init_dispex_info(dispex_data_t *info, compat
static const dispex_static_data_vtbl_t HTMLImageElementFactory_dispex_vtbl = { .query_interface = HTMLImageElementFactory_query_interface, - .destructor = HTMLImageElementFactory_destructor, - .traverse = HTMLImageElementFactory_traverse, - .unlink = HTMLImageElementFactory_unlink, + .destructor = constructor_destructor, + .traverse = constructor_traverse, + .unlink = constructor_unlink, .value = HTMLImageElementFactory_value, };
-static HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,DispatchEx**); - dispex_static_data_t HTMLImageElementFactory_dispex = { .name = "Function", .constructor_id = PROT_HTMLImageElement, - .init_constructor = HTMLImageElementFactory_Create, + .constructor_info = &HTMLImageElementFactory_dispex, + .constructor_vtbl = &HTMLImageElementFactoryVtbl, .vtbl = &HTMLImageElementFactory_dispex_vtbl, .disp_tid = IHTMLImageElementFactory_tid, .init_info = HTMLImageElementFactory_init_dispex_info, }; - -static HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow *window, DispatchEx **ret_val) -{ - HTMLImageElementFactory *ret; - - ret = malloc(sizeof(HTMLImageElementFactory)); - if(!ret) - return E_OUTOFMEMORY; - - ret->IHTMLImageElementFactory_iface.lpVtbl = &HTMLImageElementFactoryVtbl; - ret->window = window; - IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); - - init_dispatch(&ret->dispex, &HTMLImageElementFactory_dispex, window, - dispex_compat_mode(&window->event_target.dispex)); - - *ret_val = &ret->dispex; - return S_OK; -} diff --git a/dlls/mshtml/htmlselect.c b/dlls/mshtml/htmlselect.c index bc45718349c..24fa61a4e9c 100644 --- a/dlls/mshtml/htmlselect.c +++ b/dlls/mshtml/htmlselect.c @@ -374,9 +374,9 @@ HRESULT HTMLOptionElement_Create(HTMLDocumentNode *doc, nsIDOMElement *nselem, H return S_OK; }
-static inline HTMLOptionElementFactory *impl_from_IHTMLOptionElementFactory(IHTMLOptionElementFactory *iface) +static inline struct constructor *impl_from_IHTMLOptionElementFactory(IHTMLOptionElementFactory *iface) { - return CONTAINING_RECORD(iface, HTMLOptionElementFactory, IHTMLOptionElementFactory_iface); + return CONTAINING_RECORD(iface, struct constructor, iface); }
DISPEX_IDISPATCH_IMPL(HTMLOptionElementFactory, IHTMLOptionElementFactory, @@ -386,7 +386,7 @@ static HRESULT WINAPI HTMLOptionElementFactory_create(IHTMLOptionElementFactory VARIANT text, VARIANT value, VARIANT defaultselected, VARIANT selected, IHTMLOptionElement **optelem) { - HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface); + struct constructor *This = impl_from_IHTMLOptionElementFactory(iface); nsIDOMElement *nselem; HTMLDOMNode *node; HRESULT hres; @@ -438,51 +438,21 @@ static const IHTMLOptionElementFactoryVtbl HTMLOptionElementFactoryVtbl = { HTMLOptionElementFactory_create };
-static inline HTMLOptionElementFactory *HTMLOptionElementFactory_from_DispatchEx(DispatchEx *iface) -{ - return CONTAINING_RECORD(iface, HTMLOptionElementFactory, dispex); -} - static void *HTMLOptionElementFactory_query_interface(DispatchEx *dispex, REFIID riid) { - HTMLOptionElementFactory *This = HTMLOptionElementFactory_from_DispatchEx(dispex); + struct constructor *This = constructor_from_DispatchEx(dispex);
if(IsEqualGUID(&IID_IHTMLOptionElementFactory, riid)) - return &This->IHTMLOptionElementFactory_iface; + return &This->iface;
return NULL; }
-static void HTMLOptionElementFactory_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) -{ - HTMLOptionElementFactory *This = HTMLOptionElementFactory_from_DispatchEx(dispex); - - if(This->window) - note_cc_edge((nsISupports*)&This->window->base.IHTMLWindow2_iface, "window", cb); -} - -static void HTMLOptionElementFactory_unlink(DispatchEx *dispex) -{ - HTMLOptionElementFactory *This = HTMLOptionElementFactory_from_DispatchEx(dispex); - - if(This->window) { - HTMLInnerWindow *window = This->window; - This->window = NULL; - IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); - } -} - -static void HTMLOptionElementFactory_destructor(DispatchEx *dispex) -{ - HTMLOptionElementFactory *This = HTMLOptionElementFactory_from_DispatchEx(dispex); - free(This); -} - static HRESULT HTMLOptionElementFactory_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { - HTMLOptionElementFactory *This = HTMLOptionElementFactory_from_DispatchEx(dispex); + struct constructor *This = constructor_from_DispatchEx(dispex); unsigned int i, argc = params->cArgs - params->cNamedArgs; IHTMLOptionElement *opt; VARIANT empty, *arg[4]; @@ -499,7 +469,7 @@ static HRESULT HTMLOptionElementFactory_value(DispatchEx *dispex, LCID lcid, for(i = 0; i < ARRAY_SIZE(arg); i++) arg[i] = argc > i ? ¶ms->rgvarg[params->cArgs - 1 - i] : ∅
- hres = IHTMLOptionElementFactory_create(&This->IHTMLOptionElementFactory_iface, + hres = IHTMLOptionElementFactory_create((IHTMLOptionElementFactory*)&This->iface, *arg[0], *arg[1], *arg[2], *arg[3], &opt); if(FAILED(hres)) return hres; @@ -518,42 +488,22 @@ static void HTMLImageElementFactory_init_dispex_info(dispex_data_t *info, compat
static const dispex_static_data_vtbl_t HTMLOptionElementFactory_dispex_vtbl = { .query_interface = HTMLOptionElementFactory_query_interface, - .destructor = HTMLOptionElementFactory_destructor, - .traverse = HTMLOptionElementFactory_traverse, - .unlink = HTMLOptionElementFactory_unlink, + .destructor = constructor_destructor, + .traverse = constructor_traverse, + .unlink = constructor_unlink, .value = HTMLOptionElementFactory_value, };
-static HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,DispatchEx**); - dispex_static_data_t HTMLOptionElementFactory_dispex = { .name = "Function", .constructor_id = PROT_HTMLOptionElement, - .init_constructor = HTMLOptionElementFactory_Create, + .constructor_info = &HTMLOptionElementFactory_dispex, + .constructor_vtbl = &HTMLOptionElementFactoryVtbl, .vtbl = &HTMLOptionElementFactory_dispex_vtbl, .disp_tid = IHTMLOptionElementFactory_tid, .init_info = HTMLImageElementFactory_init_dispex_info, };
-static HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, DispatchEx **ret_ptr) -{ - HTMLOptionElementFactory *ret; - - ret = malloc(sizeof(*ret)); - if(!ret) - return E_OUTOFMEMORY; - - ret->IHTMLOptionElementFactory_iface.lpVtbl = &HTMLOptionElementFactoryVtbl; - ret->window = window; - IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); - - init_dispatch(&ret->dispex, &HTMLOptionElementFactory_dispex, window, - dispex_compat_mode(&window->event_target.dispex)); - - *ret_ptr = &ret->dispex; - return S_OK; -} - struct HTMLSelectElement { HTMLElement element;
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index d5e93d2ef56..0e13aa26f7e 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -529,7 +529,8 @@ struct dispex_static_data_t { const tid_t disp_tid; const tid_t* const iface_tids; void (*init_info)(dispex_data_t*,compat_mode_t); - HRESULT (*init_constructor)(HTMLInnerWindow*,DispatchEx**); + dispex_static_data_t *constructor_info; + const void *constructor_vtbl; dispex_data_t *info_cache[COMPAT_MODE_CNT]; dispex_data_t *prototype_info[COMPAT_MODE_CNT - COMPAT_MODE_IE9]; dispex_data_t *delayed_init_info; @@ -667,6 +668,20 @@ typedef enum {
dispex_prop_type_t get_dispid_type(DISPID);
+struct constructor { + DispatchEx dispex; + IUnknown iface; + HTMLInnerWindow *window; +}; + +static inline struct constructor *constructor_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, struct constructor, dispex); +} +void constructor_traverse(DispatchEx*,nsCycleCollectionTraversalCallback*); +void constructor_unlink(DispatchEx*); +void constructor_destructor(DispatchEx*); + typedef enum { GLOBAL_SCRIPTVAR, GLOBAL_ELEMENTVAR, @@ -687,20 +702,6 @@ struct EventTarget { struct wine_rb_tree handler_map; };
-typedef struct { - DispatchEx dispex; - IHTMLOptionElementFactory IHTMLOptionElementFactory_iface; - - HTMLInnerWindow *window; -} HTMLOptionElementFactory; - -typedef struct { - DispatchEx dispex; - IHTMLImageElementFactory IHTMLImageElementFactory_iface; - - HTMLInnerWindow *window; -} HTMLImageElementFactory; - struct HTMLLocation { DispatchEx dispex; IHTMLLocation IHTMLLocation_iface; diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index a203c03e2dc..1642bb4a065 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -1198,8 +1198,6 @@ static void mutation_observer_destructor(DispatchEx *dispex) free(This); }
-static HRESULT create_mutation_observer_ctor(HTMLInnerWindow *script_global, DispatchEx **ret); - static const dispex_static_data_vtbl_t mutation_observer_dispex_vtbl = { .query_interface = mutation_observer_query_interface, .destructor = mutation_observer_destructor, @@ -1207,13 +1205,15 @@ static const dispex_static_data_vtbl_t mutation_observer_dispex_vtbl = { .unlink = mutation_observer_unlink };
+static dispex_static_data_t mutation_observer_ctor_dispex; + static const tid_t mutation_observer_iface_tids[] = { IWineMSHTMLMutationObserver_tid, 0 }; dispex_static_data_t MutationObserver_dispex = { .id = PROT_MutationObserver, - .init_constructor = create_mutation_observer_ctor, + .constructor_info = &mutation_observer_ctor_dispex, .vtbl = &mutation_observer_dispex_vtbl, .disp_tid = IWineMSHTMLMutationObserver_tid, .iface_tids = mutation_observer_iface_tids, @@ -1247,22 +1247,11 @@ struct mutation_observer_ctor { DispatchEx dispex; };
-static inline struct mutation_observer_ctor *mutation_observer_ctor_from_DispatchEx(DispatchEx *iface) -{ - return CONTAINING_RECORD(iface, struct mutation_observer_ctor, dispex); -} - -static void mutation_observer_ctor_destructor(DispatchEx *dispex) -{ - struct mutation_observer_ctor *This = mutation_observer_ctor_from_DispatchEx(dispex); - free(This); -} - static HRESULT mutation_observer_ctor_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { - struct mutation_observer_ctor *This = mutation_observer_ctor_from_DispatchEx(dispex); + struct constructor *This = constructor_from_DispatchEx(dispex); VARIANT *callback; IWineMSHTMLMutationObserver *mutation_observer; HRESULT hres; @@ -1305,7 +1294,7 @@ static HRESULT mutation_observer_ctor_value(DispatchEx *dispex, LCID lcid, }
static const dispex_static_data_vtbl_t mutation_observer_ctor_dispex_vtbl = { - .destructor = mutation_observer_ctor_destructor, + .destructor = constructor_destructor, .value = mutation_observer_ctor_value };
@@ -1314,21 +1303,3 @@ static dispex_static_data_t mutation_observer_ctor_dispex = { .constructor_id = PROT_MutationObserver, .vtbl = &mutation_observer_ctor_dispex_vtbl, }; - -static HRESULT create_mutation_observer_ctor(HTMLInnerWindow *script_global, DispatchEx **ret) -{ - struct mutation_observer_ctor *obj; - - obj = calloc(1, sizeof(*obj)); - if(!obj) - { - ERR("No memory.\n"); - return E_OUTOFMEMORY; - } - - init_dispatch(&obj->dispex, &mutation_observer_ctor_dispex, script_global, - dispex_compat_mode(&script_global->event_target.dispex)); - - *ret = &obj->dispex; - return S_OK; -} diff --git a/dlls/mshtml/xmlhttprequest.c b/dlls/mshtml/xmlhttprequest.c index cadf2909a07..e6324a9288a 100644 --- a/dlls/mshtml/xmlhttprequest.c +++ b/dlls/mshtml/xmlhttprequest.c @@ -36,13 +36,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
-typedef struct { - DispatchEx dispex; - IHTMLXMLHttpRequestFactory IHTMLXMLHttpRequestFactory_iface; - - HTMLInnerWindow *window; -} HTMLXMLHttpRequestFactory; - static HRESULT bstr_to_nsacstr(BSTR bstr, nsACString *str) { char *cstr = strdupWtoU(bstr); @@ -1489,7 +1482,8 @@ static const event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = { .bind_event = HTMLXMLHttpRequest_bind_event };
-static HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,DispatchEx**); +static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl; +static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex;
static const tid_t HTMLXMLHttpRequest_iface_tids[] = { IHTMLXMLHttpRequest2_tid, @@ -1497,7 +1491,8 @@ static const tid_t HTMLXMLHttpRequest_iface_tids[] = { }; dispex_static_data_t XMLHttpRequest_dispex = { .id = PROT_XMLHttpRequest, - .init_constructor = HTMLXMLHttpRequestFactory_Create, + .constructor_info = &HTMLXMLHttpRequestFactory_dispex, + .constructor_vtbl = &HTMLXMLHttpRequestFactoryVtbl, .vtbl = &HTMLXMLHttpRequest_event_target_vtbl.dispex_vtbl, .disp_tid = DispHTMLXMLHttpRequest_tid, .iface_tids = HTMLXMLHttpRequest_iface_tids, @@ -1506,9 +1501,9 @@ dispex_static_data_t XMLHttpRequest_dispex = {
/* IHTMLXMLHttpRequestFactory */ -static inline HTMLXMLHttpRequestFactory *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory *iface) +static inline struct constructor *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory *iface) { - return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory_iface); + return CONTAINING_RECORD(iface, struct constructor, iface); }
DISPEX_IDISPATCH_IMPL(HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory, @@ -1516,7 +1511,7 @@ DISPEX_IDISPATCH_IMPL(HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory,
static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p) { - HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface); + struct constructor *This = impl_from_IHTMLXMLHttpRequestFactory(iface); HTMLXMLHttpRequest *ret; nsIXMLHttpRequest *nsxhr; nsIDOMEventTarget *nstarget; @@ -1593,50 +1588,20 @@ static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl = { HTMLXMLHttpRequestFactory_create };
-static inline HTMLXMLHttpRequestFactory *factory_from_DispatchEx(DispatchEx *iface) -{ - return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, dispex); -} - static void *HTMLXMLHttpRequestFactory_query_interface(DispatchEx *dispex, REFIID riid) { - HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(dispex); + struct constructor *This = constructor_from_DispatchEx(dispex);
if(IsEqualGUID(&IID_IHTMLXMLHttpRequestFactory, riid)) - return &This->IHTMLXMLHttpRequestFactory_iface; + return &This->iface;
return NULL; }
-static void HTMLXMLHttpRequestFactory_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb) -{ - HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(dispex); - - if(This->window) - note_cc_edge((nsISupports*)&This->window->base.IHTMLWindow2_iface, "window", cb); -} - -static void HTMLXMLHttpRequestFactory_unlink(DispatchEx *dispex) -{ - HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(dispex); - - if(This->window) { - HTMLInnerWindow *window = This->window; - This->window = NULL; - IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface); - } -} - -static void HTMLXMLHttpRequestFactory_destructor(DispatchEx *dispex) -{ - HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(dispex); - free(This); -} - static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { - HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(iface); + struct constructor *This = constructor_from_DispatchEx(iface); IHTMLXMLHttpRequest *xhr; HRESULT hres;
@@ -1647,7 +1612,7 @@ static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WOR return E_NOTIMPL; }
- hres = IHTMLXMLHttpRequestFactory_create(&This->IHTMLXMLHttpRequestFactory_iface, &xhr); + hres = IHTMLXMLHttpRequestFactory_create((IHTMLXMLHttpRequestFactory*)&This->iface, &xhr); if(FAILED(hres)) return hres;
@@ -1658,9 +1623,9 @@ static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WOR
static const dispex_static_data_vtbl_t HTMLXMLHttpRequestFactory_dispex_vtbl = { .query_interface = HTMLXMLHttpRequestFactory_query_interface, - .destructor = HTMLXMLHttpRequestFactory_destructor, - .traverse = HTMLXMLHttpRequestFactory_traverse, - .unlink = HTMLXMLHttpRequestFactory_unlink, + .destructor = constructor_destructor, + .traverse = constructor_traverse, + .unlink = constructor_unlink, .value = HTMLXMLHttpRequestFactory_value };
@@ -1675,22 +1640,3 @@ static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = { .disp_tid = IHTMLXMLHttpRequestFactory_tid, .iface_tids = HTMLXMLHttpRequestFactory_iface_tids, }; - -static HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow *window, DispatchEx **ret_ptr) -{ - HTMLXMLHttpRequestFactory *ret; - - ret = malloc(sizeof(*ret)); - if(!ret) - return E_OUTOFMEMORY; - - ret->IHTMLXMLHttpRequestFactory_iface.lpVtbl = &HTMLXMLHttpRequestFactoryVtbl; - ret->window = window; - IHTMLWindow2_AddRef(&window->base.IHTMLWindow2_iface); - - init_dispatch(&ret->dispex, &HTMLXMLHttpRequestFactory_dispex, window, - dispex_compat_mode(&window->event_target.dispex)); - - *ret_ptr = &ret->dispex; - return S_OK; -}
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/function.c | 36 ++++++++++++++++++----- dlls/jscript/jscript.c | 6 ++-- dlls/jscript/jscript.h | 2 +- dlls/jscript/jsdisp.idl | 2 +- dlls/mshtml/dispex.c | 49 ++++++++++++++++++++++++++----- dlls/mshtml/tests/documentmode.js | 9 ++++++ 6 files changed, 85 insertions(+), 19 deletions(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 9f1f53a96ae..c6e8929770b 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -74,6 +74,7 @@ typedef struct { typedef struct { FunctionInstance function; IWineJSDispatchHost *host_iface; + DWORD req_flags; } HostConstructor;
typedef struct { @@ -1130,6 +1131,9 @@ static HRESULT HostConstructor_call(script_ctx_t *ctx, FunctionInstance *func, j HRESULT hres = S_OK; unsigned i;
+ if((flags & function->req_flags) != function->req_flags) + return E_UNEXPECTED; + flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK; if(argc > ARRAYSIZE(buf) && !(dp.rgvarg = malloc(argc * sizeof(*dp.rgvarg)))) return E_OUTOFMEMORY; @@ -1159,8 +1163,13 @@ static HRESULT HostConstructor_call(script_ctx_t *ctx, FunctionInstance *func, j return hres; }
-static HRESULT HostConstructor_toString(FunctionInstance *function, jsstr_t **ret) +static HRESULT HostConstructor_toString(FunctionInstance *func, jsstr_t **ret) { + HostConstructor *function = (HostConstructor*)func; + + if(function->req_flags) + return native_function_string(L"create", ret); + *ret = jsstr_alloc(L"\nfunction() {\n [native code]\n}\n"); return *ret ? S_OK : E_OUTOFMEMORY; } @@ -1188,7 +1197,7 @@ static const function_vtbl_t HostConstructorVtbl = { };
HRESULT init_host_constructor(script_ctx_t *ctx, IWineJSDispatchHost *host_constr, IWineJSDispatch *prototype, - IWineJSDispatch **ret) + IWineJSDispatch *method, IWineJSDispatch **ret) { HostConstructor *function; HRESULT hres; @@ -1199,11 +1208,24 @@ HRESULT init_host_constructor(script_ctx_t *ctx, IWineJSDispatchHost *host_const return hres; function->host_iface = host_constr;
- hres = jsdisp_define_data_property(&function->function.dispex, L"prototype", PROPF_WRITABLE | PROPF_CONFIGURABLE, - jsval_disp((IDispatch *)prototype)); - if(FAILED(hres)) { - IWineJSDispatch_Free(&function->function.dispex.IWineJSDispatch_iface); - return hres; + if(!prototype) + function->req_flags = DISPATCH_METHOD; + else { + hres = jsdisp_define_data_property(&function->function.dispex, L"prototype", PROPF_WRITABLE | PROPF_CONFIGURABLE, + jsval_disp((IDispatch *)prototype)); + if(FAILED(hres)) { + IWineJSDispatch_Free(&function->function.dispex.IWineJSDispatch_iface); + return hres; + } + } + + if(method) { + hres = jsdisp_define_data_property(&function->function.dispex, L"create", PROPF_WRITABLE | PROPF_CONFIGURABLE, + jsval_disp((IDispatch *)method)); + if(FAILED(hres)) { + IWineJSDispatch_Free(&function->function.dispex.IWineJSDispatch_iface); + return hres; + } }
*ret = &function->function.dispex.IWineJSDispatch_iface; diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index c42109b4143..58a414b92b3 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -1458,11 +1458,11 @@ static HRESULT WINAPI WineJScript_InitHostObject(IWineJScript *iface, IWineJSDis return init_host_object(This->ctx, host_obj, prototype, flags, ret); }
-static HRESULT WINAPI WineJScript_InitHostConstructor(IWineJScript *iface, IWineJSDispatchHost *constr, - IWineJSDispatch *prototype, IWineJSDispatch **ret) +static HRESULT WINAPI WineJScript_InitHostConstructor(IWineJScript *iface, IWineJSDispatchHost *constr, IWineJSDispatch *prototype, + IWineJSDispatch *method, IWineJSDispatch **ret) { JScript *This = impl_from_IWineJScript(iface); - return init_host_constructor(This->ctx, constr, prototype, ret); + return init_host_constructor(This->ctx, constr, prototype, method, ret); }
static const IWineJScriptVtbl WineJScriptVtbl = { diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index e9207c231d8..5df78fddd41 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -241,7 +241,7 @@ HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,jsdisp_t*,jsdisp_t**); HRESULT init_dispex(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*); HRESULT init_dispex_from_constr(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*); HRESULT init_host_object(script_ctx_t*,IWineJSDispatchHost*,IWineJSDispatch*,UINT32,IWineJSDispatch**); -HRESULT init_host_constructor(script_ctx_t*,IWineJSDispatchHost*,IWineJSDispatch*,IWineJSDispatch**); +HRESULT init_host_constructor(script_ctx_t*,IWineJSDispatchHost*,IWineJSDispatch*,IWineJSDispatch*,IWineJSDispatch**);
HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*); HRESULT disp_call_name(script_ctx_t*,IDispatch*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*); diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index 5f1384bce78..9aff332e4a5 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -83,5 +83,5 @@ interface IWineJSDispatchHost : IDispatchEx interface IWineJScript : IUnknown { HRESULT InitHostObject(IWineJSDispatchHost *host_obj, IWineJSDispatch *prototype, UINT32 flags, IWineJSDispatch **ret); - HRESULT InitHostConstructor(IWineJSDispatchHost *constr, IWineJSDispatch *prototype, IWineJSDispatch **ret); + HRESULT InitHostConstructor(IWineJSDispatchHost *constr, IWineJSDispatch *prototype, IWineJSDispatch *method, IWineJSDispatch **ret); } diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index e6966a1390a..a1401dd815b 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -135,6 +135,8 @@ PRIVATE_TID_LIST #undef XDIID };
+static void init_dispatch_from_desc(DispatchEx*,dispex_data_t*,HTMLInnerWindow*,DispatchEx*); + static HRESULT load_typelib(void) { WCHAR module_path[MAX_PATH + 3]; @@ -1875,6 +1877,43 @@ static dispex_data_t *ensure_dispex_info(dispex_static_data_t *desc, compat_mode return desc->info_cache[compat_mode]; }
+static HRESULT init_host_constructor(DispatchEx *dispex, HTMLInnerWindow *script_global) +{ + prototype_id_t id = dispex->info->desc->constructor_id; + DispatchEx *prototype; + DISPID dispid; + HRESULT hres; + + hres = get_prototype(script_global, id, &prototype); + if(FAILED(hres)) + return hres; + + hres = get_builtin_id(dispex->info, L"create", 0, &dispid); + if(SUCCEEDED(hres)) { + struct constructor *create = malloc(sizeof(*create)); + + if(!create) + return E_OUTOFMEMORY; + create->iface = constructor_from_DispatchEx(dispex)->iface; + create->window = script_global; + IHTMLWindow2_AddRef(&script_global->base.IHTMLWindow2_iface); + + init_dispatch_from_desc(&create->dispex, object_descriptors[id]->constructor_info->info_cache[dispex->info->compat_mode], + NULL, NULL); + + hres = IWineJScript_InitHostConstructor(script_global->jscript, &create->dispex.IWineJSDispatchHost_iface, + NULL, NULL, &create->dispex.jsdisp); + if(SUCCEEDED(hres)) + hres = IWineJScript_InitHostConstructor(script_global->jscript, &dispex->IWineJSDispatchHost_iface, + prototype->jsdisp, create->dispex.jsdisp, &dispex->jsdisp); + IWineJSDispatchHost_Release(&create->dispex.IWineJSDispatchHost_iface); + }else if(hres == DISP_E_UNKNOWNNAME) { + hres = IWineJScript_InitHostConstructor(script_global->jscript, &dispex->IWineJSDispatchHost_iface, + prototype->jsdisp, NULL, &dispex->jsdisp); + } + return hres; +} + static void init_host_object(DispatchEx *dispex, HTMLInnerWindow *script_global, DispatchEx *prototype) { HRESULT hres; @@ -1885,13 +1924,9 @@ static void init_host_object(DispatchEx *dispex, HTMLInnerWindow *script_global, if(!script_global->jscript) initialize_script_global(script_global); if(script_global->jscript && !dispex->jsdisp) { - if(dispex->info->desc->constructor_id) { - DispatchEx *prototype; - if(FAILED(hres = get_prototype(script_global, dispex->info->desc->constructor_id, &prototype))) - return; - hres = IWineJScript_InitHostConstructor(script_global->jscript, &dispex->IWineJSDispatchHost_iface, - prototype->jsdisp, &dispex->jsdisp); - }else + if(dispex->info->desc->constructor_id) + hres = init_host_constructor(dispex, script_global); + else hres = IWineJScript_InitHostObject(script_global->jscript, &dispex->IWineJSDispatchHost_iface, prototype ? prototype->jsdisp : NULL, dispex->info->desc->js_flags, &dispex->jsdisp); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 7fba7150230..17ba2d2fba2 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -4012,4 +4012,13 @@ sync_test("constructors", function() { } ok(window.Image.prototype === window.HTMLImageElement.prototype, "Image.prototype != HTMLImageElement.prototype"); ok(window.Option.prototype === window.HTMLOptionElement.prototype, "Option.prototype != HTMLOptionElement.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 { + new XMLHttpRequest.create(); + ok(false, "new XMLHttpRequest.create() did not throw"); + }catch(e) { + ok(e.number === 0x0ffff - 0x80000000, "new XMLHttpRequest.create() threw " + e.number); + } });
From: Gabriel Ivăncescu gabrielopcode@gmail.com
And use it instead of on_prototype boolean.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index a1401dd815b..e5913f3c618 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -55,7 +55,7 @@ typedef struct { tid_t tid; BSTR name; dispex_hook_invoke_t hook; - BOOLEAN on_prototype; + prototype_id_t prototype_id; SHORT call_vtbl_off; SHORT put_vtbl_off; SHORT get_vtbl_off; @@ -519,31 +519,32 @@ static int __cdecl func_name_cmp(const void *p1, const void *p2) return wcsicmp((*(func_info_t* const*)p1)->name, (*(func_info_t* const*)p2)->name); }
-static BOOL find_prototype_member(const dispex_data_t *info, DISPID id) +static prototype_id_t find_prototype_member(const dispex_data_t *info, DISPID id) { compat_mode_t compat_mode = info->compat_mode; + prototype_id_t ret = PROT_NONE;
if(compat_mode < COMPAT_MODE_IE9) - return FALSE; + return ret;
if(!info->is_prototype) { if(!info->desc->id) - return FALSE; + return ret; info = info->desc->prototype_info[compat_mode - COMPAT_MODE_IE9]; }else { if(!info->desc->prototype_id) - return FALSE; + return ret; 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; + ret = info->desc->id; if(!info->desc->prototype_id) break; info = object_descriptors[info->desc->prototype_id]->prototype_info[compat_mode - COMPAT_MODE_IE9]; } - return FALSE; + return ret; }
static const char *object_names[] = { @@ -618,11 +619,11 @@ static dispex_data_t *preprocess_dispex_data(dispex_static_data_t *desc, compat_
data->name_table = malloc(data->func_cnt * sizeof(func_info_t*)); for(i=0; i < data->func_cnt; i++) { + data->funcs[i].prototype_id = find_prototype_member(data, data->funcs[i].id); + /* Don't expose properties that are exposed by object's prototype */ - if(find_prototype_member(data, data->funcs[i].id)) { - data->funcs[i].on_prototype = TRUE; + if(data->funcs[i].prototype_id != PROT_NONE) continue; - } data->name_table[data->name_cnt++] = data->funcs+i; } qsort(data->name_table, data->name_cnt, sizeof(func_info_t*), func_name_cmp); @@ -2546,7 +2547,7 @@ HRESULT dispex_next_id(DispatchEx *dispex, DISPID id, BOOL enum_all_own_props, D }
while(func < dispex->info->funcs + dispex->info->func_cnt) { - if(enum_all_own_props ? (!func->on_prototype) : (func->func_disp_idx == -1)) { + if(enum_all_own_props ? (func->prototype_id == PROT_NONE) : (func->func_disp_idx == -1)) { *ret = func->id; return S_OK; }
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/function.c | 2 +- dlls/jscript/jsdisp.idl | 4 ++-- dlls/mshtml/dispex.c | 21 ++++++++++++++------- dlls/mshtml/htmlwindow.c | 4 ++-- dlls/mshtml/tests/documentmode.js | 14 ++++++++++++++ 5 files changed, 33 insertions(+), 12 deletions(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index c6e8929770b..494e14bc5b7 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -67,7 +67,7 @@ typedef struct { FunctionInstance function; const WCHAR *name; UINT32 id; - UINT32 iid; + INT32 iid; UINT32 flags; } HostFunction;
diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index 9aff332e4a5..e06b36b2893 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -27,7 +27,7 @@ struct property_info UINT32 flags; const WCHAR *name; UINT32 index; - UINT32 iid; + INT32 iid; };
const unsigned int PROPF_METHOD = 0x0100; @@ -69,7 +69,7 @@ interface IWineJSDispatchHost : IDispatchEx HRESULT SetProperty(DISPID id, LCID lcid, VARIANT *v, EXCEPINFO *ei, IServiceProvider *caller); HRESULT DeleteProperty(DISPID id); HRESULT ConfigureProperty(DISPID id, UINT32 flags); - HRESULT CallFunction(DISPID id, UINT32 iid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); + HRESULT CallFunction(DISPID id, INT32 iid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); HRESULT Construct(LCID lcid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller); HRESULT GetOuterDispatch(IWineJSDispatchHost **ret); HRESULT ToString(BSTR *str); diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index e5913f3c618..96667f510bf 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1078,7 +1078,7 @@ static HRESULT function_apply(func_disp_t *func, DISPPARAMS *dp, LCID lcid, VARI } }
- hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, func->info->tid, DISPATCH_METHOD, ¶ms, res, ei, caller); + hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, -func->info->tid, DISPATCH_METHOD, ¶ms, res, ei, caller);
fail: while(argc--) @@ -1105,7 +1105,7 @@ static HRESULT function_call(func_disp_t *func, DISPPARAMS *dp, LCID lcid, VARIA if(FAILED(hres)) return CTL_E_ILLEGALFUNCTIONCALL;
- hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, func->info->tid, DISPATCH_METHOD, ¶ms, res, ei, caller); + hres = IWineJSDispatchHost_CallFunction(this_iface, func->info->id, -func->info->tid, DISPATCH_METHOD, ¶ms, res, ei, caller); IWineJSDispatchHost_Release(this_iface); return (hres == E_UNEXPECTED) ? CTL_E_ILLEGALFUNCTIONCALL : hres; } @@ -2629,13 +2629,13 @@ static HRESULT get_host_property_descriptor(DispatchEx *This, DISPID id, struct desc->flags = PROPF_CONFIGURABLE; desc->name = func->name; if(func->func_disp_idx >= 0) { - desc->iid = func->tid; + desc->iid = This->info->desc->id; desc->flags |= PROPF_METHOD | PROPF_WRITABLE; }else { if(func->func_disp_idx == -1) desc->flags |= PROPF_ENUMERABLE; if(This->info->is_prototype) { - desc->iid = func->tid; + desc->iid = This->info->desc->id; if(func->put_vtbl_off) desc->flags |= PROPF_WRITABLE; }else { @@ -2736,19 +2736,26 @@ static HRESULT WINAPI JSDispatchHost_ConfigureProperty(IWineJSDispatchHost *ifac return S_OK; }
-static HRESULT WINAPI JSDispatchHost_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DWORD flags, +static HRESULT WINAPI JSDispatchHost_CallFunction(IWineJSDispatchHost *iface, DISPID id, INT32 iid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { DispatchEx *This = impl_from_IWineJSDispatchHost(iface); func_info_t *func; HRESULT hres;
- TRACE("%s (%p)->(%lx %x %lx %p %p %p %p)\n", This->info->name, This, id, iid, flags, dp, ret, ei, caller); + TRACE("%s (%p)->(%lx %d %lx %p %p %p %p)\n", This->info->name, This, id, iid, flags, dp, ret, ei, caller);
hres = get_builtin_func(This->info, id, &func); - if(FAILED(hres) || func->tid != iid) + if(FAILED(hres)) return E_UNEXPECTED;
+ if(iid <= 0) { + if(func->tid != -iid) + return E_UNEXPECTED; + }else if(iid != func->prototype_id) { + return E_UNEXPECTED; + } + switch(flags) { case DISPATCH_METHOD: assert(func->func_disp_idx >= 0); diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index 79cf3a48898..7e3813672ce 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3479,8 +3479,8 @@ static HRESULT WINAPI WindowDispEx_ConfigureProperty(IWineJSDispatchHost *iface, return IWineJSDispatchHost_ConfigureProperty(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, id, flags); }
-static HRESULT WINAPI WindowDispEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, UINT32 iid, DWORD flags, DISPPARAMS *dp, - VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) +static HRESULT WINAPI WindowDispEx_CallFunction(IWineJSDispatchHost *iface, DISPID id, INT32 iid, DWORD flags, + DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 17ba2d2fba2..c4d65685d2f 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3146,6 +3146,13 @@ sync_test("__proto__", function() { ok(e.number === 0xa13b6 - 0x80000000 && e.name === "TypeError", "changing __proto__ on non-extensible object threw exception " + e.number + " (" + e.name + ")"); } + + obj = document.createElement("img"); + obj.__proto__ = ctor.prototype; + document.body.setAttribute.call(obj, "height", "101"); + r = document.body.getAttribute.call(obj, "height"); + ok(r === "101", "getAttribute(height) = " + r); + ok(!("getAttribute" in obj), "getAttribute exposed in obj"); });
sync_test("__defineGetter__", function() { @@ -3765,6 +3772,13 @@ sync_test("prototypes", function() { check(Attr.prototype, Node.prototype, "attr prototype"); check(document.createDocumentFragment(), DocumentFragment.prototype, "fragment"); check(DocumentFragment.prototype, Node.prototype, "fragment prototype"); + + try { + HTMLAreaElement.prototype.toString.call(document.createElement("a")); + ok(false, "Area element's toString on Anchor element didn't fail"); + } catch(e) { + ok(e.number == 0xffff - 0x80000000, "Area element's toString on Anchor element threw exception " + e.number); + } });
sync_test("prototype props", function() {
Jacek Caban (@jacek) commented about dlls/mshtml/htmlwindow.c:
This looks very ad-hoc. I created !7852 with an alternative version and various other clean ups.
On Fri Apr 18 12:57:55 2025 +0000, Jacek Caban wrote:
This looks very ad-hoc. I created !7852 with an alternative version and various other clean ups.
Ah right, I was under the impression that this way it would create a different object prototype, but I forgot constructor_id is the only thing that matters there and it can be shared with same object.