From 605819dcd94b1b1b4843fa869ed15402bdc8a18b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Iv=C4=83ncescu?= Date: Mon, 10 Oct 2022 19:55:22 +0300 Subject: [PATCH] jscript: Refill the props at end of enumeration in html mode and retry. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If properties were added during enumeration, for example on the prototype, they are actually visited in mshtml scripts in any mode. Signed-off-by: Gabriel Ivăncescu --- dlls/jscript/dispex.c | 13 ++++++++----- dlls/jscript/tests/lang.js | 2 ++ dlls/mshtml/tests/documentmode.js | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 746c5246ed1..42f41771ef2 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -2492,16 +2492,16 @@ HRESULT jsdisp_next_prop(jsdisp_t *obj, DISPID id, enum jsdisp_enum_type enum_ty DWORD idx = id; HRESULT hres; - if(id == DISPID_STARTENUM) { + if(id == DISPID_STARTENUM || idx >= obj->prop_cnt) { hres = (enum_type == JSDISP_ENUM_ALL) ? fill_protrefs(obj) : fill_props(obj); if(FAILED(hres)) return hres; - idx = 0; + if(id == DISPID_STARTENUM) + idx = 0; + if(idx >= obj->prop_cnt) + return S_FALSE; } - if(idx >= obj->prop_cnt) - return S_FALSE; - for(iter = &obj->props[idx]; iter < obj->props + obj->prop_cnt; iter++) { if(iter->type == PROP_DELETED) continue; @@ -2513,6 +2513,9 @@ HRESULT jsdisp_next_prop(jsdisp_t *obj, DISPID id, enum jsdisp_enum_type enum_ty return S_OK; } + if(obj->ctx->html_mode) + return jsdisp_next_prop(obj, prop_to_id(obj, iter - 1), enum_type, ret); + return S_FALSE; } diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index 67e4576813b..5c201d5bf26 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -1559,6 +1559,7 @@ inobj.test2 = true; tmp = 0; for(iter in inobj) { + forinTestObj.prototype.test4 = true; arr[iter] = true; tmp++; } @@ -1567,6 +1568,7 @@ ok(tmp === 3, "for..in tmp = " + tmp); ok(arr["test1"] === true, "arr[test1] !== true"); ok(arr["test2"] === true, "arr[test2] !== true"); ok(arr["test3"] === true, "arr[test3] !== true"); +ok(arr["test4"] !== true, "arr[test4] === true"); ok((delete inobj.test1) === true, "delete inobj.test1 returned false"); ok(!("test1" in inobj), "test1 is still in inobj after delete"); diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 90223d53f83..cb6d2d01ec2 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -634,6 +634,26 @@ sync_test("JS objs", function() { test_parses("if(false) { o.if; }", v >= 9); }); +sync_test("for..in", function() { + function ctor() {} + ctor.prototype.test2 = true; + + var arr = new Array(), obj = new ctor(), i, r; + obj.test1 = true; + + i = 0; + for(var r in obj) { + ctor.prototype.test3 = true; + arr[r] = true; + i++; + } + + ok(i === 3, "enum did " + i + " iterations"); + ok(arr["test1"] === true, "arr[test1] !== true"); + ok(arr["test2"] === true, "arr[test2] !== true"); + ok(arr["test3"] === true, "arr[test3] !== true"); +}); + sync_test("elem_by_id", function() { document.body.innerHTML = '
';