[PATCH v2 6/6] jscript: Implement Array.prototype.lastIndexOf.

Gabriel Ivăncescu gabrielopcode at gmail.com
Wed Apr 20 11:56:39 CDT 2022


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/jscript/array.c     | 63 ++++++++++++++++++++++++++++++++++++++++
 dlls/mshtml/tests/es5.js | 29 ++++++++++++++++++
 2 files changed, 92 insertions(+)

diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c
index 3ee687a..c8caaeb 100644
--- a/dlls/jscript/array.c
+++ b/dlls/jscript/array.c
@@ -1277,6 +1277,68 @@ done:
     return hres;
 }
 
+static HRESULT Array_lastIndexOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv,
+        jsval_t *r)
+{
+    jsval_t search, value;
+    unsigned i, length;
+    jsdisp_t *jsthis;
+    HRESULT hres;
+    BOOL eq;
+
+    TRACE("\n");
+
+    hres = get_length(ctx, vthis, &jsthis, &length);
+    if(FAILED(hres))
+        return hres;
+    if(!length)
+        goto notfound;
+
+    search = argc ? argv[0] : jsval_undefined();
+
+    i = length - 1;
+    if(argc > 1) {
+        double from_arg;
+
+        hres = to_integer(ctx, argv[1], &from_arg);
+        if(FAILED(hres))
+            goto done;
+
+        if(from_arg >= 0.0)
+            i = min(from_arg, i);
+        else {
+            from_arg += length;
+            if(from_arg < 0.0)
+                goto notfound;
+            i = from_arg;
+        }
+    }
+
+    do {
+        hres = jsdisp_get_idx(jsthis, i, &value);
+        if(hres == DISP_E_UNKNOWNNAME)
+            continue;
+        if(FAILED(hres))
+            goto done;
+
+        hres = jsval_strict_equal(value, search, &eq);
+        jsval_release(value);
+        if(FAILED(hres))
+            goto done;
+        if(eq) {
+            if(r) *r = jsval_number(i);
+            goto done;
+        }
+    } while(i--);
+
+notfound:
+    if(r) *r = jsval_number(-1);
+    hres = S_OK;
+done:
+    jsdisp_release(jsthis);
+    return hres;
+}
+
 static HRESULT Array_map(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
 {
     IDispatch *context_this = NULL, *callback;
@@ -1576,6 +1638,7 @@ static const builtin_prop_t Array_props[] = {
     {L"forEach",               Array_forEach,              PROPF_METHOD|PROPF_ES5|1},
     {L"indexOf",               Array_indexOf,              PROPF_METHOD|PROPF_ES5|1},
     {L"join",                  Array_join,                 PROPF_METHOD|1},
+    {L"lastIndexOf",           Array_lastIndexOf,          PROPF_METHOD|PROPF_ES5|1},
     {L"length",                NULL,0,                     Array_get_length, Array_set_length},
     {L"map",                   Array_map,                  PROPF_METHOD|PROPF_ES5|1},
     {L"pop",                   Array_pop,                  PROPF_METHOD},
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index 487e3de..11f8db2 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -155,6 +155,35 @@ sync_test("indexOf", function() {
     expect([1,2,3], [2, 1.9], 1);
 });
 
+sync_test("lastIndexOf", function() {
+    function expect(array, args, exr) {
+        var r = Array.prototype.lastIndexOf.apply(array, args);
+        ok(r == exr, "lastIndexOf returned " + r + " expected " + exr);
+    }
+
+    ok(Array.prototype.lastIndexOf.length == 1, "lastIndexOf.length = " + Array.prototype.lastIndexOf.length);
+
+    expect([1,2,3], [2], 1);
+    expect([1,undefined,3], [undefined], 1);
+    expect([1,undefined,3], [], 1);
+    expect([1,,3], [undefined], -1);
+    expect([1,undefined,undefined], [undefined], 2);
+    expect([1,2,3,2,5,6], [2, 2], 1);
+    expect([1,2,3,2,5,6], [2], 3);
+    expect([1,2,3,2,5,6], [2, -3], 3);
+    expect([1,2,3,2,5,6], [2, -4], 1);
+    expect([1,2,3,2,5,6], [1, -100], -1);
+    expect([1,2,3,2,5,6], [2, 100], 3);
+    expect("abcba", ["b"], 3);
+    expect(true, [true], -1);
+    expect({"4": 4, length: 5}, [4], 4);
+    expect({"4": 4, length: 5}, [undefined], -1);
+    expect({"4": 4, length: 3}, [4], -1);
+    expect({"test": true}, [true], -1);
+    expect([1,2,3], [2, 1.9], 1);
+    expect([1,2,3], [2, 0.9], -1);
+});
+
 sync_test("filter", function() {
     ok(Array.prototype.filter.length === 1, "filter.length = " + Array.prototype.filter.length);
 
-- 
2.34.1




More information about the wine-devel mailing list