Module: wine Branch: master Commit: 605819dcd94b1b1b4843fa869ed15402bdc8a18b URL: https://gitlab.winehq.org/wine/wine/-/commit/605819dcd94b1b1b4843fa869ed1540...
Author: Gabriel Ivăncescu gabrielopcode@gmail.com Date: Mon Oct 10 19:55:22 2022 +0300
jscript: Refill the props at end of enumeration in html mode and retry.
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 gabrielopcode@gmail.com
---
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 = '<form id="testid" name="testname"></form>';