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