mshtml/tests: Add initial tests for NULL Dispatch objects in scripts.

Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Gabriel Ivăncescu 2022-04-12 17:47:31 +03:00 committed by Alexandre Julliard
parent 3349dc5eea
commit 3485f162e9
3 changed files with 222 additions and 0 deletions

View File

@ -1322,6 +1322,64 @@ sync_test("builtins_diffs", function() {
}
});
sync_test("nullDisp", function() {
var v = document.documentMode, nullDisp = external.nullDisp, r;
todo_wine.
ok(external.getVT(nullDisp) === "VT_NULL", "getVT(nullDisp) is not VT_NULL");
ok(typeof(nullDisp) === "object", "typeof(nullDisp) = " + typeof(nullDisp));
ok(nullDisp === nullDisp, "nullDisp !== nullDisp");
ok(nullDisp === null, "nullDisp === null");
ok(nullDisp == null, "nullDisp == null");
ok(!nullDisp === true, "!nullDisp = " + !nullDisp);
ok(String(nullDisp) === "null", "String(nullDisp) = " + String(nullDisp));
ok(+nullDisp === 0, "+nullDisp !== 0");
ok(''+nullDisp === "null", "''+nullDisp !== null");
ok(nullDisp != new Object(), "nullDisp == new Object()");
ok(new Object() != nullDisp, "new Object() == nullDisp");
ok((typeof Object(nullDisp)) === "object", "typeof Object(nullDisp) !== 'object'");
r = Object(nullDisp).toString();
ok(r === "[object Object]", "Object(nullDisp).toString() = " + r);
ok(Object(nullDisp) != nullDisp, "Object(nullDisp) == nullDisp");
ok(new Object(nullDisp) != nullDisp, "new Object(nullDisp) == nullDisp");
if(v >= 8) {
r = JSON.stringify.call(null, nullDisp);
todo_wine.
ok(r === "null", "JSON.stringify(nullDisp) returned " + r);
}
try {
(new Object()) instanceof nullDisp;
ok(false, "expected exception on (new Object()) instanceof nullDisp");
}catch(e) {
ok(e.number === 0xa138a - 0x80000000, "(new Object()) instanceof nullDisp threw " + e.number);
}
try {
Function.prototype.apply.call(nullDisp, Object, []);
ok(false, "expected exception calling Function.apply on nullDisp");
}catch(e) {
todo_wine.
ok(e.number === 0xa138a - 0x80000000, "Function.apply on nullDisp threw " + e.number);
}
try {
Function.prototype.call.call(nullDisp, Object);
ok(false, "expected exception calling Function.call on nullDisp");
}catch(e) {
todo_wine.
ok(e.number === 0xa138a - 0x80000000, "Function.call on nullDisp threw " + e.number);
}
try {
new nullDisp;
ok(false, "expected exception for new nullDisp");
}catch(e) {
todo_wine.
ok(e.number === 0xa138f - 0x80000000, "new nullDisp threw " + e.number);
}
});
sync_test("__proto__", function() {
var v = document.documentMode;
var r, x = 42;

View File

@ -298,9 +298,25 @@ sync_test("getOwnPropertyDescriptor", function() {
test_own_data_prop_desc(function(){}, "prototype", true, false, false);
test_own_data_prop_desc(Function, "prototype", false, false, false);
test_own_data_prop_desc(String.prototype, "constructor", true, false, true);
try {
Object.getOwnPropertyDescriptor(null, "prototype");
ok(false, "expected exception with null");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "with null context threw " + n);
}
try {
Object.getOwnPropertyDescriptor(external.nullDisp, "prototype");
ok(false, "expected exception calling getOwnPropertyDescriptor(nullDisp)");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "getOwnPropertyDescriptor(nullDisp) threw " + n);
}
});
sync_test("defineProperty", function() {
var nullDisp = external.nullDisp;
function test_accessor_prop_desc(obj, prop, orig_desc) {
var expected_enumerable = "enumerable" in orig_desc && !!orig_desc.enumerable;
var expected_configurable = "configurable" in orig_desc && !!orig_desc.configurable;
@ -548,6 +564,16 @@ sync_test("defineProperty", function() {
Object.defineProperty(obj, "funcprop", desc);
test_accessor_prop_desc(obj, "funcprop", desc);
ok(obj.funcprop(100) === 10, "obj.funcprop() = " + obj.funcprop(100));
expect_exception(function() {
Object.defineProperty(null, "funcprop", desc);
}, JS_E_OBJECT_EXPECTED);
expect_exception(function() {
Object.defineProperty(nullDisp, "funcprop", desc);
}, JS_E_OBJECT_EXPECTED);
expect_exception(function() {
Object.defineProperty(obj, "funcprop", nullDisp);
}, JS_E_OBJECT_EXPECTED);
});
sync_test("defineProperties", function() {
@ -831,6 +857,13 @@ sync_test("getPrototypeOf", function() {
ok(Object.getPrototypeOf(obj) === null, "Object.getPrototypeOf(obj) = " + Object.getPrototypeOf(obj));
ok(Object.getPrototypeOf(external) === null, "Object.getPrototypeOf(non-JS obj) = " + Object.getPrototypeOf(external));
try {
Object.getOwnPropertyDescriptor(external.nullDisp);
ok(false, "expected exception calling getOwnPropertyDescriptor(nullDisp)");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "getOwnPropertyDescriptor(nullDisp) threw " + n);
}
});
sync_test("toString", function() {
@ -956,6 +989,14 @@ sync_test("keys", function() {
ok(keys === "", "keys([]) = " + keys);
ok(Object.keys.length === 1, "Object.keys.length = " + Object.keys.length);
try {
Object.keys(external.nullDisp);
ok(false, "expected exception calling keys(nullDisp)");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "keys(nullDisp) threw " + n);
}
});
sync_test("getOwnPropertyNames", function() {
@ -980,6 +1021,14 @@ sync_test("getOwnPropertyNames", function() {
ok(names === "length", "names = " + names);
ok(Object.getOwnPropertyNames.length === 1, "Object.getOwnPropertyNames.length = " + Object.getOwnPropertyNames.length);
try {
Object.getOwnPropertyNames(external.nullDisp);
ok(false, "expected exception calling getOwnPropertyNames(nullDisp)");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "getOwnPropertyNames(nullDisp) threw " + n);
}
});
sync_test("reduce", function() {
@ -1091,6 +1140,14 @@ sync_test("preventExtensions", function() {
ok(Object.preventExtensions.length === 1, "Object.preventExtensions.length = " + Object.preventExtensions.length);
ok(Object.isExtensible.length === 1, "Object.isExtensible.length = " + Object.isExtensible.length);
try {
Object.preventExtensions(external.nullDisp);
ok(false, "expected exception calling preventExtensions(nullDisp)");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "preventExtensions(nullDisp) threw " + n);
}
});
sync_test("freeze", function() {
@ -1143,6 +1200,14 @@ sync_test("freeze", function() {
}
ok(o[0] === 1, "o[0] = " + o[0]);
ok(o.length === 1, "o.length = " + o.length);
try {
Object.freeze(external.nullDisp);
ok(false, "expected exception freeze(nullDisp)");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "freeze(nullDisp) threw " + n);
}
});
sync_test("seal", function() {
@ -1195,9 +1260,18 @@ sync_test("seal", function() {
}
ok(o[0] === 1, "o[0] = " + o[0]);
ok(o.length === 1, "o.length = " + o.length);
try {
Object.seal(external.nullDisp);
ok(false, "expected exception calling seal(nullDisp)");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "seal(nullDisp) threw " + n);
}
});
sync_test("isFrozen", function() {
var nullDisp = external.nullDisp;
ok(Object.isFrozen.length === 1, "Object.isFrozen.length = " + Object.isFrozen.length);
ok(Object.isSealed.length === 1, "Object.isSealed.length = " + Object.isSealed.length);
@ -1263,6 +1337,28 @@ sync_test("isFrozen", function() {
ok(Object.isFrozen(o) === true, "o is not frozen");
ok(Object.isSealed(o) === true, "o is not sealed");
ok(Object.isExtensible(o) === false, "o is extensible");
try {
Object.isFrozen(nullDisp);
ok(false, "expected exception calling isFrozen(nullDisp)");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "isFrozen(nullDisp) threw " + n);
}
try {
Object.isSealed(nullDisp);
ok(false, "expected exception calling isSealed(nullDisp)");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "isSealed(nullDisp) threw " + n);
}
try {
Object.isExtensible(nullDisp);
ok(false, "expected exception calling isExtensible(nullDisp)");
}catch(ex) {
var n = ex.number >>> 0;
ok(n === JS_E_OBJECT_EXPECTED, "isExtensible(nullDisp) threw " + n);
}
});
sync_test("builtin_context", function() {

View File

@ -151,6 +151,8 @@ DEFINE_EXPECT(GetTypeInfo);
#define DISPID_EXTERNAL_BROKEN 0x300004
#define DISPID_EXTERNAL_WIN_SKIP 0x300005
#define DISPID_EXTERNAL_WRITESTREAM 0x300006
#define DISPID_EXTERNAL_GETVT 0x300007
#define DISPID_EXTERNAL_NULL_DISP 0x300008
static const GUID CLSID_TestScript =
{0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x07,0x46}};
@ -589,6 +591,14 @@ static HRESULT WINAPI externalDisp_GetDispID(IDispatchEx *iface, BSTR bstrName,
*pid = DISPID_EXTERNAL_WRITESTREAM;
return S_OK;
}
if(!lstrcmpW(bstrName, L"getVT")) {
*pid = DISPID_EXTERNAL_GETVT;
return S_OK;
}
if(!lstrcmpW(bstrName, L"nullDisp")) {
*pid = DISPID_EXTERNAL_NULL_DISP;
return S_OK;
}
ok(0, "unexpected name %s\n", wine_dbgstr_w(bstrName));
return DISP_E_UNKNOWNNAME;
@ -716,6 +726,64 @@ static HRESULT WINAPI externalDisp_InvokeEx(IDispatchEx *iface, DISPID id, LCID
stream_write(V_BSTR(pdp->rgvarg+1), V_BSTR(pdp->rgvarg));
return S_OK;
case DISPID_EXTERNAL_GETVT:
ok(pdp != NULL, "pdp == NULL\n");
ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
ok(pvarRes != NULL, "pvarRes == NULL\n");
ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
ok(pei != NULL, "pei == NULL\n");
V_VT(pvarRes) = VT_BSTR;
switch(V_VT(pdp->rgvarg)) {
case VT_EMPTY:
V_BSTR(pvarRes) = SysAllocString(L"VT_EMPTY");
break;
case VT_NULL:
V_BSTR(pvarRes) = SysAllocString(L"VT_NULL");
break;
case VT_I4:
V_BSTR(pvarRes) = SysAllocString(L"VT_I4");
break;
case VT_R8:
V_BSTR(pvarRes) = SysAllocString(L"VT_R8");
break;
case VT_BSTR:
V_BSTR(pvarRes) = SysAllocString(L"VT_BSTR");
break;
case VT_DISPATCH:
V_BSTR(pvarRes) = SysAllocString(L"VT_DISPATCH");
break;
case VT_BOOL:
V_BSTR(pvarRes) = SysAllocString(L"VT_BOOL");
break;
case VT_DATE:
V_BSTR(pvarRes) = SysAllocString(L"VT_DATE");
break;
default:
ok(0, "unknown vt %d\n", V_VT(pdp->rgvarg));
return E_FAIL;
}
return S_OK;
case DISPID_EXTERNAL_NULL_DISP:
ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags);
ok(pdp != NULL, "pdp == NULL\n");
ok(!pdp->rgvarg, "rgvarg != NULL\n");
ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
ok(!pdp->cArgs, "cArgs = %d\n", pdp->cArgs);
ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
ok(pvarRes != NULL, "pvarRes == NULL\n");
ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pvarRes) = %d\n", V_VT(pvarRes));
ok(pei != NULL, "pei == NULL\n");
V_VT(pvarRes) = VT_DISPATCH;
V_DISPATCH(pvarRes) = NULL;
return S_OK;
default:
ok(0, "unexpected call\n");
return E_NOTIMPL;