[PATCH v3 02/12] mshtml: Handle VT_DISPATCH in variant_to_nsstr.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Thu Nov 18 10:44:41 CST 2021
Some javascript libraries such as prototype.js use this (by setting to an
array) to examine setAttribute quirks.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
dlls/mshtml/nsembed.c | 41 ++++++++++++----
dlls/mshtml/tests/documentmode.js | 77 +++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 8 deletions(-)
diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c
index 4224d6a..40e7b4a 100644
--- a/dlls/mshtml/nsembed.c
+++ b/dlls/mshtml/nsembed.c
@@ -994,6 +994,8 @@ HRESULT return_nsstr_variant(nsresult nsres, nsAString *nsstr, unsigned flags, V
HRESULT variant_to_nsstr(VARIANT *v, BOOL hex_int, nsAString *nsstr)
{
WCHAR buf[32];
+ HRESULT hres;
+ VARIANT var;
switch(V_VT(v)) {
case VT_NULL:
@@ -1013,19 +1015,42 @@ HRESULT variant_to_nsstr(VARIANT *v, BOOL hex_int, nsAString *nsstr)
nsAString_Init(nsstr, buf);
break;
- case VT_R8: {
- VARIANT strv;
- HRESULT hres;
-
- V_VT(&strv) = VT_EMPTY;
- hres = VariantChangeTypeEx(&strv, v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),
+ case VT_R8:
+ V_VT(&var) = VT_EMPTY;
+ hres = VariantChangeTypeEx(&var, v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT),
0, VT_BSTR);
if(FAILED(hres))
return hres;
- nsAString_Init(nsstr, V_BSTR(&strv));
- SysFreeString(V_BSTR(&strv));
+ nsAString_Init(nsstr, V_BSTR(&var));
+ SysFreeString(V_BSTR(&var));
break;
+
+ case VT_DISPATCH: {
+ LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
+ IDispatch *disp = V_DISPATCH(v);
+
+ if(!disp) {
+ nsAString_InitDepend(nsstr, NULL);
+ return S_OK;
+ }
+
+ hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, lcid, DISPATCH_PROPERTYGET, NULL, &var, NULL, NULL);
+ if(FAILED(hres))
+ return hres;
+
+ if(V_VT(&var) == VT_BSTR) {
+ nsAString_Init(nsstr, V_BSTR(&var));
+ SysFreeString(V_BSTR(&var));
+ break;
+ }
+ if(V_VT(&var) == (VT_BSTR | VT_BYREF)) {
+ nsAString_Init(nsstr, *V_BSTRREF(&var));
+ break;
+ }
+ hres = variant_to_nsstr(&var, hex_int, nsstr);
+ VariantClear(&var);
+ return hres;
}
default:
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index d5f33dd..954dafd 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -1088,6 +1088,72 @@ sync_test("elem_attr", function() {
r = elem.getAttribute("className");
ok(r === "cls3", "className attr = " + r);
+ var arr = [3];
+ elem.setAttribute("testattr", arr);
+ r = elem.getAttribute("testattr");
+ ok(r === (v < 8 ? arr : "3"), "testattr = " + r);
+ todo_wine_if(v === 8).
+ ok(elem.testattr === (v < 9 ? arr : undefined), "elem.testattr = " + elem.testattr);
+ r = elem.removeAttribute("testattr");
+ ok(r === (v < 9 ? true : undefined), "testattr removeAttribute returned " + r);
+ ok(elem.testattr === undefined, "removed testattr = " + elem.testattr);
+
+ arr[0] = 9;
+ elem.setAttribute("testattr", "string");
+ elem.testattr = arr;
+ r = elem.getAttribute("testattr");
+ todo_wine_if(v === 8).
+ ok(r === (v < 8 ? arr : (v < 9 ? "9" : "string")), "testattr = " + r);
+ ok(elem.testattr === arr, "elem.testattr = " + elem.testattr);
+ arr[0] = 3;
+ r = elem.getAttribute("testattr");
+ todo_wine_if(v === 8).
+ ok(r === (v < 8 ? arr : (v < 9 ? "3" : "string")), "testattr = " + r);
+ ok(elem.testattr === arr, "elem.testattr = " + elem.testattr);
+ r = elem.removeAttribute("testattr");
+ ok(r === (v < 9 ? true : undefined), "testattr removeAttribute returned " + r);
+ todo_wine_if(v === 8).
+ ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr = " + elem.testattr);
+
+ arr.toString = function() { return 42; }
+ elem.testattr = arr;
+ r = elem.getAttribute("testattr");
+ todo_wine_if(v === 8).
+ ok(r === (v < 8 ? arr : (v < 9 ? "42" : null)), "testattr with custom toString = " + r);
+ elem.setAttribute("testattr", arr);
+ r = elem.getAttribute("testattr");
+ ok(r === (v < 8 ? arr : "42"), "testattr after setAttribute with custom toString = " + r);
+ ok(elem.testattr === arr, "elem.testattr after setAttribute with custom toString = " + elem.testattr);
+ r = elem.removeAttribute("testattr");
+ ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom toString returned " + r);
+ todo_wine_if(v === 8).
+ ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom toString = " + elem.testattr);
+
+ arr.valueOf = function() { return "arrval"; }
+ elem.testattr = arr;
+ r = elem.getAttribute("testattr");
+ todo_wine_if(v === 8).
+ ok(r === (v < 8 ? arr : (v < 9 ? "arrval" : null)), "testattr with custom valueOf = " + r);
+ elem.setAttribute("testattr", arr);
+ r = elem.getAttribute("testattr");
+ todo_wine_if(v >= 10).
+ ok(r === (v < 8 ? arr : (v < 10 ? "arrval" : "42")), "testattr after setAttribute with custom valueOf = " + r);
+ ok(elem.testattr === arr, "elem.testattr after setAttribute with custom valueOf = " + elem.testattr);
+ r = elem.removeAttribute("testattr");
+ ok(r === (v < 9 ? true : undefined), "testattr removeAttribute with custom valueOf returned " + r);
+ todo_wine_if(v === 8).
+ ok(elem.testattr === (v < 9 ? undefined : arr), "removed testattr with custom valueOf = " + elem.testattr);
+ delete arr.valueOf;
+ delete arr.toString;
+
+ elem.setAttribute("id", arr);
+ r = elem.getAttribute("id");
+ todo_wine_if(v >= 8 && v < 10).
+ ok(r === (v < 8 || v >= 10 ? "3" : "[object]"), "id = " + r);
+ r = elem.removeAttribute("id");
+ ok(r === (v < 9 ? true : undefined), "id removeAttribute returned " + r);
+ ok(elem.id === "", "removed id = " + elem.id);
+
var func = function() { };
elem.onclick = func;
ok(elem.onclick === func, "onclick = " + elem.onclick);
@@ -1136,6 +1202,17 @@ sync_test("elem_attr", function() {
todo_wine_if(v >= 8).
ok(elem.onclick === null, "removed onclick = " + elem.onclick);
+ elem.setAttribute("ondblclick", arr);
+ r = elem.getAttribute("ondblclick");
+ todo_wine_if(v >= 8 && v < 10).
+ ok(r === (v < 8 ? arr : (v < 10 ? "[object]" : "3")), "ondblclick = " + r);
+ r = elem.removeAttribute("ondblclick");
+ ok(r === (v < 8 ? false : (v < 9 ? true : undefined)), "ondblclick removeAttribute returned " + r);
+ r = Object.prototype.toString.call(elem.ondblclick);
+ todo_wine_if(v >= 9).
+ ok(r === (v < 8 ? "[object Array]" : (v < 9 ? "[object Object]" : (v < 11 ? "[object Null]" : "[object Function]"))),
+ "removed ondblclick Object.toString returned " + r);
+
elem.setAttribute("ondblclick", "string");
r = elem.getAttribute("ondblclick");
ok(r === "string", "ondblclick string = " + r);
--
2.31.1
More information about the wine-devel
mailing list