This get us pass the "Update your browser" blocker in adobe's sign-in page. The page itself doesn't make use of `window.MutationObserver`.
However the sign-in page is still broken.
-- v17: mshtml: add stubs for MutationObserver methods mshtml: implement window.MutationObserver with MutationObserver stub
From: Yuxuan Shui yshui@codeweavers.com
--- dlls/mshtml/htmlwindow.c | 33 ++- dlls/mshtml/mshtml_private.h | 6 +- dlls/mshtml/mshtml_private_iface.idl | 14 ++ dlls/mshtml/mutation.c | 292 +++++++++++++++++++++++++++ dlls/mshtml/tests/documentmode.js | 58 ++++++ 5 files changed, 401 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c index c6072c7e9fa..b1d423e8e34 100644 --- a/dlls/mshtml/htmlwindow.c +++ b/dlls/mshtml/htmlwindow.c @@ -309,6 +309,9 @@ static void release_inner_window(HTMLInnerWindow *This) if(This->mon) IMoniker_Release(This->mon);
+ if(This->mutation_observer_ctor) + IDispatch_Release(This->mutation_observer_ctor); + free(This); }
@@ -3330,6 +3333,26 @@ static HRESULT WINAPI window_private_get_console(IWineHTMLWindowPrivate *iface, return S_OK; }
+static HRESULT WINAPI window_private_get_MutationObserver(IWineHTMLWindowPrivate *iface, + IDispatch **mutation_observer) +{ + HTMLWindow *This = impl_from_IWineHTMLWindowPrivateVtbl(iface); + HRESULT hres; + + FIXME("iface %p, mutation_observer %p, stub.\n", iface, mutation_observer); + + if (!This->inner_window->mutation_observer_ctor) { + hres = create_mutation_observer_ctor(dispex_compat_mode(&This->inner_window->event_target.dispex), + &This->inner_window->mutation_observer_ctor); + if (FAILED(hres)) + return hres; + } + + IDispatch_AddRef(This->inner_window->mutation_observer_ctor); + *mutation_observer = This->inner_window->mutation_observer_ctor; + return S_OK; +} + static const IWineHTMLWindowPrivateVtbl WineHTMLWindowPrivateVtbl = { window_private_QueryInterface, window_private_AddRef, @@ -3343,6 +3366,7 @@ static const IWineHTMLWindowPrivateVtbl WineHTMLWindowPrivateVtbl = { window_private_get_console, window_private_matchMedia, window_private_postMessage, + window_private_get_MutationObserver };
static inline HTMLWindow *impl_from_IWineHTMLWindowCompatPrivateVtbl(IWineHTMLWindowCompatPrivate *iface) @@ -3975,12 +3999,19 @@ static void HTMLWindow_init_dispex_info(dispex_data_t *info, compat_mode_t compa {DISPID_UNKNOWN} };
+ /* Hide props not available in IE10 */ + static const dispex_hook_t private_ie10_hooks[] = { + {DISPID_IWINEHTMLWINDOWPRIVATE_MUTATIONOBSERVER}, + {DISPID_UNKNOWN} + }; + if(compat_mode >= COMPAT_MODE_IE9) dispex_info_add_interface(info, IHTMLWindow7_tid, NULL); else dispex_info_add_interface(info, IWineHTMLWindowCompatPrivate_tid, NULL); if(compat_mode >= COMPAT_MODE_IE10) - dispex_info_add_interface(info, IWineHTMLWindowPrivate_tid, NULL); + dispex_info_add_interface(info, IWineHTMLWindowPrivate_tid, + compat_mode >= COMPAT_MODE_IE11 ? NULL : private_ie10_hooks);
dispex_info_add_interface(info, IHTMLWindow5_tid, NULL); dispex_info_add_interface(info, IHTMLWindow4_tid, compat_mode >= COMPAT_MODE_IE11 ? window4_ie11_hooks : NULL); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 59d652a828b..ffd179f1124 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -294,7 +294,8 @@ typedef struct EventTarget EventTarget; XIID(IWinePageTransitionEvent) \ XIID(IWineXMLHttpRequestPrivate) \ XIID(IWineMSHTMLConsole) \ - XIID(IWineMSHTMLMediaQueryList) + XIID(IWineMSHTMLMediaQueryList) \ + XIID(IWineMSHTMLMutationObserver)
typedef enum { #define XIID(iface) iface ## _tid, @@ -619,6 +620,7 @@ struct HTMLInnerWindow { LONG task_magic;
IMoniker *mon; + IDispatch *mutation_observer_ctor; nsChannelBSC *bscallback; struct list bindings; }; @@ -1479,3 +1481,5 @@ IInternetSecurityManager *get_security_manager(void); extern HINSTANCE hInst; void create_console(compat_mode_t compat_mode, IWineMSHTMLConsole **ret); HRESULT create_media_query_list(HTMLWindow *window, BSTR media_query, IDispatch **ret); + +HRESULT create_mutation_observer_ctor(compat_mode_t compat_mode, IDispatch **ret); diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl index c0bb30fbbc8..46bae638fa5 100644 --- a/dlls/mshtml/mshtml_private_iface.idl +++ b/dlls/mshtml/mshtml_private_iface.idl @@ -76,6 +76,17 @@ interface IWineMSHTMLConsole : IDispatch HRESULT warn([in, optional] VARIANT *varargStart); }
+[ + odl, + oleautomation, + dual, + hidden, + uuid(6ac5491e-1758-4b82-98a2-83e31a7c8871) +] +interface IWineMSHTMLMutationObserver : IDispatch +{ +} + [ odl, oleautomation, @@ -95,6 +106,7 @@ interface IWineMSHTMLMediaQueryList : IDispatch HRESULT removeListener([in] VARIANT *listener); }
+const long DISPID_IWINEHTMLWINDOWPRIVATE_MUTATIONOBSERVER = 55; [ odl, oleautomation, @@ -114,6 +126,8 @@ interface IWineHTMLWindowPrivate : IDispatch HRESULT matchMedia([in] BSTR media_query, [retval, out] IDispatch **media_query_list); [id(54)] HRESULT postMessage([in] VARIANT msg, [in] BSTR targetOrigin, [in, optional] VARIANT transfer); + [propget, id(DISPID_IWINEHTMLWINDOWPRIVATE_MUTATIONOBSERVER)] + HRESULT MutationObserver([retval, out] IDispatch **observer_ctor); }
[ diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 83ab623aea8..cbd54a8c151 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -1076,3 +1076,295 @@ void init_mutation(nsIComponentManager *component_manager) if(NS_FAILED(nsres)) ERR("Could not create nsIContentUtils instance: %08lx\n", nsres); } + +struct mutation_observer { + IWineMSHTMLMutationObserver IWineMSHTMLMutationObserver_iface; + + LONG ref; + DispatchEx dispex; + IDispatch *callback; +}; + +static inline struct mutation_observer *impl_from_IWineMSHTMLMutationObserver(IWineMSHTMLMutationObserver *iface) +{ + return CONTAINING_RECORD(iface, struct mutation_observer, IWineMSHTMLMutationObserver_iface); +} + +static HRESULT WINAPI MutationObserver_QueryInterface(IWineMSHTMLMutationObserver *iface, REFIID riid, void **ppv) +{ + struct mutation_observer *This = impl_from_IWineMSHTMLMutationObserver(iface); + + TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IWineMSHTMLMutationObserver, riid)) { + *ppv = &This->IWineMSHTMLMutationObserver_iface; + }else { + WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI MutationObserver_AddRef(IWineMSHTMLMutationObserver *iface) +{ + struct mutation_observer *This = impl_from_IWineMSHTMLMutationObserver(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; +} + +static ULONG WINAPI MutationObserver_Release(IWineMSHTMLMutationObserver *iface) +{ + struct mutation_observer *This = impl_from_IWineMSHTMLMutationObserver(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if(!ref) { + release_dispex(&This->dispex); + IDispatch_Release(This->callback); + This->callback = NULL; + free(This); + } + + return ref; +} + +static HRESULT WINAPI MutationObserver_GetTypeInfoCount(IWineMSHTMLMutationObserver *iface, UINT *pctinfo) +{ + struct mutation_observer *This = impl_from_IWineMSHTMLMutationObserver(iface); + FIXME("(%p)->(%p)\n", This, pctinfo); + + return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); +} + +static HRESULT WINAPI MutationObserver_GetTypeInfo(IWineMSHTMLMutationObserver *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + struct mutation_observer *This = impl_from_IWineMSHTMLMutationObserver(iface); + + return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); +} + +static HRESULT WINAPI MutationObserver_GetIDsOfNames(IWineMSHTMLMutationObserver *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, + DISPID *rgDispId) +{ + struct mutation_observer *This = impl_from_IWineMSHTMLMutationObserver(iface); + + return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames, lcid, + rgDispId); +} + +static HRESULT WINAPI MutationObserver_Invoke(IWineMSHTMLMutationObserver *iface, DISPID dispIdMember, + REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, + VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + struct mutation_observer *This = impl_from_IWineMSHTMLMutationObserver(iface); + + return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags, + pDispParams, pVarResult, pExcepInfo, puArgErr); +} + +static const IWineMSHTMLMutationObserverVtbl WineMSHTMLMutationObserverVtbl = { + MutationObserver_QueryInterface, + MutationObserver_AddRef, + MutationObserver_Release, + MutationObserver_GetTypeInfoCount, + MutationObserver_GetTypeInfo, + MutationObserver_GetIDsOfNames, + MutationObserver_Invoke, +}; + +static const tid_t mutation_observer_iface_tids[] = { + IWineMSHTMLMutationObserver_tid, + 0 +}; +static dispex_static_data_t mutation_observer_dispex = { + L"MutationObserver", + NULL, + IWineMSHTMLMutationObserver_tid, + mutation_observer_iface_tids +}; + +static HRESULT create_mutation_observer(compat_mode_t compat_mode, IDispatch *callback, + IWineMSHTMLMutationObserver **ret) { + struct mutation_observer *obj; + + TRACE("(compat_mode = %d, callback = %p, ret = %p)\n", compat_mode, callback, ret); + + obj = calloc(1, sizeof(*obj)); + if(!obj) + { + ERR("No memory.\n"); + return E_OUTOFMEMORY; + } + + obj->IWineMSHTMLMutationObserver_iface.lpVtbl = &WineMSHTMLMutationObserverVtbl; + obj->ref = 1; + init_dispatch(&obj->dispex, (IUnknown*)&obj->IWineMSHTMLMutationObserver_iface.lpVtbl, + &mutation_observer_dispex, compat_mode); + + IDispatch_AddRef(callback); + obj->callback = callback; + *ret = &obj->IWineMSHTMLMutationObserver_iface; + return S_OK; +} + +struct mutation_observer_ctor { + IUnknown IUnknown_iface; + DispatchEx dispex; + + LONG ref; +}; + +static inline struct mutation_observer_ctor *mutation_observer_ctor_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct mutation_observer_ctor, IUnknown_iface); +} + +static inline struct mutation_observer_ctor *mutation_observer_ctor_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, struct mutation_observer_ctor, dispex); +} + +static HRESULT WINAPI mutation_observer_ctor_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + struct mutation_observer_ctor *This = mutation_observer_ctor_from_IUnknown(iface); + + TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); + + if(IsEqualGUID(&IID_IUnknown, riid)) { + *ppv = &This->IUnknown_iface; + }else if(dispex_query_interface(&This->dispex, riid, ppv)) { + return *ppv ? S_OK : E_NOINTERFACE; + }else { + WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI mutation_observer_ctor_AddRef(IUnknown *iface) +{ + struct mutation_observer_ctor *This = mutation_observer_ctor_from_IUnknown(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; +} + +static ULONG WINAPI mutation_observer_ctor_Release(IUnknown *iface) +{ + struct mutation_observer_ctor *This = mutation_observer_ctor_from_IUnknown(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if(!ref) { + release_dispex(&This->dispex); + free(This); + } + + return ref; +} + +static const IUnknownVtbl mutation_observer_ctor_vtbl = { + mutation_observer_ctor_QueryInterface, + mutation_observer_ctor_AddRef, + mutation_observer_ctor_Release, +}; + +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); + VARIANT *callback; + IWineMSHTMLMutationObserver *mutation_observer; + HRESULT hres; + int argc = params->cArgs - params->cNamedArgs; + + TRACE("(%p)->(%lx %x %p %p %p %p)\n", This, lcid, flags, params, res, ei, caller); + + if (argc < 1) + return E_UNEXPECTED; + + callback = params->rgvarg + (params->cArgs - 1); + if (V_VT(callback) != VT_DISPATCH) { + FIXME("Should return TypeMismatchError\n"); + return E_FAIL; + } + + switch (flags) { + case DISPATCH_CONSTRUCT: + case DISPATCH_METHOD: + case DISPATCH_METHOD | DISPATCH_PROPERTYGET: + break; + default: + FIXME("flags %x is not supported\n", flags); + return E_NOTIMPL; + } + + if (!res) { + /* This function has no side effects if the return value is dropped. */ + return S_OK; + } + + V_VT(res) = VT_NULL; + + hres = create_mutation_observer(dispex_compat_mode(&This->dispex), V_DISPATCH(callback), + &mutation_observer); + if (FAILED(hres)) + return hres; + + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = (IDispatch*)mutation_observer; + + return S_OK; +} + +static dispex_static_data_vtbl_t mutation_observer_ctor_dispex_vtbl = { + .value = mutation_observer_ctor_value +}; + +static const tid_t mutation_observer_ctor_iface_tids[] = { + 0 +}; + +static dispex_static_data_t mutation_observer_ctor_dispex = { + L"Function", + &mutation_observer_ctor_dispex_vtbl, + NULL_tid, + mutation_observer_ctor_iface_tids +}; + +HRESULT create_mutation_observer_ctor(compat_mode_t compat_mode, IDispatch **ret) { + struct mutation_observer_ctor *obj; + + TRACE("(compat_mode = %d, ret = %p)\n", compat_mode, ret); + + obj = calloc(1, sizeof(*obj)); + if(!obj) + { + ERR("No memory.\n"); + return E_OUTOFMEMORY; + } + + obj->IUnknown_iface.lpVtbl = &mutation_observer_ctor_vtbl; + obj->ref = 1; + init_dispatch(&obj->dispex, (IUnknown*)&obj->IUnknown_iface.lpVtbl, + &mutation_observer_ctor_dispex, compat_mode); + + *ret = (IDispatch *)&obj->dispex.IDispatchEx_iface; + return S_OK; +} diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 00a6eded3fe..35921ca565f 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -343,6 +343,9 @@ sync_test("builtin_toString", function() { test("console", window.console, "Console"); test("mediaQueryList", window.matchMedia("(hover:hover)"), "MediaQueryList"); } + if(v >= 11) { + test("MutationObserver", new window.MutationObserver(function() {}), "MutationObserver"); + } if(v >= 9) { document.body.innerHTML = "<!--...-->"; test("comment", document.body.firstChild, "Comment"); @@ -475,6 +478,7 @@ sync_test("window_props", function() { test_exposed("performance", true); test_exposed("console", v >= 10); test_exposed("matchMedia", v >= 10); + test_exposed("MutationObserver", v >= 11); });
sync_test("domimpl_props", function() { @@ -2853,6 +2857,60 @@ sync_test("__defineSetter__", function() { ok(x.setterVal === 9, "x.setterVal after setting bar = " + x.setterVal); });
+sync_test("MutationObserver", function() { + if (!window.MutationObserver) { + return; + } + + try { + window.MutationObserver(); + ok(false, "MutationObserver without args should fail"); + } catch(e) { + ok(e.number == 0xffff - 0x80000000, "MutationObserver without new threw exception " + e.number); + } + + try { + window.MutationObserver(42); + ok(false, "MutationObserver with non-function should fail"); + } catch(e) { + todo_wine. + ok(e.name == "TypeMismatchError", "MutationObserver with non-function arg threw exception " + e.name); + } + + try { + window.MutationObserver(function() {}); + } catch(e) { + ok(false, "MutationObserver without new threw exception " + e.number); + } + + try { + new window.MutationObserver(); + ok(false, "MutationObserver with no args should fail"); + } catch(e) { + ok(e.number == 0xffff - 0x80000000, "MutationObserver with no args threw exception " + e.number); + } + + try { + new window.MutationObserver(1); + ok(false, "MutationObserver with non-function arg should fail"); + } catch(e) { + todo_wine. + ok(e.name == "TypeMismatchError", "MutationObserver with non-function arg threw exception " + e.name); + } + + try { + new window.MutationObserver(function() {}); + } catch(e) { + ok(false, "MutationObserver threw exception " + e.number); + } + + try { + new window.MutationObserver(function() {}, 1); + } catch(e) { + ok(false, "MutationObserver with extra args threw exception " + e.number); + } +}) + async_test("postMessage", function() { var v = document.documentMode; var onmessage_called = false;
From: Yuxuan Shui yshui@codeweavers.com
--- dlls/mshtml/mshtml_private_iface.idl | 7 +++++++ dlls/mshtml/mutation.c | 31 ++++++++++++++++++++++++++++ dlls/mshtml/tests/documentmode.js | 10 ++++++++- 3 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl index 46bae638fa5..e4d97361ce1 100644 --- a/dlls/mshtml/mshtml_private_iface.idl +++ b/dlls/mshtml/mshtml_private_iface.idl @@ -21,6 +21,7 @@ #include <mshtmdid.h>
import "ocidl.idl"; +import "mshtml.idl";
[ version(1.0), @@ -85,6 +86,12 @@ interface IWineMSHTMLConsole : IDispatch ] interface IWineMSHTMLMutationObserver : IDispatch { + [id(1)] + HRESULT disconnect(); + [id(2)] + HRESULT observe([in] IHTMLDOMNode *target, [in] IDispatch *options); + [id(3)] + HRESULT takeRecords([retval, out] IDispatch **records); }
[ diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index cbd54a8c151..33478860c02 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -1171,6 +1171,34 @@ static HRESULT WINAPI MutationObserver_Invoke(IWineMSHTMLMutationObserver *iface pDispParams, pVarResult, pExcepInfo, puArgErr); }
+static HRESULT WINAPI MutationObserver_disconnect(IWineMSHTMLMutationObserver *iface) +{ + struct mutation_observer *This = impl_from_IWineMSHTMLMutationObserver(iface); + + FIXME("(%p), stub\n", This); + + return S_OK; +} + +static HRESULT WINAPI MutationObserver_observe(IWineMSHTMLMutationObserver *iface, IHTMLDOMNode *target, + IDispatch *options) +{ + struct mutation_observer *This = impl_from_IWineMSHTMLMutationObserver(iface); + + FIXME("(%p)->(%p %p), stub\n", This, target, options); + + return S_OK; +} + +static HRESULT WINAPI MutationObserver_takeRecords(IWineMSHTMLMutationObserver *iface, IDispatch **ret) +{ + struct mutation_observer *This = impl_from_IWineMSHTMLMutationObserver(iface); + + FIXME("(%p)->(%p), stub\n", This, ret); + + return E_NOTIMPL; +} + static const IWineMSHTMLMutationObserverVtbl WineMSHTMLMutationObserverVtbl = { MutationObserver_QueryInterface, MutationObserver_AddRef, @@ -1179,6 +1207,9 @@ static const IWineMSHTMLMutationObserverVtbl WineMSHTMLMutationObserverVtbl = { MutationObserver_GetTypeInfo, MutationObserver_GetIDsOfNames, MutationObserver_Invoke, + MutationObserver_disconnect, + MutationObserver_observe, + MutationObserver_takeRecords };
static const tid_t mutation_observer_iface_tids[] = { diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 35921ca565f..9f46de12466 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -2909,7 +2909,15 @@ sync_test("MutationObserver", function() { } catch(e) { ok(false, "MutationObserver with extra args threw exception " + e.number); } -}) + + var mutation_observer = new MutationObserver(function() {}); + function test_exposed(prop) { + ok(prop in mutation_observer, prop + " not found in MutationObserver."); + } + test_exposed("observe"); + test_exposed("disconnect"); + test_exposed("takeRecords"); +});
async_test("postMessage", function() { var v = document.documentMode;
On Wed Jul 26 19:01:19 2023 +0000, Yuxuan Shui wrote:
When called without `new`, `cNamedArgs` is not 0.
We have named arg `this`.
On Wed Jul 26 18:16:38 2023 +0000, Yuxuan Shui wrote:
and this comment is to point out, if we don't need the return value, it's safe to skip the `create_mutation_observer` call, a fact which is not necessarily trivial at first glance.
I think it's one of those things that are self explanatory. The job of the constructor is to create an instance of the mutation observer object. If the result is discarded (NULL pointer), then that can safely be skipped. In javascript code, if you don't assign the return value to anything, the result pointer will be NULL (this only happens to methods/constructors btw, for getters the result must always be non-NULL, and is explicitly freed otherwise if not needed).
In terms of js code, the behavior is identical and it shouldn't have any side effects. So here it's just an optimization. Such function *shouldn't* have side effects, other than returning the created object.
On Wed Jul 26 19:04:00 2023 +0000, Yuxuan Shui wrote:
We have named arg `this`.
I see, you're right, but I don't think that code is handling it correctly, it implicitly assumes it is DISPID_THIS. I think this should be checked, then, with a FIXME if it's not. So if cNamedArgs is > 1 or if it's 1 but not DISPID_THIS, print FIXME and return E_NOTIMPL (we have many cases of this in dispex.c). And then I guess you can use `argc` again. Sorry for the confusion earlier.
Gabriel Ivăncescu (@insn) commented about dlls/mshtml/mutation.c:
- TRACE("(%p)->(%lx %x %p %p %p %p)\n", This, lcid, flags, params, res, ei, caller);
- if (argc < 1)
return E_UNEXPECTED;
- callback = params->rgvarg + (params->cArgs - 1);
- if (V_VT(callback) != VT_DISPATCH) {
FIXME("Should return TypeMismatchError\n");
return E_FAIL;
- }
- switch (flags) {
- case DISPATCH_CONSTRUCT:
- case DISPATCH_METHOD:
- case DISPATCH_METHOD | DISPATCH_PROPERTYGET:
The result pointer must not be NULL for `DISPATCH_METHOD | DISPATCH_PROPERTYGET`. See many such instances in dispex.c. I guess you could break after checking it though, instead of falling through, since there's only a break anyway.
On Thu Jul 27 13:20:06 2023 +0000, Gabriel Ivăncescu wrote:
The result pointer must not be NULL for `DISPATCH_METHOD | DISPATCH_PROPERTYGET`. See many such instances in dispex.c. I guess you could break after checking it though, instead of falling through, since there's only a break anyway.
it is NULL when you do `window.MutationObserver(...)`. and we don't want to fail this case.
On Thu Jul 27 13:18:21 2023 +0000, Gabriel Ivăncescu wrote:
I see, you're right, but I don't think that code is handling it correctly, it implicitly assumes it is DISPID_THIS. I think this should be checked, then, with a FIXME if it's not. So if cNamedArgs is > 1 or if it's 1 but not DISPID_THIS, print FIXME and return E_NOTIMPL (we have many cases of this in dispex.c). And then I guess you can use `argc` again. Sorry for the confusion earlier.
but the same check is not done in other similar places
On Thu Jul 27 13:13:44 2023 +0000, Gabriel Ivăncescu wrote:
I think it's one of those things that are self explanatory. The job of the constructor is to create an instance of the mutation observer object. If the result is discarded (NULL pointer), then that can safely be skipped. In javascript code, if you don't assign the return value to anything, the result pointer will be NULL (this only happens to methods/constructors btw, for getters the result must always be non-NULL, and is explicitly freed otherwise if not needed). In terms of js code, the behavior is identical and it shouldn't have any side effects. So here it's just an optimization. Such function *shouldn't* have side effects, other than returning the created object.
personally i disagree, but i will remove this comment.