From: Gabriel Ivăncescu gabrielopcode@gmail.com
Previously, the first prototype was simply skipped, since prototype_id would point to the *second* prototype (first one is implicitly assumed to be the object's dispex).
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index 77eec049912..7e85d41b4fd 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1375,6 +1375,11 @@ HRESULT dispex_get_chain_builtin_id(DispatchEx *dispex, const WCHAR *name, DWORD
assert(compat_mode >= COMPAT_MODE_IE9);
+ hres = get_builtin_id(info, name, flags, pid); + if(hres != DISP_E_UNKNOWNNAME) + return hres; + info = info->desc->prototype_info[compat_mode - COMPAT_MODE_IE9]; + for(;;) { hres = get_builtin_id(info, name, flags, pid); if(hres != DISP_E_UNKNOWNNAME)
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/dispex.c | 6 +++--- dlls/jscript/function.c | 6 +++--- dlls/jscript/jsdisp.idl | 4 ++-- dlls/mshtml/dispex.c | 34 +++++++++++++++++++++---------- dlls/mshtml/htmldoc.c | 2 +- dlls/mshtml/htmlstorage.c | 2 +- dlls/mshtml/htmlwindow.c | 8 ++++---- dlls/mshtml/pluginhost.c | 2 +- dlls/mshtml/tests/documentmode.js | 14 +++++++++++++ 9 files changed, 52 insertions(+), 26 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index d5ed3adf4fb..98cd608cab0 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -275,7 +275,7 @@ static HRESULT update_external_prop(jsdisp_t *obj, const WCHAR *name, dispex_pro if(desc->name) name = desc->name;
- if(!desc->iid) { + if(!desc->prototype_id) { if(!prop && !(prop = alloc_prop(obj, name, PROP_DELETED, 0))) return E_OUTOFMEMORY; prop->type = PROP_EXTERN; @@ -497,7 +497,7 @@ HRESULT jsdisp_index_lookup(jsdisp_t *obj, const WCHAR *name, unsigned length, s desc->flags |= PROPF_WRITABLE; desc->name = NULL; desc->index = idx; - desc->iid = 0; + desc->prototype_id = 0; return S_OK; }
@@ -512,7 +512,7 @@ HRESULT jsdisp_next_index(jsdisp_t *obj, unsigned length, unsigned id, struct pr desc->flags |= PROPF_WRITABLE; desc->name = NULL; desc->index = desc->id; - desc->iid = 0; + desc->prototype_id = 0; return S_OK; }
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 9f1f53a96ae..a7132e9ab6a 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 prototype_id; UINT32 flags; } HostFunction;
@@ -1023,7 +1023,7 @@ static HRESULT HostFunction_call(script_ctx_t *ctx, FunctionInstance *func, jsva
if(SUCCEEDED(hres)) { V_VT(&retv) = VT_EMPTY; - hres = IWineJSDispatchHost_CallFunction(obj, function->id, function->iid, function->flags, &dp, + hres = IWineJSDispatchHost_CallFunction(obj, function->id, function->prototype_id, function->flags, &dp, r ? &retv : NULL, &ei, &ctx->jscaller->IServiceProvider_iface); if(hres == DISP_E_EXCEPTION) handle_dispatch_exception(ctx, &ei); @@ -1084,7 +1084,7 @@ HRESULT create_host_function(script_ctx_t *ctx, const struct property_info *desc
function->name = desc->name; function->id = desc->id; - function->iid = desc->iid; + function->prototype_id = desc->prototype_id; function->flags = flags; *ret = &function->function.dispex; return S_OK; diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index 5f1384bce78..ce1d71bab6a 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 prototype_id; };
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 prototype_id, 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 7e85d41b4fd..c411cef0c9c 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -1075,7 +1075,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--) @@ -1102,7 +1102,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; } @@ -1179,7 +1179,7 @@ static HRESULT function_get_prop_desc(DispatchEx *dispex, DISPID id, struct prop desc->id = id; desc->flags = 0; desc->name = function_props[idx].name; - desc->iid = 0; + desc->prototype_id = 0; return S_OK; }
@@ -2578,7 +2578,7 @@ HRESULT dispex_index_prop_desc(DispatchEx *dispex, DISPID id, struct property_in desc->flags |= PROPF_ENUMERABLE; desc->name = NULL; desc->index = id - MSHTML_DISPID_CUSTOM_MIN; - desc->iid = 0; + desc->prototype_id = 0; return S_OK; }
@@ -2598,18 +2598,18 @@ 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->prototype_id = This->info->desc->id ? This->info->desc->id : -func->tid; 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->prototype_id = This->info->desc->id ? This->info->desc->id : -func->tid; if(func->put_vtbl_off) desc->flags |= PROPF_WRITABLE; }else { desc->flags |= PROPF_WRITABLE; - desc->iid = 0; + desc->prototype_id = 0; } } break; @@ -2618,7 +2618,7 @@ static HRESULT get_host_property_descriptor(DispatchEx *This, DISPID id, struct dynamic_prop_t *prop = &This->dynamic_data->props[id - DISPID_DYNPROP_0]; desc->flags = prop->flags & PROPF_PUBLIC_MASK; desc->name = prop->name; - desc->iid = 0; + desc->prototype_id = 0; break; } case DISPEXPROP_CUSTOM: @@ -2705,19 +2705,31 @@ 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 prototype_id, DWORD flags, DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { DispatchEx *This = impl_from_IWineJSDispatchHost(iface); + dispex_static_data_t *desc = This->info->desc; 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, prototype_id, 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(prototype_id <= 0) { + if(func->tid != -prototype_id) + return E_UNEXPECTED; + }else if(prototype_id != desc->id) { + while(prototype_id != desc->prototype_id) { + if(!desc->prototype_id) + return E_UNEXPECTED; + desc = object_descriptors[desc->prototype_id]; + } + } + switch(flags) { case DISPATCH_METHOD: assert(func->func_disp_idx >= 0); diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index ffd594291f3..056d6cbacf6 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -5528,7 +5528,7 @@ static HRESULT HTMLDocumentNode_get_prop_desc(DispatchEx *dispex, DISPID id, str desc->name = This->elem_vars[idx]; desc->id = id; desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE | PROPF_ENUMERABLE; - desc->iid = 0; + desc->prototype_id = 0; return S_OK; }
diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index 98c1202e315..263e2479a82 100644 --- a/dlls/mshtml/htmlstorage.c +++ b/dlls/mshtml/htmlstorage.c @@ -1273,7 +1273,7 @@ static HRESULT HTMLStorage_get_prop_desc(DispatchEx *dispex, DISPID id, struct p desc->name = This->props[id - MSHTML_DISPID_CUSTOM_MIN]; desc->id = id; desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE | PROPF_ENUMERABLE; - desc->iid = 0; + desc->prototype_id = 0; return S_OK; }
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index ffcaf86a361..fbfa821955e 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -3491,13 +3491,13 @@ 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 prototype_id, DWORD flags, + DISPPARAMS *dp, VARIANT *ret, EXCEPINFO *ei, IServiceProvider *caller) { HTMLOuterWindow *This = impl_from_IWineJSDispatchHost(iface);
return IWineJSDispatchHost_CallFunction(&This->base.inner_window->event_target.dispex.IWineJSDispatchHost_iface, - id, iid, flags, dp, ret, ei, caller); + id, prototype_id, flags, dp, ret, ei, caller); }
static HRESULT WINAPI WindowDispEx_Construct(IWineJSDispatchHost *iface, LCID lcid, DWORD flags, DISPPARAMS *dp, VARIANT *ret, @@ -4042,7 +4042,7 @@ HRESULT HTMLWindow_get_prop_desc(DispatchEx *dispex, DISPID id, struct property_ desc->name = prop->name; desc->id = id; desc->flags = PROPF_WRITABLE | PROPF_CONFIGURABLE; - desc->iid = 0; + desc->prototype_id = 0;
switch(prop->type) { case GLOBAL_SCRIPTVAR: { diff --git a/dlls/mshtml/pluginhost.c b/dlls/mshtml/pluginhost.c index c4a580ea4eb..03959266f1f 100644 --- a/dlls/mshtml/pluginhost.c +++ b/dlls/mshtml/pluginhost.c @@ -835,7 +835,7 @@ HRESULT HTMLPluginContainer_get_prop_desc(DispatchEx *dispex, DISPID id, struct desc->id = id; desc->flags = 0; desc->name = plugin_container->props[id - MSHTML_DISPID_CUSTOM_MIN]->name; - desc->iid = 0; + desc->prototype_id = 0; return S_OK; }
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 5bbd8b098f6..d304fbadd62 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3131,6 +3131,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() { @@ -3750,6 +3757,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() {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlimg.c | 4 +-- dlls/mshtml/htmlwindow.c | 60 ++++++++++++++++--------------- dlls/mshtml/mshtml_private.h | 9 +++-- dlls/mshtml/tests/documentmode.js | 16 +++++++++ 4 files changed, 56 insertions(+), 33 deletions(-)
diff --git a/dlls/mshtml/htmlimg.c b/dlls/mshtml/htmlimg.c index f6a4b992ab6..b4fd5de07b5 100644 --- a/dlls/mshtml/htmlimg.c +++ b/dlls/mshtml/htmlimg.c @@ -885,7 +885,7 @@ static dispex_static_data_t HTMLImageElementFactory_dispex = { .iface_tids = HTMLImageElementFactory_iface_tids, };
-HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow *window, HTMLImageElementFactory **ret_val) +HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow *window, DispatchEx **ret_val) { HTMLImageElementFactory *ret;
@@ -900,6 +900,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 fbfa821955e..d5facbcb73f 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -676,18 +676,13 @@ static HRESULT WINAPI HTMLWindow2_get_Image(IHTMLWindow2 *iface, IHTMLImageEleme
TRACE("(%p)->(%p)\n", This, p);
- if(!window->image_factory) { - HRESULT hres; - - hres = HTMLImageElementFactory_Create(window, &window->image_factory); + if(!window->constructors[CTOR_IMAGE]) { + HRESULT hres = HTMLImageElementFactory_Create(window, &window->constructors[CTOR_IMAGE]); if(FAILED(hres)) return hres; }
- *p = &window->image_factory->IHTMLImageElementFactory_iface; - IHTMLImageElementFactory_AddRef(*p); - - return S_OK; + return IWineJSDispatchHost_QueryInterface(&window->constructors[CTOR_IMAGE]->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; @@ -3827,23 +3815,35 @@ static HRESULT HTMLWindow_find_dispid(DispatchEx *dispex, const WCHAR *name, DWO if(dispex_compat_mode(dispex) >= COMPAT_MODE_IE9) { const WCHAR **constr_name = bsearch(&name, constructor_names, ARRAYSIZE(constructor_names) , sizeof(constructor_names[0]), cmp_name); + DispatchEx *constr = NULL; + if(constr_name) { prototype_id_t id = constr_name - constructor_names + 1; compat_mode_t compat_mode = dispex_compat_mode(dispex); - DispatchEx *constr; - VARIANT v;
if(compat_mode >= object_descriptors[id]->min_compat_mode && (!object_descriptors[id]->max_compat_mode || compat_mode <= object_descriptors[id]->max_compat_mode)) { hres = get_constructor(This, id, &constr); if(FAILED(hres)) return hres; - - V_VT(&v) = VT_DISPATCH; - V_DISPATCH(&v) = (IDispatch *)&constr->IWineJSDispatchHost_iface; - return dispex_define_property(&This->event_target.dispex, name, PROPF_WRITABLE | PROPF_CONFIGURABLE, &v, dispid); + } + }else { + if(!wcscmp(name, L"Image")) { + if(!This->constructors[CTOR_IMAGE]) { + hres = HTMLImageElementFactory_Create(This, &This->constructors[CTOR_IMAGE]); + if(FAILED(hres)) + return hres; + } + constr = This->constructors[CTOR_IMAGE]; } } + + if(constr) { + VARIANT v; + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch *)&constr->IWineJSDispatchHost_iface; + return dispex_define_property(&This->event_target.dispex, name, PROPF_WRITABLE | PROPF_CONFIGURABLE, &v, dispid); + } }
hres = get_frame_by_name(This->base.outer_window, name, FALSE, &frame); @@ -4188,15 +4188,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 +4231,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..0089a92409a 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -510,6 +510,10 @@ typedef enum { ALL_PROTOTYPES #undef X PROT_LAST, + + /* Extra constructors without new prototypes */ + CTOR_IMAGE = PROT_LAST, + CTOR_LAST } prototype_id_t;
struct dispex_static_data_t { @@ -771,7 +775,6 @@ struct HTMLInnerWindow {
IHTMLEventObj *event;
- HTMLImageElementFactory *image_factory; HTMLOptionElementFactory *option_factory; IHTMLScreen *screen; OmHistory *history; @@ -801,7 +804,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 +1173,7 @@ HRESULT update_window_doc(HTMLInnerWindow*); HTMLOuterWindow *mozwindow_to_window(const mozIDOMWindowProxy*); void get_top_window(HTMLOuterWindow*,HTMLOuterWindow**); HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow*,HTMLOptionElementFactory**); -HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,HTMLImageElementFactory**); +HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,DispatchEx**); HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,DispatchEx**); HRESULT create_location(HTMLOuterWindow*,HTMLLocation**); HRESULT create_navigator(HTMLInnerWindow*,IOmNavigator**); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index d304fbadd62..e9a2f0172d0 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3995,3 +3995,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 | 4 ++-- dlls/mshtml/htmlwindow.c | 28 ++++++++++++---------------- dlls/mshtml/mshtml_private.h | 4 ++-- dlls/mshtml/tests/documentmode.js | 3 ++- 4 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/dlls/mshtml/htmlselect.c b/dlls/mshtml/htmlselect.c index 2d02589db38..1436c959ca0 100644 --- a/dlls/mshtml/htmlselect.c +++ b/dlls/mshtml/htmlselect.c @@ -531,7 +531,7 @@ static dispex_static_data_t HTMLOptionElementFactory_dispex = { .iface_tids = HTMLOptionElementFactory_iface_tids, };
-HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, HTMLOptionElementFactory **ret_ptr) +HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, DispatchEx **ret_ptr) { HTMLOptionElementFactory *ret;
@@ -546,7 +546,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 d5facbcb73f..e06e44a81e6 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -1229,18 +1229,13 @@ static HRESULT WINAPI HTMLWindow2_get_Option(IHTMLWindow2 *iface, IHTMLOptionEle
TRACE("(%p)->(%p)\n", This, p);
- if(!window->option_factory) { - HRESULT hres; - - hres = HTMLOptionElementFactory_Create(window, &window->option_factory); + if(!window->constructors[CTOR_OPTION]) { + HRESULT hres = HTMLOptionElementFactory_Create(window, &window->constructors[CTOR_OPTION]); if(FAILED(hres)) return hres; }
- *p = &window->option_factory->IHTMLOptionElementFactory_iface; - IHTMLOptionElementFactory_AddRef(*p); - - return S_OK; + return IWineJSDispatchHost_QueryInterface(&window->constructors[CTOR_OPTION]->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; @@ -3835,6 +3823,13 @@ static HRESULT HTMLWindow_find_dispid(DispatchEx *dispex, const WCHAR *name, DWO return hres; } constr = This->constructors[CTOR_IMAGE]; + }else if(!wcscmp(name, L"Option")) { + if(!This->constructors[CTOR_OPTION]) { + hres = HTMLOptionElementFactory_Create(This, &This->constructors[CTOR_OPTION]); + if(FAILED(hres)) + return hres; + } + constr = This->constructors[CTOR_OPTION]; } }
@@ -4193,13 +4188,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 0089a92409a..0f88d5a12aa 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -513,6 +513,7 @@ typedef enum {
/* Extra constructors without new prototypes */ CTOR_IMAGE = PROT_LAST, + CTOR_OPTION, CTOR_LAST } prototype_id_t;
@@ -775,7 +776,6 @@ struct HTMLInnerWindow {
IHTMLEventObj *event;
- HTMLOptionElementFactory *option_factory; IHTMLScreen *screen; OmHistory *history; IOmNavigator *navigator; @@ -1172,7 +1172,7 @@ 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 HTMLOptionElementFactory_Create(HTMLInnerWindow*,DispatchEx**); HRESULT HTMLImageElementFactory_Create(HTMLInnerWindow*,DispatchEx**); HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow*,DispatchEx**); HRESULT create_location(HTMLOuterWindow*,HTMLLocation**); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index e9a2f0172d0..7b0152a6ecd 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -4001,7 +4001,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)) @@ -4010,4 +4010,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"); });
Jacek Caban (@jacek) commented about dlls/mshtml/dispex.c:
assert(compat_mode >= COMPAT_MODE_IE9);
- hres = get_builtin_id(info, name, flags, pid);
- if(hres != DISP_E_UNKNOWNNAME)
return hres;
- info = info->desc->prototype_info[compat_mode - COMPAT_MODE_IE9];
Please add a test case.
Jacek Caban (@jacek) commented about dlls/mshtml/dispex.c:
desc->flags = PROPF_CONFIGURABLE; desc->name = func->name; if(func->func_disp_idx >= 0) {
desc->iid = func->tid;
desc->prototype_id = This->info->desc->id ? This->info->desc->id : -func->tid;
Given that it's not always about prototypes, I'm not sure we want to rename it to `prototype_id`.
What are the cases that still don't have id? You introduce ids for constructors later in the series, so we could just as well use them. Other than that there is the location object, is there anything else? I wonder if we can just ensure that every relevant object has an id instead.
Jacek Caban (@jacek) commented about dlls/mshtml/htmlwindow.c:
if(FAILED(hres)) return hres;
V_VT(&v) = VT_DISPATCH;
V_DISPATCH(&v) = (IDispatch *)&constr->IWineJSDispatchHost_iface;
return dispex_define_property(&This->event_target.dispex, name, PROPF_WRITABLE | PROPF_CONFIGURABLE, &v, dispid);
}
}else {
if(!wcscmp(name, L"Image")) {
if(!This->constructors[CTOR_IMAGE]) {
hres = HTMLImageElementFactory_Create(This, &This->constructors[CTOR_IMAGE]);
if(FAILED(hres))
return hres;
}
constr = This->constructors[CTOR_IMAGE]; }
Could we extend `init_constructor` mechanism instead?
On Thu Apr 10 13:05:15 2025 +0000, Jacek Caban wrote:
Given that it's not always about prototypes, I'm not sure we want to rename it to `prototype_id`. What are the cases that still don't have id? You introduce ids for constructors later in the series, so we could just as well use them. Other than that there is the location object, is there anything else? I wonder if we can just ensure that every relevant object has an id instead.
I don't think location object should be an issue, since it's always initialized with COMPAT_MODE_QUIRKS (as it's tied to outer window, it's never a jsdisp), and this code path is only for IE9+ jsdisps. But I thought id was used to lookup the (cached) prototype? (in `get_prototype` from `ensure_real_info`)
In this case, constructors (those of `constructor_dispex`) don't have an `id` field. e.g. window.HTMLElement constructor has no id, but a HTMLElement object does. Even if we separate the constructors each to have their own dispex and id, `ensure_real_info` would cache it wrong, no?
In this case, constructors (those of `constructor_dispex`) don't have an `id` field. e.g. window.HTMLElement constructor has no id, but a HTMLElement object does.
They also don't have builtin properties, so why is it a problem?
On Thu Apr 10 15:50:00 2025 +0000, Jacek Caban wrote:
In this case, constructors (those of `constructor_dispex`) don't have
an `id` field. e.g. window.HTMLElement constructor has no id, but a HTMLElement object does. They also don't have builtin properties, so why is it a problem?
Ah right, I guess I was being overly cautious with it.
On Thu Apr 10 13:05:15 2025 +0000, Jacek Caban wrote:
Please add a test case.
I thought it was an obvious oversight—attempting to write a test revealed a lot of issues with removeAttribute compared to native (which is the only place it's called from right now), so I guess I'll just drop this patch for now as I don't plan on working on that.
I did plan to use it in other places later, so I'll probably move it there.