From: Jacek Caban <jacek@codeweavers.com> Based on patch by Yongjie Yao. --- dlls/mshtml/htmlevent.c | 39 +++++++++++++++++++++++++++++++ dlls/mshtml/htmlevent.h | 1 + dlls/mshtml/mutation.c | 21 ++++++++++++++++- dlls/mshtml/nsiface.idl | 15 +++++++++++- dlls/mshtml/tests/documentmode.js | 33 ++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 2 deletions(-) diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index e3301f2ddfd..cfe2acb4fe0 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -4884,6 +4884,45 @@ void update_doc_cp_events(HTMLDocumentNode *doc, cp_static_data_t *cp) } } +void event_attr_changed(HTMLDocumentNode *doc, nsIDOMElement *nselem, const WCHAR *name) +{ + nsAString name_str, value_str; + const PRUnichar *value; + HTMLDOMNode *node; + IDispatch *disp; + eventid_t eid; + nsresult nsres; + HRESULT hres; + + eid = attr_to_eid(name); + if(eid == EVENTID_LAST) + return; + + hres = get_node((nsIDOMNode*)nselem, TRUE, &node); + if(FAILED(hres)) + return; + + nsAString_InitDepend(&name_str, name); + nsAString_InitDepend(&value_str, NULL); + + nsres = nsIDOMElement_GetAttribute(nselem, &name_str, &value_str); + if(NS_SUCCEEDED(nsres)) { + nsAString_GetData(&value_str, &value); + + TRACE("%p.%s = %s\n", nselem, debugstr_w(name), debugstr_w(value)); + + disp = script_parse_event(doc->window, value); + if(disp) { + set_event_handler_disp(get_node_event_prop_target(node, eid), eid, disp); + IDispatch_Release(disp); + } + } + + node_release(node); + nsAString_Finish(&name_str); + nsAString_Finish(&value_str); +} + void check_event_attr(HTMLDocumentNode *doc, nsIDOMElement *nselem) { nsIDOMMozNamedAttrMap *attr_map; diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h index 3f4e11690f8..9576d91c9ff 100644 --- a/dlls/mshtml/htmlevent.h +++ b/dlls/mshtml/htmlevent.h @@ -98,6 +98,7 @@ typedef struct DOMEvent { const WCHAR *get_event_name(eventid_t); void check_event_attr(HTMLDocumentNode*,nsIDOMElement*); +void event_attr_changed(HTMLDocumentNode*,nsIDOMElement*,const WCHAR*); void traverse_event_target(EventTarget*,nsCycleCollectionTraversalCallback*); void release_event_target(EventTarget*); HRESULT set_event_handler(EventTarget*,eventid_t,VARIANT*); diff --git a/dlls/mshtml/mutation.c b/dlls/mshtml/mutation.c index 92fc97a03d9..b330bf3d883 100644 --- a/dlls/mshtml/mutation.c +++ b/dlls/mshtml/mutation.c @@ -785,8 +785,27 @@ static void NSAPI nsDocumentObserver_AttributeWillChange(nsIDocumentObserver *if } static void NSAPI nsDocumentObserver_AttributeChanged(nsIDocumentObserver *iface, nsIDocument *aDocument, - void *aElement, LONG aNameSpaceID, nsIAtom *aAttribute, LONG aModType, const nsAttrValue *aOldValue) + /*mozilla::dom::Element*/ void *aElement, LONG aNameSpaceID, nsIAtom *aAttribute, LONG aModType, const nsAttrValue *aOldValue) { + HTMLDocumentNode *This = impl_from_nsIDocumentObserver(iface); + nsIDOMElement *elem; + nsAString name_str; + const WCHAR *name; + nsresult nsres; + + nsAString_Init(&name_str, NULL); + nsres = nsIAtom_ScriptableToString(aAttribute, &name_str); + assert(nsres == NS_OK); + nsAString_GetData(&name_str, &name); + + TRACE("(%p)->(%p, %s)\n", This, aElement, debugstr_w(name)); + + nsres = nsISupports_QueryInterface(aElement, &IID_nsIDOMElement, (void **)&elem); + assert(nsres == NS_OK); + + event_attr_changed(This, elem, name); + nsAString_Finish(&name_str); + nsIDOMElement_Release(elem); } static void NSAPI nsDocumentObserver_NativeAnonymousChildListChange(nsIDocumentObserver *iface, nsIDocument *aDocument, diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 1f2131dfb24..8bba7d9f83b 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -143,7 +143,6 @@ typedef nsISupports nsIDOMCSSValue; typedef nsISupports nsIPrintSession; typedef nsISupports nsIControllerCommandTable; typedef nsISupports nsIPrincipal; -typedef nsISupports nsIAtom; typedef nsISupports nsISupportsArray; typedef nsISupports nsIContentFilter; typedef nsISupports nsIDOMMediaList; @@ -273,6 +272,20 @@ interface nsIRunnable : nsISupports nsresult Run(); } +[ + object, + uuid(8b8c11d4-3ed5-4079-8974-73c7576cdb34), + local +] +interface nsIAtom : nsISupports +{ + nsresult ScriptableToString(nsAString *_retval); + nsresult ToUTF8String(nsACString *_retval); + nsresult ScriptableEquals(const nsAString *aString, bool *_retval); + bool EqualsUTF8(const nsACString *aString); + bool IsStaticAtom(); +} + [ object, uuid(d1899240-f9d2-11d2-bdd6-000064657374), diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index b0df4ed2479..dadd7ba6b04 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3169,6 +3169,39 @@ sync_test("elem_attrNS", function() { ok(r === "13", "numattr = " + r); }); + +var rec; + +sync_test("event attr", function() { + document.body.innerHTML = '<div></div>'; + var elem = document.body.firstChild, prev; + var v = document.documentMode; + + ok(elem.onclick === null, "elem.onclick = " + elem.onclick); + elem.setAttribute("onclick", "rec += 'attr';"); + if (v < 8) + ok(elem.onclick === "rec += 'attr';", "elem.onclick = " + elem.onclick); + else + todo_wine_if(v == 8). + ok(typeof(elem.onclick) === "function", "elem.onclick = " + elem.onclick); + rec = ""; + elem.click(); + todo_wine_if(v == 8). + ok(rec === (v < 8 ? "" : "attr"), "unexpected rec = " + rec ); + + elem.setAttribute("onclick", "rec += 'attr2';"); + rec = ""; + elem.click(); + todo_wine_if(v == 8). + ok(rec === (v < 8 ? "" : "attr2"), "unexpected rec = " + rec ); + + elem.onclick = "rec += 'prop';"; + ok(elem.onclick === (v < 9 ? "rec += 'prop';" : null), "elem.onclick = " + elem.onclick); + rec = ""; + elem.click(); + ok(rec === "", "unexpected rec = " + rec ); +}); + sync_test("builtins_diffs", function() { var v = document.documentMode; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9976