[PATCH 02/10] mshtml/tests: Add initial tests for NULL Dispatch objects in scripts.

Gabriel Ivăncescu gabrielopcode at gmail.com
Tue Apr 12 09:47:31 CDT 2022


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/mshtml/tests/documentmode.js | 58 +++++++++++++++++++
 dlls/mshtml/tests/es5.js          | 96 +++++++++++++++++++++++++++++++
 dlls/mshtml/tests/script.c        | 68 ++++++++++++++++++++++
 3 files changed, 222 insertions(+)

diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index 55de9b7..5f475cc 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -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;
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index 6baebbd..14ec4f9 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -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() {
diff --git a/dlls/mshtml/tests/script.c b/dlls/mshtml/tests/script.c
index de42e89..ceb4fc7 100644
--- a/dlls/mshtml/tests/script.c
+++ b/dlls/mshtml/tests/script.c
@@ -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;
-- 
2.34.1




More information about the wine-devel mailing list