[PATCH v2 4/4] mshtml: Implement IWineDOMTokenList_remove() method.

Paul Gofman pgofman at codeweavers.com
Mon Jul 19 07:53:18 CDT 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
v2:
    - define _remove argument as BSTR (and remove multiple arguments tests).

 dlls/mshtml/htmlelem.c               | 57 +++++++++++++++++++++++-----
 dlls/mshtml/mshtml_private_iface.idl |  2 +
 dlls/mshtml/tests/dom.js             | 43 +++++++++++++++++++++
 3 files changed, 93 insertions(+), 9 deletions(-)

diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index fd9ef686381..9ad538d2b00 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -6515,14 +6515,15 @@ static const WCHAR *find_token(const WCHAR *list, const WCHAR *token, unsigned i
     return NULL;
 }
 
-static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, BSTR token)
+static HRESULT WINAPI token_list_add_remove(IWineDOMTokenList *iface, BSTR token, BOOL remove)
 {
     struct token_list *token_list = impl_from_IWineDOMTokenList(iface);
     unsigned int i, len, old_len, new_len;
+    const WCHAR *old_pos;
     BSTR new, old;
     HRESULT hr;
 
-    TRACE("iface %p, token %s.\n", iface, debugstr_w(token));
+    TRACE("iface %p, token %s, remove %#x.\n", iface, debugstr_w(token), remove);
 
     len = token ? lstrlenW(token) : 0;
     if (!len)
@@ -6543,14 +6544,33 @@ static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, BSTR token)
 
     TRACE("old %s.\n", debugstr_w(old));
 
-    if (find_token(old, token, len))
+    if (((old_pos = find_token(old, token, len)) && !remove)
+            || (!old_pos && remove))
     {
         SysFreeString(old);
         return S_OK;
     }
 
     old_len = old ? lstrlenW(old) : 0;
-    new_len = old_len + len + !!old_len;
+    if (remove)
+    {
+        while (old_pos != old && iswspace(old_pos[-1]))
+        {
+            --old_pos;
+            ++len;
+        }
+        while (iswspace(old_pos[len]))
+            ++len;
+
+        if (old_pos != old && old_pos[len])
+            --len;
+
+        new_len = old_len - len;
+    }
+    else
+    {
+        new_len = old_len + len + !!old_len;
+    }
 
     if (!(new = SysAllocStringLen(NULL, new_len)))
     {
@@ -6559,11 +6579,19 @@ static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, BSTR token)
         return E_OUTOFMEMORY;
     }
 
-    memcpy(new, old, sizeof(*new) * old_len);
-    if (old_len)
-        new[old_len++]= L' ';
-    memcpy(new + old_len, token, sizeof(*new) * len);
-    new[old_len + len] = 0;
+    if (remove)
+    {
+        memcpy(new, old, sizeof(*new) * (old_pos - old));
+        memcpy(new + (old_pos - old), old_pos + len, sizeof(*new) * (old_len - (old_pos - old) - len + 1));
+    }
+    else
+    {
+        memcpy(new, old, sizeof(*new) * old_len);
+        if (old_len)
+            new[old_len++]= L' ';
+        memcpy(new + old_len, token, sizeof(*new) * len);
+        new[old_len + len] = 0;
+    }
 
     SysFreeString(old);
 
@@ -6574,6 +6602,16 @@ static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, BSTR token)
     return hr;
 }
 
+static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, BSTR token)
+{
+    return token_list_add_remove(iface, token, FALSE);
+}
+
+static HRESULT WINAPI token_list_remove(IWineDOMTokenList *iface, BSTR token)
+{
+    return token_list_add_remove(iface, token, TRUE);
+}
+
 static const IWineDOMTokenListVtbl WineDOMTokenListVtbl = {
     token_list_QueryInterface,
     token_list_AddRef,
@@ -6583,6 +6621,7 @@ static const IWineDOMTokenListVtbl WineDOMTokenListVtbl = {
     token_list_GetIDsOfNames,
     token_list_Invoke,
     token_list_add,
+    token_list_remove,
 };
 
 static const tid_t token_list_iface_tids[] = {
diff --git a/dlls/mshtml/mshtml_private_iface.idl b/dlls/mshtml/mshtml_private_iface.idl
index 8a2c9463dca..491f4afb0b6 100644
--- a/dlls/mshtml/mshtml_private_iface.idl
+++ b/dlls/mshtml/mshtml_private_iface.idl
@@ -113,6 +113,8 @@ interface IWineDOMTokenList : IDispatch
 {
     [id(1)]
     HRESULT add([in] BSTR token);
+    [id(2)]
+    HRESULT remove([in] BSTR token);
 }
 
 } /* library MSHTML_private */
diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js
index ccbb3d8b69d..0085b40efed 100644
--- a/dlls/mshtml/tests/dom.js
+++ b/dlls/mshtml/tests/dom.js
@@ -562,4 +562,47 @@ sync_test("classList", function() {
         exception = true;
     }
     ok(exception, "Expected exception for classList.add(\"e f\")");
+
+    classList.remove("e");
+    ok(elem.className === "a b c 4", "remove: expected className 'a b c 4', got " + elem.className);
+
+    exception = false
+    try
+    {
+        classList.remove("e f");
+    }
+    catch(e)
+    {
+        exception = true;
+    }
+    ok(exception, "remove: expected exception for classList.remove(\"e f\")");
+
+    exception = false
+    try
+    {
+        classList.remove("");
+    }
+    catch(e)
+    {
+        exception = true;
+    }
+    ok(exception, "remove: expected exception for classList.remove(\"\")");
+
+    classList.remove("d");
+    ok(elem.className === "a b c 4", "remove: expected className 'a b c 4', got " + elem.className);
+
+    classList.remove("c");
+    ok(elem.className === "a b 4", "remove: expected className 'a b 4', got " + elem.className);
+
+    classList.remove(4);
+    ok(elem.className === "a b", "remove: expected className 'a b', got " + elem.className);
+
+    classList.remove('a');
+    ok(elem.className === "b", "remove: expected className 'b', got " + elem.className);
+
+    classList.remove("a");
+    ok(elem.className === "b", "remove (2): expected className 'b', got " + elem.className);
+
+    classList.remove("b");
+    ok(elem.className === "", "remove: expected className '', got " + elem.className);
 });
-- 
2.31.1




More information about the wine-devel mailing list