-- v6: mshtml: Validate builtin host functions in IE9+ using prototype_id rather mshtml: Store the object_id of the last object in the prototype chain that 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.
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 375f9be5402..518d009db41 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -3052,26 +3052,26 @@ HRESULT get_prototype(HTMLInnerWindow *script_global, object_id_t id, DispatchEx return S_OK; }
-struct constructor +struct stub_constructor { DispatchEx dispex; object_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; @@ -3094,21 +3094,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, };
@@ -3127,14 +3127,14 @@ HRESULT get_constructor(HTMLInnerWindow *script_global, object_id_t id, Dispatch 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 | 72 ++++++-------------------------- dlls/mshtml/htmlselect.c | 72 ++++++-------------------------- dlls/mshtml/mshtml_private.h | 31 +++++++------- dlls/mshtml/mutation.c | 39 +++--------------- dlls/mshtml/xmlhttprequest.c | 79 ++++++------------------------------ 6 files changed, 96 insertions(+), 240 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 518d009db41..6a4ca42ba5b 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -3052,6 +3052,31 @@ HRESULT get_prototype(HTMLInnerWindow *script_global, object_id_t id, DispatchEx 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; @@ -3122,10 +3147,20 @@ HRESULT get_constructor(HTMLInnerWindow *script_global, object_id_t id, Dispatch }
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 942cf885cc4..f5097f74b2a 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,35 +842,17 @@ 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 *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, &Image_dispex, window, - dispex_compat_mode(&window->event_target.dispex)); - - *ret_val = &ret->dispex; - return S_OK; -} - dispex_static_data_t Image_dispex = { .name = "Function", .constructor_id = OBJID_HTMLImageElement, - .init_constructor = HTMLImageElementFactory_Create, + .constructor_info = &Image_dispex, + .constructor_vtbl = &HTMLImageElementFactoryVtbl, .vtbl = &HTMLImageElementFactory_dispex_vtbl, .disp_tid = IHTMLImageElementFactory_tid, .init_info = HTMLImageElementFactory_init_dispex_info, diff --git a/dlls/mshtml/htmlselect.c b/dlls/mshtml/htmlselect.c index 29875d91d7e..f5f7a2a5b54 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,35 +488,17 @@ static void HTMLOptionElementFactory_init_dispex_info(dispex_data_t *info, compa
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 *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, &Option_dispex, window, - dispex_compat_mode(&window->event_target.dispex)); - - *ret_ptr = &ret->dispex; - return S_OK; -} - dispex_static_data_t Option_dispex = { .name = "Function", .constructor_id = OBJID_HTMLOptionElement, - .init_constructor = HTMLOptionElementFactory_Create, + .constructor_info = &Option_dispex, + .constructor_vtbl = &HTMLOptionElementFactoryVtbl, .vtbl = &HTMLOptionElementFactory_dispex_vtbl, .disp_tid = IHTMLOptionElementFactory_tid, .init_info = HTMLOptionElementFactory_init_dispex_info, diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index cf8c2a5162b..b72e172979f 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -520,7 +520,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; @@ -657,6 +658,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, @@ -677,20 +692,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 91cc61b6191..0ff31056fda 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 = OBJID_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 = OBJID_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 109ef990f67..aeaafcbe829 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); @@ -1490,9 +1483,9 @@ static const event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = { };
/* 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, @@ -1500,7 +1493,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; @@ -1577,50 +1570,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;
@@ -1631,7 +1594,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;
@@ -1642,9 +1605,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 };
@@ -1660,32 +1623,14 @@ static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = { .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; -} - static const tid_t HTMLXMLHttpRequest_iface_tids[] = { IHTMLXMLHttpRequest2_tid, 0 }; dispex_static_data_t XMLHttpRequest_dispex = { .id = OBJID_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,
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 6a4ca42ba5b..5fbdee27728 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) +{ + object_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 55df3d746e4..2f432d2e3e3 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 5fbdee27728..be86fc24506 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; + object_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 object_id_t find_prototype_member(const dispex_data_t *info, DISPID id) { compat_mode_t compat_mode = info->compat_mode; + object_id_t ret = OBJID_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 != OBJID_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 == OBJID_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 be86fc24506..f7169d37d81 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 c8c0c7c1ea6..ef43b1824a5 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 2f432d2e3e3..8c75e13d784 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/jscript/function.c:
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);
This hardcodes "create" in several places across all layers, except for the XHR constructor, where the logic arguably belongs. Instead of passing "method" to `InitHostConstructor`, maybe we could pass the method’s name (or NULL for actual constructors) and use that here instead.
Jacek Caban (@jacek) commented about dlls/jscript/function.c:
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));
This could be done in MSHTML.
Jacek Caban (@jacek) commented about dlls/mshtml/tests/documentmode.js:
} 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");
It would be good to add a test showing that it's an actual function, for example using `typeof()`.
Jacek Caban (@jacek) commented about dlls/mshtml/dispex.c:
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);
This is a very specific case, and a special case like this doesn’t really belong in the generic code here. `HTMLXMLHttpRequestFactory_Create` seems like the logical place to handle it instead. That makes me think removing the `init_constructor` logic earlier might not be the right call after all.
On Tue Apr 22 23:01:04 2025 +0000, Jacek Caban wrote:
This is a very specific case, and a special case like this doesn’t really belong in the generic code here. `HTMLXMLHttpRequestFactory_Create` seems like the logical place to handle it instead. That makes me think removing the `init_constructor` logic earlier might not be the right call after all.
Yeah maybe I can keep `init_constructor` to just initialize the dispatch in most cases (except for this), which makes more sense from the name too.
On Tue Apr 22 23:01:03 2025 +0000, Jacek Caban wrote:
This could be done in MSHTML.
How do I make it non-enumerable from mshtml? If I use fdexNameEnsure it makes it enumerable. Should I add a new wine-specific method to the interface?
On Tue Apr 22 23:01:03 2025 +0000, Jacek Caban wrote:
This hardcodes "create" in several places across all layers, except for the XHR constructor, where the logic arguably belongs. Instead of passing "method" to `InitHostConstructor`, maybe we could pass the method’s name (or NULL for actual constructors) and use that here instead.
Yeah I considered that at first too, but I realized I couldn't add non-enumerable prop without a new method. If you're fine with that or have another way I'll be happy to switch.
On Wed Apr 23 14:50:28 2025 +0000, Gabriel Ivăncescu wrote:
How do I make it non-enumerable from mshtml? If I use fdexNameEnsure it makes it enumerable. Should I add a new wine-specific method to the interface?
Oh, right, there is that. Something like `IWineJSDispatch::DefineProperty(struct property_info *desc, VARIANT *v)` seems reasonable to me.
This MR is getting a bit mixed. In the last patch, I was hoping we could also avoid negative values for iids, but let’s leave that for a separate MR.
On Wed Apr 23 20:05:58 2025 +0000, Jacek Caban wrote:
This MR is getting a bit mixed. In the last patch, I was hoping we could also avoid negative values for iids, but let’s leave that for a separate MR.
Those are only used for the legacy function objects, should I make a separate method for them instead? (in the follow up MR)
I mean instead of reusing `CallFunction`.