Jacek Caban : mshtml: Added support for accessing document elements by index.

Alexandre Julliard julliard at winehq.org
Tue May 31 13:08:18 CDT 2011


Module: wine
Branch: master
Commit: a42cffbdcc16e7180bd21ee13de78da9c190f6ac
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a42cffbdcc16e7180bd21ee13de78da9c190f6ac

Author: Jacek Caban <jacek at 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);




More information about the wine-cvs mailing list