Commit 7be0cffa authored by Gabriel Ivăncescu's avatar Gabriel Ivăncescu Committed by Alexandre Julliard

jscript: Implement fdexNameCaseInsensitive flag handling.

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. Signed-off-by: 's avatarGabriel Ivăncescu <gabrielopcode@gmail.com>
parent 015491ab
......@@ -930,6 +930,124 @@ static void test_aggregation(void)
ok(!unk || broken(unk != NULL), "unk = %p\n", unk);
}
static void test_case_sens(void)
{
static const WCHAR *const names[] = { L"abc", L"foo", L"bar", L"mAth", L"evaL" };
DISPPARAMS dp = { NULL, NULL, 0, 0 };
IActiveScriptParse *parser;
IActiveScript *script;
EXCEPINFO ei = { 0 };
IDispatchEx *disp;
DISPID id, id2;
unsigned i;
HRESULT hr;
VARIANT v;
BSTR bstr;
script = create_jscript();
hr = IActiveScript_QueryInterface(script, &IID_IActiveScriptParse, (void**)&parser);
ok(hr == S_OK, "Could not get IActiveScriptParse iface: %08lx\n", hr);
SET_EXPECT(GetLCID);
hr = IActiveScript_SetScriptSite(script, &ActiveScriptSite);
ok(hr == S_OK, "SetScriptSite failed: %08lx\n", hr);
CHECK_CALLED(GetLCID);
SET_EXPECT(OnStateChange_INITIALIZED);
hr = IActiveScriptParse_InitNew(parser);
ok(hr == S_OK, "InitNew failed: %08lx\n", hr);
CHECK_CALLED(OnStateChange_INITIALIZED);
SET_EXPECT(OnStateChange_CONNECTED);
hr = IActiveScript_SetScriptState(script, SCRIPTSTATE_CONNECTED);
ok(hr == S_OK, "SetScriptState(SCRIPTSTATE_CONNECTED) failed: %08lx\n", hr);
CHECK_CALLED(OnStateChange_CONNECTED);
parse_script(parser, L"var aBc; var abC; function Foo() { }\nFoo.prototype.foo = 13; var Bar = new Foo(); Bar.Foo = 42;");
disp = get_script_dispatch(script, NULL);
for(i = 0; i < ARRAY_SIZE(names); i++) {
bstr = SysAllocString(names[i]);
hr = IDispatchEx_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, &id);
ok(hr == DISP_E_UNKNOWNNAME, "GetIDsOfNames(%s) returned %08lx, expected %08lx\n", debugstr_w(bstr), hr, DISP_E_UNKNOWNNAME);
hr = IDispatchEx_GetDispID(disp, bstr, 0, &id);
ok(hr == DISP_E_UNKNOWNNAME, "GetDispID(%s) returned %08lx, expected %08lx\n", debugstr_w(bstr), hr, DISP_E_UNKNOWNNAME);
hr = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive, &id);
ok(hr == S_OK, "GetDispID(%s) with fdexNameCaseInsensitive failed: %08lx\n", debugstr_w(bstr), hr);
ok(id > 0, "Unexpected DISPID for %s: %ld\n", debugstr_w(bstr), id);
SysFreeString(bstr);
}
get_disp_id(disp, L"Bar", S_OK, &id);
hr = IDispatchEx_InvokeEx(disp, id, 0, DISPATCH_PROPERTYGET, &dp, &v, &ei, NULL);
ok(hr == S_OK, "InvokeEx failed: %08lx\n", hr);
ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
ok(V_DISPATCH(&v) != NULL, "V_DISPATCH(v) = NULL\n");
IDispatchEx_Release(disp);
hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IDispatchEx, (void**)&disp);
ok(hr == S_OK, "Could not get IDispatchEx iface: %08lx\n", hr);
VariantClear(&v);
bstr = SysAllocString(L"foo");
hr = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseSensitive, &id);
ok(hr == S_OK, "GetDispID failed: %08lx\n", hr);
/* 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);
hr = IDispatchEx_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, &id2);
ok(hr == S_OK, "GetIDsOfNames failed: %08lx\n", hr);
ok(id == id2, "id != id2\n");
hr = IDispatchEx_DeleteMemberByName(disp, bstr, fdexNameCaseInsensitive);
ok(hr == S_OK, "DeleteMemberByName failed: %08lx\n", hr);
hr = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive, &id2);
ok(hr == S_OK, "GetDispID failed: %08lx\n", hr);
ok(id == id2, "id != id2\n");
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);
bstr = SysAllocString(L"fOo");
hr = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive, &id2);
ok(hr == S_OK, "GetDispID failed: %08lx\n", hr);
ok(id == id2, "id != id2\n");
hr = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive | fdexNameEnsure, &id2);
ok(hr == S_OK, "GetDispID failed: %08lx\n", hr);
ok(id == id2, "id != id2\n");
hr = IDispatchEx_GetDispID(disp, bstr, fdexNameEnsure, &id2);
ok(hr == S_OK, "GetDispID failed: %08lx\n", hr);
ok(id != id2, "id == id2\n");
hr = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive | fdexNameEnsure, &id2);
ok(hr == S_OK, "GetDispID failed: %08lx\n", hr);
SysFreeString(bstr);
IDispatchEx_Release(disp);
IActiveScriptParse_Release(parser);
SET_EXPECT(OnStateChange_DISCONNECTED);
SET_EXPECT(OnStateChange_INITIALIZED);
SET_EXPECT(OnStateChange_CLOSED);
hr = IActiveScript_Close(script);
ok(hr == S_OK, "Close failed: %08lx\n", hr);
CHECK_CALLED(OnStateChange_DISCONNECTED);
CHECK_CALLED(OnStateChange_INITIALIZED);
CHECK_CALLED(OnStateChange_CLOSED);
IActiveScript_Release(script);
}
static void test_param_ids(void)
{
static const WCHAR *const names1[] = { L"test", L"c", L"foo", L"b", L"a" };
......@@ -2324,6 +2442,7 @@ START_TEST(jscript)
test_jscript2();
test_jscript_uninitializing();
test_aggregation();
test_case_sens();
test_param_ids();
test_code_persistence();
test_named_items();
......
......@@ -33,6 +33,18 @@ var JS_E_WRONG_THIS = 0x800a13fc;
var tests = [];
sync_test("script vars", function() {
function foo() { }
foo.prototype.foo = 13;
var obj = new foo();
obj.Foo = 42;
obj.aBc = 1;
obj.abC = 2;
obj.Bar = 3;
document.body.foobar = 42;
external.testVars(document.body, obj);
});
sync_test("date_now", function() {
var now = Date.now();
var time = (new Date()).getTime();
......
......@@ -155,6 +155,7 @@ DEFINE_EXPECT(GetTypeInfo);
#define DISPID_EXTERNAL_NULL_DISP 0x300008
#define DISPID_EXTERNAL_IS_ENGLISH 0x300009
#define DISPID_EXTERNAL_LIST_SEP 0x30000A
#define DISPID_EXTERNAL_TEST_VARS 0x30000B
static const GUID CLSID_TestScript =
{0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x07,0x46}};
......@@ -198,6 +199,95 @@ static BOOL init_key(const char *key_name, const char *def_value, BOOL init)
return res == ERROR_SUCCESS;
}
static void test_script_vars(unsigned argc, VARIANTARG *argv)
{
static const WCHAR *const jsobj_names[] = { L"abc", L"foO", L"bar", L"TostRing", L"hasownpropERty" };
IHTMLBodyElement *body;
IDispatchEx *disp;
DISPID id, id2;
HRESULT hres;
unsigned i;
BSTR bstr;
ok(argc == 2, "argc = %d\n", argc);
ok(V_VT(&argv[0]) == VT_DISPATCH, "VT = %d\n", V_VT(&argv[0]));
ok(V_VT(&argv[1]) == VT_DISPATCH, "VT = %d\n", V_VT(&argv[1]));
/* JS object disp */
hres = IDispatch_QueryInterface(V_DISPATCH(&argv[0]), &IID_IDispatchEx, (void**)&disp);
ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres);
hres = IDispatchEx_QueryInterface(disp, &IID_IHTMLBodyElement, (void**)&body);
ok(hres == E_NOINTERFACE, "Got IHTMLBodyElement iface on JS object? %08lx\n", hres);
for(i = 0; i < ARRAY_SIZE(jsobj_names); i++) {
bstr = SysAllocString(jsobj_names[i]);
hres = IDispatchEx_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, &id);
ok(hres == DISP_E_UNKNOWNNAME, "GetIDsOfNames(%s) returned %08lx, expected %08lx\n", debugstr_w(bstr), hres, DISP_E_UNKNOWNNAME);
hres = IDispatchEx_GetDispID(disp, bstr, 0, &id);
ok(hres == DISP_E_UNKNOWNNAME, "GetDispID(%s) returned %08lx, expected %08lx\n", debugstr_w(bstr), hres, DISP_E_UNKNOWNNAME);
hres = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive, &id);
ok(hres == S_OK, "GetDispID(%s) with fdexNameCaseInsensitive failed: %08lx\n", debugstr_w(bstr), hres);
ok(id > 0, "Unexpected DISPID for %s: %ld\n", debugstr_w(bstr), id);
SysFreeString(bstr);
}
bstr = SysAllocString(L"foo");
hres = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseSensitive, &id);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
/* 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);
hres = IDispatchEx_GetIDsOfNames(disp, &IID_NULL, &bstr, 1, 0, &id2);
ok(hres == S_OK, "GetIDsOfNames failed: %08lx\n", hres);
ok(id == id2, "id != id2\n");
hres = IDispatchEx_DeleteMemberByName(disp, bstr, fdexNameCaseInsensitive);
ok(hres == S_OK, "DeleteMemberByName failed: %08lx\n", hres);
hres = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive, &id2);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
ok(id == id2, "id != id2\n");
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);
bstr = SysAllocString(L"fOo");
hres = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive, &id2);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
ok(id == id2, "id != id2\n");
hres = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive | fdexNameEnsure, &id2);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
ok(id == id2, "id != id2\n");
hres = IDispatchEx_GetDispID(disp, bstr, fdexNameEnsure, &id2);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
ok(id != id2, "id == id2\n");
hres = IDispatchEx_GetDispID(disp, bstr, fdexNameCaseInsensitive | fdexNameEnsure, &id2);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
SysFreeString(bstr);
IDispatchEx_Release(disp);
/* Body element disp */
hres = IDispatch_QueryInterface(V_DISPATCH(&argv[1]), &IID_IDispatchEx, (void**)&disp);
ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres);
hres = IDispatchEx_QueryInterface(disp, &IID_IHTMLBodyElement, (void**)&body);
ok(hres == S_OK, "Could not get IHTMLBodyElement iface: %08lx\n", hres);
IHTMLBodyElement_Release(body);
IDispatchEx_Release(disp);
}
static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface,
REFIID riid, void**ppv)
{
......@@ -609,6 +699,10 @@ static HRESULT WINAPI externalDisp_GetDispID(IDispatchEx *iface, BSTR bstrName,
*pid = DISPID_EXTERNAL_LIST_SEP;
return S_OK;
}
if(!lstrcmpW(bstrName, L"testVars")) {
*pid = DISPID_EXTERNAL_TEST_VARS;
return S_OK;
}
ok(0, "unexpected name %s\n", wine_dbgstr_w(bstrName));
return DISP_E_UNKNOWNNAME;
......@@ -833,6 +927,15 @@ static HRESULT WINAPI externalDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID
return S_OK;
}
case DISPID_EXTERNAL_TEST_VARS:
ok(pdp != NULL, "pdp == NULL\n");
ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
ok(pei != NULL, "pei == NULL\n");
test_script_vars(pdp->cArgs, pdp->rgvarg);
return S_OK;
default:
ok(0, "unexpected call\n");
return E_NOTIMPL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment