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