From: Olivia Ryan <olivia.r.dev@gmail.com> --- dlls/windows.web/json_array.c | 64 ++++++++++--- dlls/windows.web/tests/web.c | 164 ++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+), 10 deletions(-) diff --git a/dlls/windows.web/json_array.c b/dlls/windows.web/json_array.c index d62427d92d1..c48b868e062 100644 --- a/dlls/windows.web/json_array.c +++ b/dlls/windows.web/json_array.c @@ -26,6 +26,8 @@ struct json_array { IJsonArray IJsonArray_iface; LONG ref; + IJsonValue **elements; + ULONG length; }; static inline struct json_array *impl_from_IJsonArray( IJsonArray *iface ) @@ -66,7 +68,17 @@ static ULONG WINAPI json_array_statics_Release( IJsonArray *iface ) { struct json_array *impl = impl_from_IJsonArray( iface ); ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + + if (!ref) + { + for (UINT32 i = 0; i < impl->length; i++) + IJsonValue_Release( impl->elements[i] ); + + if (impl->elements) free( impl->elements ); + free( impl ); + } return ref; } @@ -90,32 +102,62 @@ static HRESULT WINAPI json_array_statics_GetTrustLevel( IJsonArray *iface, Trust static HRESULT WINAPI json_array_statics_GetObjectAt( IJsonArray *iface, UINT32 index, IJsonObject **value ) { - FIXME( "iface %p, index %u, value %p\n", iface, index, value ); - return E_NOTIMPL; + struct json_array *impl = impl_from_IJsonArray( iface ); + + TRACE( "iface %p, index %u, value %p\n", iface, index, value ); + + if (!value) return E_INVALIDARG; + if (index >= impl->length) return E_BOUNDS; + + return IJsonValue_GetObject( impl->elements[index], value ); } static HRESULT WINAPI json_array_statics_GetArrayAt( IJsonArray *iface, UINT32 index, IJsonArray **value ) { - FIXME( "iface %p, index %u, value %p\n", iface, index, value ); - return E_NOTIMPL; + struct json_array *impl = impl_from_IJsonArray( iface ); + + TRACE( "iface %p, index %u, value %p\n", iface, index, value ); + + if (!value) return E_INVALIDARG; + if (index >= impl->length) return E_BOUNDS; + + return IJsonValue_GetArray( impl->elements[index], value ); } static HRESULT WINAPI json_array_statics_GetStringAt( IJsonArray *iface, UINT32 index, HSTRING *value ) { - FIXME( "iface %p, index %u, value %p\n", iface, index, value ); - return E_NOTIMPL; + struct json_array *impl = impl_from_IJsonArray( iface ); + + TRACE( "iface %p, index %u, value %p\n", iface, index, value ); + + if (!value) return E_INVALIDARG; + if (index >= impl->length) return E_BOUNDS; + + return IJsonValue_GetString( impl->elements[index], value ); } static HRESULT WINAPI json_array_statics_GetNumberAt( IJsonArray *iface, UINT32 index, double *value ) { - FIXME( "iface %p, index %u, value %p\n", iface, index, value ); - return E_NOTIMPL; + struct json_array *impl = impl_from_IJsonArray( iface ); + + TRACE( "iface %p, index %u, value %p\n", iface, index, value ); + + if (!value) return E_INVALIDARG; + if (index >= impl->length) return E_BOUNDS; + + return IJsonValue_GetNumber( impl->elements[index], value ); } static HRESULT WINAPI json_array_statics_GetBooleanAt( IJsonArray *iface, UINT32 index, boolean *value ) { - FIXME( "iface %p, index %u, value %p\n", iface, index, value ); - return E_NOTIMPL; + struct json_array *impl = impl_from_IJsonArray( iface ); + + TRACE( "iface %p, index %u, value %p\n", iface, index, value ); + + if (!value) return E_INVALIDARG; + if (index >= impl->length) return E_BOUNDS; + + return IJsonValue_GetBoolean( impl->elements[index], value ); } static const struct IJsonArrayVtbl json_array_statics_vtbl = @@ -212,6 +254,8 @@ static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInsp impl->IJsonArray_iface.lpVtbl = &json_array_statics_vtbl; impl->ref = 1; + impl->elements = NULL; + impl->length = 0; *instance = (IInspectable*)&impl->IJsonArray_iface; return S_OK; diff --git a/dlls/windows.web/tests/web.c b/dlls/windows.web/tests/web.c index 84a1f3e850a..87c7f7fb66a 100644 --- a/dlls/windows.web/tests/web.c +++ b/dlls/windows.web/tests/web.c @@ -47,14 +47,37 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid ) static void test_JsonArrayStatics(void) { + static const WCHAR *json_value_statics_name = L"Windows.Data.Json.JsonValue"; static const WCHAR *json_array_name = L"Windows.Data.Json.JsonArray"; + IJsonValueStatics *json_value_statics = (void *)0xdeadbeef; IActivationFactory *factory = (void *)0xdeadbeef; IInspectable *inspectable = (void *)0xdeadbeef; + IJsonObject *child_object = (void *)0xdeadbeef; + IJsonArray *child_array = (void *)0xdeadbeef; IJsonArray *json_array = (void *)0xdeadbeef; + IJsonValue *json_value = (void *)0xdeadbeef; + BOOLEAN child_boolean; + HSTRING child_string; + DOUBLE child_number; HSTRING str = NULL; HRESULT hr; LONG ref; + hr = WindowsCreateString( json_value_statics_name, wcslen( json_value_statics_name ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); + WindowsDeleteString( str ); + ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( json_value_statics_name ) ); + return; + } + + hr = IActivationFactory_QueryInterface( factory, &IID_IJsonValueStatics, (void **)&json_value_statics ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ref = IActivationFactory_Release( factory ); + hr = WindowsCreateString( json_array_name, wcslen( json_array_name ), &str ); ok( hr == S_OK, "got hr %#lx.\n", hr ); hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); @@ -84,10 +107,151 @@ static void test_JsonArrayStatics(void) check_interface( inspectable, &IID_IAgileObject ); + hr = IJsonArray_GetObjectAt( json_array, 0, NULL ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetObjectAt( json_array, 0, &child_object ); + ok( hr == E_BOUNDS, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetArrayAt( json_array, 0, NULL ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetArrayAt( json_array, 0, &child_array ); + ok( hr == E_BOUNDS, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetStringAt( json_array, 0, NULL ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetStringAt( json_array, 0, &child_string ); + ok( hr == E_BOUNDS, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetNumberAt( json_array, 0, NULL ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetNumberAt( json_array, 0, &child_number ); + ok( hr == E_BOUNDS, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetBooleanAt( json_array, 0, NULL ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetBooleanAt( json_array, 0, &child_boolean ); + ok( hr == E_BOUNDS, "got hr %#lx.\n", hr ); + IJsonArray_Release( json_array ); IInspectable_Release( inspectable ); ref = IActivationFactory_Release( factory ); ok( ref == 1, "got ref %ld.\n", ref ); + + hr = WindowsCreateString( L"[{}]", wcslen( L"[{}]" ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonValueStatics_Parse( json_value_statics, str, &json_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + WindowsDeleteString( str ); + if (SUCCEEDED(hr)) + { + hr = IJsonValue_GetArray( json_value, &json_array ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( json_value ); + hr = IJsonArray_GetObjectAt( json_array, 0, &child_object ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonObject_Release( child_object ); + hr = IJsonArray_GetArrayAt( json_array, 0, &child_array ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetStringAt( json_array, 0, &child_string ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetNumberAt( json_array, 0, &child_number ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetBooleanAt( json_array, 0, &child_boolean ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + IJsonArray_Release( json_array ); + } + + hr = WindowsCreateString( L"[[]]", wcslen( L"[[]]" ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonValueStatics_Parse( json_value_statics, str, &json_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + WindowsDeleteString( str ); + if (SUCCEEDED(hr)) + { + hr = IJsonValue_GetArray( json_value, &json_array ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( json_value ); + hr = IJsonArray_GetObjectAt( json_array, 0, &child_object ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetArrayAt( json_array, 0, &child_array ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonArray_Release( child_array ); + hr = IJsonArray_GetStringAt( json_array, 0, &child_string ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetNumberAt( json_array, 0, &child_number ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetBooleanAt( json_array, 0, &child_boolean ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + IJsonArray_Release( json_array ); + } + + hr = WindowsCreateString( L"[\"Hello, World!\"]", wcslen( L"[\"Hello, World!\"]" ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonValueStatics_Parse( json_value_statics, str, &json_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + WindowsDeleteString( str ); + if (SUCCEEDED(hr)) + { + hr = IJsonValue_GetArray( json_value, &json_array ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( json_value ); + hr = IJsonArray_GetObjectAt( json_array, 0, &child_object ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetArrayAt( json_array, 0, &child_array ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetStringAt( json_array, 0, &child_string ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + WindowsDeleteString( child_string ); + hr = IJsonArray_GetNumberAt( json_array, 0, &child_number ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetBooleanAt( json_array, 0, &child_boolean ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + IJsonArray_Release( json_array ); + } + + hr = WindowsCreateString( L"[12.6]", wcslen( L"[12.6]" ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonValueStatics_Parse( json_value_statics, str, &json_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + WindowsDeleteString( str ); + if (SUCCEEDED(hr)) + { + hr = IJsonValue_GetArray( json_value, &json_array ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( json_value ); + hr = IJsonArray_GetObjectAt( json_array, 0, &child_object ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetArrayAt( json_array, 0, &child_array ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetStringAt( json_array, 0, &child_string ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetNumberAt( json_array, 0, &child_number ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetBooleanAt( json_array, 0, &child_boolean ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + IJsonArray_Release( json_array ); + } + + hr = WindowsCreateString( L"[true]", wcslen( L"[true]" ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonValueStatics_Parse( json_value_statics, str, &json_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + WindowsDeleteString( str ); + if (SUCCEEDED(hr)) + { + hr = IJsonValue_GetArray( json_value, &json_array ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( json_value ); + hr = IJsonArray_GetObjectAt( json_array, 0, &child_object ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetArrayAt( json_array, 0, &child_array ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetStringAt( json_array, 0, &child_string ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetNumberAt( json_array, 0, &child_number ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonArray_GetBooleanAt( json_array, 0, &child_boolean ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonArray_Release( json_array ); + } + + IJsonValueStatics_Release( json_value_statics ); } static void test_JsonObjectStatics(void) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10263