From 3216c04d71ed8118f8acb3e52861ba60ca032d8e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gabriel=20Iv=C4=83ncescu?= Date: Thu, 13 Oct 2022 20:24:39 +0300 Subject: [PATCH] mshtml: Expose props via element name only for specific element types. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Gabriel Ivăncescu --- dlls/mshtml/htmldoc.c | 31 +++++++++++++++++++------------ dlls/mshtml/tests/documentmode.js | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index d86ed07e033..aa71e53d144 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -4820,23 +4820,30 @@ static inline HTMLDocument *impl_from_IDispatchEx(IDispatchEx *iface) static HRESULT has_elem_name(nsIDOMHTMLDocument *nsdoc, const WCHAR *name) { - nsIDOMNodeList *node_list; - nsAString name_str; + static const WCHAR fmt[] = L":-moz-any(applet,embed,form,iframe,img,object)[name=\"%s\"]"; + WCHAR buf[128], *selector = buf; + nsAString selector_str; + nsIDOMElement *nselem; nsresult nsres; - UINT32 len; + size_t len; - nsAString_InitDepend(&name_str, name); - nsres = nsIDOMHTMLDocument_GetElementsByName(nsdoc, &name_str, &node_list); - nsAString_Finish(&name_str); - if(NS_FAILED(nsres)) - return map_nsresult(nsres); + len = wcslen(name) + ARRAY_SIZE(fmt) - 2 /* %s */; + if(len > ARRAY_SIZE(buf) && !(selector = heap_alloc(len * sizeof(WCHAR)))) + return E_OUTOFMEMORY; + swprintf(selector, len, fmt, name); - nsres = nsIDOMNodeList_GetLength(node_list, &len); - nsIDOMNodeList_Release(node_list); + nsAString_InitDepend(&selector_str, selector); + nsres = nsIDOMHTMLDocument_QuerySelector(nsdoc, &selector_str, &nselem); + nsAString_Finish(&selector_str); + if(selector != buf) + heap_free(selector); if(NS_FAILED(nsres)) return map_nsresult(nsres); - return len ? S_OK : DISP_E_UNKNOWNNAME; + if(!nselem) + return DISP_E_UNKNOWNNAME; + nsIDOMElement_Release(nselem); + return S_OK; } static HRESULT dispid_from_elem_name(HTMLDocumentNode *This, const WCHAR *name, DISPID *dispid) @@ -5918,7 +5925,7 @@ static HRESULT HTMLDocumentNode_next_dispid(DispatchEx *dispex, DISPID id, DISPI } /* Populate possibly missing DISPIDs */ - nsAString_InitDepend(&nsstr, L"[name]"); + nsAString_InitDepend(&nsstr, L":-moz-any(applet,embed,form,iframe,img,object)[name]"); nsres = nsIDOMHTMLDocument_QuerySelectorAll(This->nsdoc, &nsstr, &node_list); nsAString_Finish(&nsstr); if(NS_FAILED(nsres)) diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index ad258b3df2e..5aa9759fe81 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -669,7 +669,7 @@ sync_test("for..in", function() { sync_test("elem_by_id", function() { document.body.innerHTML = '
'; - var found; + var found, i; var id_elem = document.getElementById("testid"); ok(id_elem.tagName === "FORM", "id_elem.tagName = " + id_elem.tagName); @@ -704,6 +704,39 @@ sync_test("elem_by_id", function() { found = true; } ok(found, "testname was not enumerated in document"); + + // these tags expose name as props, and id only if they have a name + var tags = [ "embed", "form", "iframe", "img" ]; + for(i in tags) { + var tag = tags[i]; + document.body.innerHTML = '<' + tag + ' id="testid" name="testname"><' + tag + ' id="foobar">'; + ok("testname" in document, tag + " did not expose testname"); + todo_wine. + ok("testid" in document, tag + " did not expose testid"); + ok(!("foobar" in document), tag + " exposed foobar"); + } + + // these tags always expose their id as well as name (we don't test applet because it makes Windows pop up a dialog box) + tags = [ "object" ]; + for(i in tags) { + var tag = tags[i]; + document.body.innerHTML = '<' + tag + ' id="testid" name="testname"><' + tag + ' id="foobar">'; + ok("testname" in document, tag + " did not expose testname"); + todo_wine. + ok("testid" in document, tag + " did not expose testid"); + todo_wine. + ok("foobar" in document, tag + " did not expose foobar"); + } + + // all other tags don't expose props for either id or name, test a few of them here + tags = [ "a", "b", "body", "center", "div", "frame", "h2", "head", "html", "input", "meta", "p", "span", "style", "table", "winetest" ]; + for(i in tags) { + var tag = tags[i]; + document.body.innerHTML = '<' + tag + ' id="testid" name="testname"><' + tag + ' id="foobar">'; + ok(!("testname" in document), tag + " exposed testname"); + ok(!("testid" in document), tag + " exposed testid"); + ok(!("foobar" in document), tag + " exposed foobar"); + } }); sync_test("doc_mode", function() { -- 2.11.4.GIT