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

Paul Gofman pgofman at codeweavers.com
Mon Jul 19 04:55:46 CDT 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/mshtml/htmlelem.c               | 55 ++++++++++++++++++++++++----
 dlls/mshtml/mshtml_private_iface.idl |  2 +
 dlls/mshtml/tests/dom.js             | 43 ++++++++++++++++++++++
 3 files changed, 92 insertions(+), 8 deletions(-)

diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index b5b0daa2539..4506f170616 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -6515,11 +6515,12 @@ static const WCHAR *find_token(const WCHAR *list, const WCHAR *token, unsigned i
     return NULL;
 }
 
-static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *token_array)
+static HRESULT WINAPI token_list_add_remove(IWineDOMTokenList *iface, SAFEARRAY *token_array, BOOL remove)
 {
     struct token_list *token_list = impl_from_IWineDOMTokenList(iface);
     unsigned int i, len, old_len, new_len;
     WCHAR *token, *old, *new;
+    const WCHAR *old_pos;
     VARIANT *var, tmp;
     HRESULT hr;
 
@@ -6578,7 +6579,8 @@ static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *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);
         hr = S_OK;
@@ -6586,7 +6588,25 @@ static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *token_
     }
 
     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 = heap_alloc(sizeof(*new) * (new_len + 1))))
     {
@@ -6596,11 +6616,19 @@ static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *token_
         goto done;
     }
 
-    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);
 
@@ -6616,6 +6644,16 @@ done:
     return hr;
 }
 
+static HRESULT WINAPI token_list_add(IWineDOMTokenList *iface, SAFEARRAY *token_array)
+{
+    return token_list_add_remove(iface, token_array, FALSE);
+}
+
+static HRESULT WINAPI token_list_remove(IWineDOMTokenList *iface, SAFEARRAY *token_array)
+{
+    return token_list_add_remove(iface, token_array, TRUE);
+}
+
 static const IWineDOMTokenListVtbl WineDOMTokenListVtbl = {
     token_list_QueryInterface,
     token_list_AddRef,
@@ -6625,6 +6663,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 b50d2f9502b..7dc4928aab8 100644
--- a/dlls/mshtml/mshtml_private_iface.idl
+++ b/dlls/mshtml/mshtml_private_iface.idl
@@ -113,6 +113,8 @@ interface IWineDOMTokenList : IDispatch
 {
     [vararg, id(1)]
     HRESULT add([in] SAFEARRAY(VARIANT) token);
+    [vararg, id(2)]
+    HRESULT remove([in] SAFEARRAY(VARIANT) token);
 }
 
 } /* library MSHTML_private */
diff --git a/dlls/mshtml/tests/dom.js b/dlls/mshtml/tests/dom.js
index ae6d49da26c..f3fe245d250 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", 4);
+    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