From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmldoc.c | 106 ++++++++++++++++++++++++++---- dlls/mshtml/tests/documentmode.js | 1 - 2 files changed, 92 insertions(+), 15 deletions(-)
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 0c96d73eb76..5a928e68fe1 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -4818,7 +4818,7 @@ static inline HTMLDocument *impl_from_IDispatchEx(IDispatchEx *iface) return CONTAINING_RECORD(iface, HTMLDocument, IDispatchEx_iface); }
-static HRESULT dispid_from_elem_name(HTMLDocumentNode *This, BSTR name, DISPID *dispid) +static HRESULT dispid_from_elem_name(HTMLDocumentNode *This, const WCHAR *name, DISPID *dispid, BOOL enum_name) { nsIDOMNodeList *node_list; nsAString name_str; @@ -4829,19 +4829,21 @@ static HRESULT dispid_from_elem_name(HTMLDocumentNode *This, BSTR name, DISPID * if(!This->nsdoc) return DISP_E_UNKNOWNNAME;
- nsAString_InitDepend(&name_str, name); - nsres = nsIDOMHTMLDocument_GetElementsByName(This->nsdoc, &name_str, &node_list); - nsAString_Finish(&name_str); - if(NS_FAILED(nsres)) - return E_FAIL; + if(!enum_name) { + nsAString_InitDepend(&name_str, name); + nsres = nsIDOMHTMLDocument_GetElementsByName(This->nsdoc, &name_str, &node_list); + nsAString_Finish(&name_str); + if(NS_FAILED(nsres)) + return E_FAIL;
- nsres = nsIDOMNodeList_GetLength(node_list, &len); - nsIDOMNodeList_Release(node_list); - if(NS_FAILED(nsres)) - return E_FAIL; + nsres = nsIDOMNodeList_GetLength(node_list, &len); + nsIDOMNodeList_Release(node_list); + if(NS_FAILED(nsres)) + return E_FAIL;
- if(!len) - return DISP_E_UNKNOWNNAME; + if(!len) + return DISP_E_UNKNOWNNAME; + }
for(i=0; i < This->elem_vars_cnt; i++) { if(!wcscmp(name, This->elem_vars[i])) { @@ -4943,7 +4945,7 @@ static HRESULT WINAPI DocDispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, if(hres != DISP_E_UNKNOWNNAME) return hres;
- return dispid_from_elem_name(This->doc_node, bstrName, pid); + return dispid_from_elem_name(This->doc_node, bstrName, pid, FALSE); }
static HRESULT WINAPI DocDispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, @@ -5885,6 +5887,82 @@ static HRESULT HTMLDocumentNode_invoke(DispatchEx *dispex, DISPID id, LCID lcid, return S_OK; }
+static HRESULT HTMLDocumentNode_next_dispid(DispatchEx *dispex, DISPID id, DISPID *pid) +{ + DWORD idx = (id == DISPID_STARTENUM) ? 0 : id - MSHTML_DISPID_CUSTOM_MIN + 1; + HTMLDocumentNode *This = impl_from_DispatchEx(dispex); + nsIDOMNodeList *node_list; + const PRUnichar *name; + nsIDOMElement *nselem; + nsIDOMNode *nsnode; + nsAString nsstr; + nsresult nsres; + UINT32 i, len; + HRESULT hres; + + if(!This->nsdoc) + return S_FALSE; + + while(idx < This->elem_vars_cnt) { + nsAString_InitDepend(&nsstr, This->elem_vars[idx]); + nsres = nsIDOMHTMLDocument_GetElementsByName(This->nsdoc, &nsstr, &node_list); + nsAString_Finish(&nsstr); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + + nsres = nsIDOMNodeList_GetLength(node_list, &len); + nsIDOMNodeList_Release(node_list); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + + if(len) { + *pid = idx + MSHTML_DISPID_CUSTOM_MIN; + return S_OK; + } + idx++; + } + + /* Populate possibly missing DISPIDs */ + nsAString_InitDepend(&nsstr, L"[name]"); + nsres = nsIDOMHTMLDocument_QuerySelectorAll(This->nsdoc, &nsstr, &node_list); + nsAString_Finish(&nsstr); + if(NS_FAILED(nsres)) + return map_nsresult(nsres); + + for(i = 0, hres = S_OK; SUCCEEDED(hres); i++) { + nsres = nsIDOMNodeList_Item(node_list, i, &nsnode); + if(NS_FAILED(nsres)) { + hres = map_nsresult(nsres); + break; + } + if(!nsnode) + break; + + nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&nselem); + nsIDOMNode_Release(nsnode); + if(nsres != S_OK) + continue; + + nsres = get_elem_attr_value(nselem, L"name", &nsstr, &name); + nsIDOMElement_Release(nselem); + if(NS_FAILED(nsres)) + hres = map_nsresult(nsres); + else { + hres = dispid_from_elem_name(This, name, &id, TRUE); + nsAString_Finish(&nsstr); + } + } + nsIDOMNodeList_Release(node_list); + if(FAILED(hres)) + return hres; + + if(idx >= This->elem_vars_cnt) + return S_FALSE; + + *pid = idx + MSHTML_DISPID_CUSTOM_MIN; + return S_OK; +} + static compat_mode_t HTMLDocumentNode_get_compat_mode(DispatchEx *dispex) { HTMLDocumentNode *This = impl_from_DispatchEx(dispex); @@ -5943,7 +6021,7 @@ static const event_target_vtbl_t HTMLDocumentNode_event_target_vtbl = { HTMLDocumentNode_get_name, HTMLDocumentNode_invoke, NULL, - NULL, + HTMLDocumentNode_next_dispid, HTMLDocumentNode_get_compat_mode, NULL }, diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index a3a0e2439cd..ad258b3df2e 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -703,7 +703,6 @@ sync_test("elem_by_id", function() { if(id_elem === "testname") found = true; } - todo_wine. ok(found, "testname was not enumerated in document"); });