Module: wine Branch: master Commit: a42cffbdcc16e7180bd21ee13de78da9c190f6ac URL: http://source.winehq.org/git/wine.git/?a=commit;h=a42cffbdcc16e7180bd21ee13d...
Author: Jacek Caban jacek@codeweavers.com Date: Tue May 31 12:19:04 2011 +0200
mshtml: Added support for accessing document elements by index.
---
dlls/mshtml/htmldoc.c | 127 ++++++++++++++++++++++++++++++++++++++++- dlls/mshtml/mshtml_private.h | 4 + dlls/mshtml/tests/jstest.html | 20 +++++++ 3 files changed, 149 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 6ecb39b..1ebb8eb 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -1557,6 +1557,64 @@ 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) +{ + nsIDOMNodeList *node_list; + nsAString name_str; + PRUint32 len; + unsigned i; + nsresult nsres; + + 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; + + nsres = nsIDOMNodeList_GetLength(node_list, &len); + nsIDOMNodeList_Release(node_list); + if(NS_FAILED(nsres)) + return E_FAIL; + + if(!len) + return DISP_E_UNKNOWNNAME; + + for(i=0; i < This->elem_vars_cnt; i++) { + if(!strcmpW(name, This->elem_vars[i])) { + *dispid = MSHTML_DISPID_CUSTOM_MIN+i; + return S_OK; + } + } + + if(This->elem_vars_cnt == This->elem_vars_size) { + WCHAR **new_vars; + + if(This->elem_vars_size) { + new_vars = heap_realloc(This->elem_vars, This->elem_vars_size*2*sizeof(WCHAR*)); + if(!new_vars) + return E_OUTOFMEMORY; + This->elem_vars_size *= 2; + }else { + new_vars = heap_alloc(16*sizeof(WCHAR*)); + if(!new_vars) + return E_OUTOFMEMORY; + This->elem_vars_size = 16; + } + + This->elem_vars = new_vars; + } + + This->elem_vars[This->elem_vars_cnt] = heap_strdupW(name); + if(!This->elem_vars[This->elem_vars_cnt]) + return E_OUTOFMEMORY; + + *dispid = MSHTML_DISPID_CUSTOM_MIN+This->elem_vars_cnt++; + return S_OK; +} + static HRESULT WINAPI DocDispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) { HTMLDocument *This = impl_from_IDispatchEx(iface); @@ -1630,8 +1688,13 @@ static HRESULT WINAPI DocDispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMemb static HRESULT WINAPI DocDispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) { HTMLDocument *This = impl_from_IDispatchEx(iface); + HRESULT hres;
- return IDispatchEx_GetDispID(This->dispex, bstrName, grfdex, pid); + hres = IDispatchEx_GetDispID(This->dispex, bstrName, grfdex, pid); + if(hres != DISP_E_UNKNOWNNAME) + return hres; + + return dispid_from_elem_name(This->doc_node, bstrName, pid); }
static HRESULT WINAPI DocDispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, @@ -1905,6 +1968,11 @@ static HRESULT HTMLDocumentNode_QI(HTMLDOMNode *iface, REFIID riid, void **ppv) static void HTMLDocumentNode_destructor(HTMLDOMNode *iface) { HTMLDocumentNode *This = impl_from_HTMLDOMNode(iface); + unsigned i; + + for(i=0; i < This->elem_vars_cnt; i++) + heap_free(This->elem_vars[i]); + heap_free(This->elem_vars);
if(This->body_event_target) release_event_target(This->body_event_target); @@ -1956,6 +2024,61 @@ static HRESULT HTMLDocumentFragment_clone(HTMLDOMNode *iface, nsIDOMNode *nsnode return S_OK; }
+static inline HTMLDocumentNode *impl_from_DispatchEx(DispatchEx *iface) +{ + return CONTAINING_RECORD(iface, HTMLDocumentNode, node.dispex); +} + +static HRESULT HTMLDocumentNode_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLDocumentNode *This = impl_from_DispatchEx(dispex); + nsIDOMNodeList *node_list; + nsAString name_str; + nsIDOMNode *nsnode; + HTMLDOMNode *node; + unsigned i; + nsresult nsres; + HRESULT hres; + + if(flags != DISPATCH_PROPERTYGET) { + FIXME("unsupported flags %x\n", flags); + return E_NOTIMPL; + } + + i = id - MSHTML_DISPID_CUSTOM_MIN; + + if(!This->nsdoc || i >= This->elem_vars_cnt) + return DISP_E_UNKNOWNNAME; + + nsAString_InitDepend(&name_str, This->elem_vars[i]); + nsres = nsIDOMHTMLDocument_GetElementsByName(This->nsdoc, &name_str, &node_list); + nsAString_Finish(&name_str); + if(NS_FAILED(nsres)) + return E_FAIL; + + nsres = nsIDOMNodeList_Item(node_list, 0, &nsnode); + nsIDOMNodeList_Release(node_list); + if(NS_FAILED(nsres) || !nsnode) + return DISP_E_UNKNOWNNAME; + + hres = get_node(This, nsnode, TRUE, &node); + if(FAILED(hres)) + return hres; + + IHTMLDOMNode_AddRef(&node->IHTMLDOMNode_iface); + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = (IDispatch*)&node->IHTMLDOMNode_iface; + return S_OK; +} + + +static const dispex_static_data_vtbl_t HTMLDocumentNode_dispex_vtbl = { + NULL, + NULL, + HTMLDocumentNode_invoke +}; + static const NodeImplVtbl HTMLDocumentFragmentImplVtbl = { HTMLDocumentNode_QI, HTMLDocumentNode_destructor, @@ -1973,7 +2096,7 @@ static const tid_t HTMLDocumentNode_iface_tids[] = { };
static dispex_static_data_t HTMLDocumentNode_dispex = { - NULL, + &HTMLDocumentNode_dispex_vtbl, DispHTMLDocument_tid, NULL, HTMLDocumentNode_iface_tids diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 6832d54..6fc78ec 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -623,6 +623,10 @@ struct HTMLDocumentNode { nsDocumentEventListener *nsevent_listener; BOOL *event_vector;
+ WCHAR **elem_vars; + unsigned elem_vars_size; + unsigned elem_vars_cnt; + BOOL skip_mutation_notif;
struct list bindings; diff --git a/dlls/mshtml/tests/jstest.html b/dlls/mshtml/tests/jstest.html index c19abe8..b465491 100644 --- a/dlls/mshtml/tests/jstest.html +++ b/dlls/mshtml/tests/jstest.html @@ -43,6 +43,25 @@ function test_createDocumentFragment() { ok(cloned.nodeName === "#document-fragment", "cloned.nodeName = " + cloned.nodeName); }
+function test_document_name_as_index() { + document.body.innerHTML = '<form name="formname"></form>'; + var e = document.getElementById("formname"); + ok(!!e, "e is null"); + + ok(document.formname === e, "document.formname != getElementById('formname')"); + ok("formname" in document, "formname' is not in document"); + + document.body.removeChild(e); + + ok(document.formname === undefined, "document.formname is not undefined"); + ok(!("formname" in document), "formname' is in document"); + + document.body.innerHTML = '<form id="formid"></form>'; + var e = document.getElementById("formid"); + ok(!!e, "e is null"); + ok(!("formid" in document), "formid is in document"); +} + var globalVar = false;
function runTest() { @@ -55,6 +74,7 @@ function runTest() { test_removeAttribute(document.body); test_select_index(); test_createDocumentFragment(); + test_document_name_as_index();
var r = window.execScript("globalVar = true;"); ok(r === undefined, "execScript returned " + r);