Jacek Caban : mshtml: Added support for accessing elements id by global properties.
Alexandre Julliard
julliard at winehq.org
Tue Nov 3 15:37:18 CST 2009
Module: wine
Branch: master
Commit: 82c8e7c68489581e6a42038b1fc46d58d978f59a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=82c8e7c68489581e6a42038b1fc46d58d978f59a
Author: Jacek Caban <jacek at codeweavers.com>
Date: Sun Nov 1 19:21:57 2009 +0100
mshtml: Added support for accessing elements id by global properties.
---
dlls/mshtml/htmlwindow.c | 91 ++++++++++++++++++++++++++++++++----------
dlls/mshtml/mshtml_private.h | 6 +++
dlls/mshtml/tests/script.c | 39 +++++++++++++++++-
3 files changed, 114 insertions(+), 22 deletions(-)
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index a14fe5c..6158b32 100644
--- a/dlls/mshtml/htmlwindow.c
+++ b/dlls/mshtml/htmlwindow.c
@@ -1005,8 +1005,7 @@ static HRESULT HTMLWindow_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD fla
VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
{
HTMLWindow *This = HTMLWINDOW2_THIS(iface);
- IDispatchEx *dispex;
- IDispatch *disp;
+ global_prop_t *prop;
DWORD idx;
HRESULT hres;
@@ -1014,24 +1013,51 @@ static HRESULT HTMLWindow_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD fla
if(idx >= This->global_prop_cnt)
return DISP_E_MEMBERNOTFOUND;
- disp = get_script_disp(This->global_props[idx].script_host);
- if(!disp)
- return E_UNEXPECTED;
-
- hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
- if(SUCCEEDED(hres)) {
- TRACE("%s >>>\n", debugstr_w(This->global_props[idx].name));
- hres = IDispatchEx_InvokeEx(dispex, This->global_props[idx].id, lcid, flags, params, res, ei, caller);
- if(hres == S_OK)
- TRACE("%s <<<\n", debugstr_w(This->global_props[idx].name));
- else
- WARN("%s <<< %08x\n", debugstr_w(This->global_props[idx].name), hres);
- IDispatchEx_Release(dispex);
- }else {
- FIXME("No IDispatchEx\n");
+ prop = This->global_props+idx;
+
+ switch(prop->type) {
+ case GLOBAL_SCRIPTVAR: {
+ IDispatchEx *dispex;
+ IDispatch *disp;
+
+ disp = get_script_disp(prop->script_host);
+ if(!disp)
+ return E_UNEXPECTED;
+
+ hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+ if(SUCCEEDED(hres)) {
+ TRACE("%s >>>\n", debugstr_w(prop->name));
+ hres = IDispatchEx_InvokeEx(dispex, prop->id, lcid, flags, params, res, ei, caller);
+ if(hres == S_OK)
+ TRACE("%s <<<\n", debugstr_w(prop->name));
+ else
+ WARN("%s <<< %08x\n", debugstr_w(prop->name), hres);
+ IDispatchEx_Release(dispex);
+ }else {
+ FIXME("No IDispatchEx\n");
+ }
+ IDispatch_Release(disp);
+ break;
+ }
+ case GLOBAL_ELEMENTVAR: {
+ IHTMLElement *elem;
+
+ hres = IHTMLDocument3_getElementById(HTMLDOC3(&This->doc->basedoc), prop->name, &elem);
+ if(FAILED(hres))
+ return hres;
+
+ if(!elem)
+ return DISP_E_MEMBERNOTFOUND;
+
+ V_VT(res) = VT_DISPATCH;
+ V_DISPATCH(res) = (IDispatch*)elem;
+ break;
+ }
+ default:
+ ERR("invalid type %d\n", prop->type);
+ hres = DISP_E_MEMBERNOTFOUND;
}
- IDispatch_Release(disp);
return hres;
}
@@ -1399,7 +1425,7 @@ static HRESULT WINAPI WindowDispEx_Invoke(IDispatchEx *iface, DISPID dispIdMembe
pVarResult, pExcepInfo, puArgErr);
}
-static global_prop_t *alloc_global_prop(HTMLWindow *This, BSTR name)
+static global_prop_t *alloc_global_prop(HTMLWindow *This, global_prop_type_t type, BSTR name)
{
if(This->global_prop_cnt == This->global_prop_size) {
global_prop_t *new_props;
@@ -1422,6 +1448,7 @@ static global_prop_t *alloc_global_prop(HTMLWindow *This, BSTR name)
if(!This->global_props[This->global_prop_cnt].name)
return NULL;
+ This->global_props[This->global_prop_cnt].type = type;
return This->global_props + This->global_prop_cnt++;
}
@@ -1436,6 +1463,7 @@ static HRESULT WINAPI WindowDispEx_GetDispID(IDispatchEx *iface, BSTR bstrName,
ScriptHost *script_host;
DISPID id;
DWORD i;
+ HRESULT hres;
TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid);
@@ -1450,7 +1478,7 @@ static HRESULT WINAPI WindowDispEx_GetDispID(IDispatchEx *iface, BSTR bstrName,
if(find_global_prop(This, bstrName, grfdex, &script_host, &id)) {
global_prop_t *prop;
- prop = alloc_global_prop(This, bstrName);
+ prop = alloc_global_prop(This, GLOBAL_SCRIPTVAR, bstrName);
if(!prop)
return E_OUTOFMEMORY;
@@ -1461,7 +1489,28 @@ static HRESULT WINAPI WindowDispEx_GetDispID(IDispatchEx *iface, BSTR bstrName,
return S_OK;
}
- return IDispatchEx_GetDispID(DISPATCHEX(&This->dispex), bstrName, grfdex, pid);
+ hres = IDispatchEx_GetDispID(DISPATCHEX(&This->dispex), bstrName, grfdex, pid);
+ if(hres != DISP_E_UNKNOWNNAME)
+ return hres;
+
+ if(This->doc) {
+ global_prop_t *prop;
+ IHTMLElement *elem;
+
+ hres = IHTMLDocument3_getElementById(HTMLDOC3(&This->doc->basedoc), bstrName, &elem);
+ if(SUCCEEDED(hres) && elem) {
+ IHTMLElement_Release(elem);
+
+ prop = alloc_global_prop(This, GLOBAL_ELEMENTVAR, bstrName);
+ if(!prop)
+ return E_OUTOFMEMORY;
+
+ *pid = prop_to_dispid(This, prop);
+ return S_OK;
+ }
+ }
+
+ return DISP_E_UNKNOWNNAME;
}
static HRESULT WINAPI WindowDispEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index a6a8396..89acf46 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -168,7 +168,13 @@ typedef enum {
typedef struct ScriptHost ScriptHost;
+typedef enum {
+ GLOBAL_SCRIPTVAR,
+ GLOBAL_ELEMENTVAR
+} global_prop_type_t;
+
typedef struct {
+ global_prop_type_t type;
WCHAR *name;
ScriptHost *script_host;
DISPID id;
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c
index 16c7811..05f2e4e 100644
--- a/dlls/mshtml/tests/script.c
+++ b/dlls/mshtml/tests/script.c
@@ -112,6 +112,7 @@ DEFINE_EXPECT(AddNamedItem);
DEFINE_EXPECT(ParseScriptText);
DEFINE_EXPECT(GetScriptDispatch);
DEFINE_EXPECT(funcDisp);
+DEFINE_EXPECT(script_divid_d);
DEFINE_EXPECT(script_testprop_d);
DEFINE_EXPECT(script_testprop_i);
DEFINE_EXPECT(AXQueryInterface_IActiveScript);
@@ -369,7 +370,13 @@ static HRESULT WINAPI scriptDisp_GetDispID(IDispatchEx *iface, BSTR bstrName, DW
return S_OK;
}
- ok(0, "unexpected call\n");
+ if(!strcmp_wa(bstrName, "divid")) {
+ CHECK_EXPECT(script_divid_d);
+ ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
+ return E_FAIL;
+ }
+
+ ok(0, "unexpected call\b");
return E_NOTIMPL;
}
@@ -915,6 +922,33 @@ static void test_nextdispid(IDispatchEx *dispex)
ok(id == DISPID_STARTENUM, "id != DISPID_STARTENUM\n");
}
+static void test_global_id(void)
+{
+ VARIANT var;
+ DISPPARAMS dp;
+ EXCEPINFO ei;
+ BSTR tmp;
+ DISPID id;
+ HRESULT hres;
+
+ SET_EXPECT(GetScriptDispatch);
+ SET_EXPECT(script_divid_d);
+ tmp = a2bstr("divid");
+ hres = IDispatchEx_GetDispID(window_dispex, tmp, fdexNameCaseSensitive, &id);
+ ok(hres == S_OK, "GetDispID failed: %08x\n", hres);
+ SysFreeString(tmp);
+ CHECK_CALLED(GetScriptDispatch);
+ CHECK_CALLED(script_divid_d);
+
+ VariantInit(&var);
+ memset(&ei, 0, sizeof(ei));
+ memset(&dp, 0, sizeof(dp));
+ hres = IDispatchEx_InvokeEx(window_dispex, id, 0, DISPATCH_PROPERTYGET, &dp, &var, &ei, NULL);
+ ok(hres == S_OK, "InvokeEx failed: %08x\n", hres);
+ ok(V_VT(&var) == VT_DISPATCH, "V_VT(var) = %d\n", V_VT(&var));
+ VariantClear(&var);
+}
+
static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *iface,
LPCOLESTR pstrCode, LPCOLESTR pstrItemName, IUnknown *punkContext,
LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLine,
@@ -1104,6 +1138,8 @@ static HRESULT WINAPI ActiveScriptParse_ParseScriptText(IActiveScriptParse *ifac
CHECK_CALLED(GetScriptDispatch);
CHECK_CALLED(script_testprop_i);
+ test_global_id();
+
test_security();
return S_OK;
@@ -1421,6 +1457,7 @@ static IClassFactory script_cf = { &ClassFactoryVtbl };
static const char simple_script_str[] =
"<html><head></head><body>"
+ "<div id=\"divid\"></div>"
"<script language=\"TestScript\">simple script</script>"
"</body></html>";
More information about the wine-cvs
mailing list