Despite common sense, native doesn't seem to look for exact match first; it simply case-insensitively compares the props and returns as soon as it finds one. This is also reliant on implementation details in case the object has multiple props with same case-insensitive names, e.g. an object having `Foo` prop, with `foo` prop on its prototype, can still find `Foo` even if you look up `foo` instead (which matches exactly on the prototype). Which is not always reliable, sometimes it finds the prototype first.
See the following diff to illustrate possible behavior on native (which is what I get). Note that especially for jscript, the behavior makes no sense logically; first it picks 'Foo', despite 'foo' being available on the prototype (i.e. exact match). You might think it just looks up on props first, and prototype later, but the second ok() added shows that it finds the prototype's prop first, instead!
```diff
diff --git a/dlls/jscript/tests/jscript.c b/dlls/jscript/tests/jscript.c
index 03774da..2428363 100644
--- a/dlls/jscript/tests/jscript.c
+++ b/dlls/jscript/tests/jscript.c
@@ -999,6 +999,7 @@ static void test_case_sens(void)
/* Native picks one "arbitrarily" here, depending how it's laid out, so can't compare exact id */
hr = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive, &id2);
ok(hr == S_OK, "GetDispID failed: %08lx\n", hr);
+ ok(id != id2, "id == id2\n");
hr = IDispatchEx_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, &id2);
ok(hr == S_OK, "GetIDsOfNames failed: %08lx\n", hr);
@@ -1031,6 +1032,7 @@ static void test_case_sens(void)
hr = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive | fdexNameEnsure, &id2);
ok(hr == S_OK, "GetDispID failed: %08lx\n", hr);
+ ok(id == id2, "id != id2\n");
SysFreeString(bstr);
IDispatchEx_Release(disp);
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c
index 14e3a14..563b87a 100644
--- a/dlls/mshtml/tests/script.c
+++ b/dlls/mshtml/tests/script.c
@@ -241,6 +241,7 @@ static void test_script_vars(unsigned argc, VARIANTARG *argv)
/* Native picks one "arbitrarily" here, depending how it's laid out, so can't compare exact id */
hres = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive, &id2);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+ ok(id != id2, "id == id2\n");
hres = IDispatchEx_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, &id2);
ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres);
@@ -273,6 +274,7 @@ static void test_script_vars(unsigned argc, VARIANTARG *argv)
hres = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive | fdexNameEnsure, &id2);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+ ok(id != id2, "id == id2\n");
SysFreeString(bstr);
IDispatchEx_Release(disp);
```
Strangely, mshtml's jscript still finds the prop on the object the second time, but that could be to different underlying implementation. I don't think it's necessary to replicate this quirk.
The main point of this case insensitive handling is that it will be needed later when IE9+ modes use jscript proxy objects for the mshtml objects, because those default to case-insensitive search in GetIDsOfNames, likely to preserve backwards compatibility with pre-IE9 modes. It's a weird quirk, I know, but we have tests for that, which would otherwise break when proxies get added. I'll also add more tests around it later, to prove this, of course, that it also applies to jscript props (e.g. hasOwnProperty on the prototype is still looked case-insensitively if GetIDsOfNames is used).
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/656
Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com>
--
v2: comctl32/edit: Handle IME composition result string only when EIMES_GETCOMPSTRATONCE is set.
comctl32/edit: Let DefWindowProcW() handle WM_IME_CHAR.
comctl32/edit: Implement EM_GETIMESTATUS.
comctl32/edit: Implement EM_SETIMESTATUS.
comctl32/tests: Add IME tests for edit control.
https://gitlab.winehq.org/wine/wine/-/merge_requests/627