From: Olivia Ryan <olivia.r.dev@gmail.com> --- dlls/windows.web/json_object.c | 85 ++++++++++++-- dlls/windows.web/json_value.c | 90 +++++++++++++-- dlls/windows.web/tests/web.c | 197 ++++++++++++++++++++++++++++++++- 3 files changed, 352 insertions(+), 20 deletions(-) diff --git a/dlls/windows.web/json_object.c b/dlls/windows.web/json_object.c index 81f12e2b72d..afb0fc6e1f4 100644 --- a/dlls/windows.web/json_object.c +++ b/dlls/windows.web/json_object.c @@ -121,32 +121,97 @@ static HRESULT WINAPI json_object_statics_SetNamedValue( IJsonObject *iface, HST static HRESULT WINAPI json_object_statics_GetNamedObject( IJsonObject *iface, HSTRING name, IJsonObject **value ) { - FIXME( "iface %p, name %s, value %p stub!\n", iface, debugstr_hstring( name ), value ); - return E_NOTIMPL; + IJsonValue *internal_value; + JsonValueType value_type; + HRESULT hr; + + TRACE( "iface %p, name %s, value %p.\n", iface, debugstr_hstring( name ), value ); + + if (!value) return E_POINTER; + if (FAILED(hr = IJsonObject_GetNamedValue( iface, name, &internal_value ))) + return hr; + + IJsonValue_Release( internal_value ); + IJsonValue_get_ValueType( internal_value, &value_type ); + if (value_type != JsonValueType_Object) return E_ILLEGAL_METHOD_CALL; + + return IJsonValue_GetObject( internal_value, value ); } static HRESULT WINAPI json_object_statics_GetNamedArray( IJsonObject *iface, HSTRING name, IJsonArray **value ) { - FIXME( "iface %p, name %s, value %p stub!\n", iface, debugstr_hstring( name ), value ); - return E_NOTIMPL; + IJsonValue *internal_value; + JsonValueType value_type; + HRESULT hr; + + TRACE( "iface %p, name %s, value %p.\n", iface, debugstr_hstring( name ), value ); + + if (!value) return E_POINTER; + if (FAILED(hr = IJsonObject_GetNamedValue( iface, name, &internal_value ))) + return hr; + + IJsonValue_Release( internal_value ); + IJsonValue_get_ValueType( internal_value, &value_type ); + if (value_type != JsonValueType_Array) return E_ILLEGAL_METHOD_CALL; + + return IJsonValue_GetArray( internal_value, value ); } static HRESULT WINAPI json_object_statics_GetNamedString( IJsonObject *iface, HSTRING name, HSTRING *value ) { - FIXME( "iface %p, name %s, value %p stub!\n", iface, debugstr_hstring( name ), value ); - return E_NOTIMPL; + IJsonValue *internal_value; + JsonValueType value_type; + HRESULT hr; + + TRACE( "iface %p, name %s, value %p.\n", iface, debugstr_hstring( name ), value ); + + if (!value) return E_POINTER; + if (FAILED(hr = IJsonObject_GetNamedValue( iface, name, &internal_value ))) + return hr; + + IJsonValue_Release( internal_value ); + IJsonValue_get_ValueType( internal_value, &value_type ); + if (value_type != JsonValueType_String) return E_ILLEGAL_METHOD_CALL; + + return IJsonValue_GetString( internal_value, value ); } static HRESULT WINAPI json_object_statics_GetNamedNumber( IJsonObject *iface, HSTRING name, DOUBLE *value ) { - FIXME( "iface %p, name %s, value %p stub!\n", iface, debugstr_hstring( name ), value ); - return E_NOTIMPL; + IJsonValue *internal_value; + JsonValueType value_type; + HRESULT hr; + + TRACE( "iface %p, name %s, value %p.\n", iface, debugstr_hstring( name ), value ); + + if (!value) return E_POINTER; + if (FAILED(hr = IJsonObject_GetNamedValue( iface, name, &internal_value ))) + return hr; + + IJsonValue_Release( internal_value ); + IJsonValue_get_ValueType( internal_value, &value_type ); + if (value_type != JsonValueType_Number) return E_ILLEGAL_METHOD_CALL; + + return IJsonValue_GetNumber( internal_value, value ); } static HRESULT WINAPI json_object_statics_GetNamedBoolean( IJsonObject *iface, HSTRING name, boolean *value ) { - FIXME( "iface %p, name %s, value %p stub!\n", iface, debugstr_hstring( name ), value ); - return E_NOTIMPL; + IJsonValue *internal_value; + JsonValueType value_type; + HRESULT hr; + + TRACE( "iface %p, name %s, value %p.\n", iface, debugstr_hstring( name ), value ); + + if (!value) return E_POINTER; + if (FAILED(hr = IJsonObject_GetNamedValue( iface, name, &internal_value ))) + return hr; + + IJsonValue_Release( internal_value ); + IJsonValue_get_ValueType( internal_value, &value_type ); + if (value_type != JsonValueType_Boolean) return E_ILLEGAL_METHOD_CALL; + + return IJsonValue_GetBoolean( internal_value, value ); } static const struct IJsonObjectVtbl json_object_statics_vtbl = diff --git a/dlls/windows.web/json_value.c b/dlls/windows.web/json_value.c index c014b70ae65..6fb5670a014 100644 --- a/dlls/windows.web/json_value.c +++ b/dlls/windows.web/json_value.c @@ -126,6 +126,7 @@ struct json_value double parsed_number; boolean parsed_boolean; IJsonArray *parsed_array; + IJsonObject *parsed_object; }; static inline struct json_value *impl_from_IJsonValue( IJsonValue *iface ) @@ -173,6 +174,7 @@ static ULONG WINAPI json_value_Release( IJsonValue *iface ) { WindowsDeleteString( impl->parsed_string ); if ( impl->parsed_array ) IJsonArray_Release( impl->parsed_array ); + if ( impl->parsed_object ) IJsonObject_Release( impl->parsed_object ); free( impl ); } return ref; @@ -270,12 +272,14 @@ static HRESULT WINAPI json_value_GetObject( IJsonValue *iface, IJsonObject **val { struct json_value *impl = impl_from_IJsonValue( iface ); - FIXME( "iface %p, value %p stub!\n", iface, value ); + TRACE( "iface %p, value %p\n", iface, value ); if (!value) return E_POINTER; if (impl->json_value_type != JsonValueType_Object) return E_ILLEGAL_METHOD_CALL; - return E_NOTIMPL; + IJsonObject_AddRef( impl->parsed_object ); + *value = impl->parsed_object; + return S_OK; } static const struct IJsonValueVtbl json_value_vtbl = @@ -472,12 +476,85 @@ static HRESULT parse_json_string( const WCHAR **json, UINT32 *len, HSTRING *outp return WindowsPromoteStringBuffer( buf, output ); } +static HRESULT parse_json_object( const WCHAR **json, UINT32 *len, struct json_value *impl ) +{ + struct json_value *child; + HSTRING name; + HRESULT hr; + + TRACE( "json %s, impl %p", debugstr_wn( *json, *len ), impl ); + + if (FAILED(hr = IActivationFactory_ActivateInstance( + json_object_factory, (IInspectable**)&impl->parsed_object ))) return hr; + + (*json)++; + (*len)--; + + trim_string( json, len ); + while (*len && **json != '}') + { + if (FAILED(hr = parse_json_string( json, len, &name ))) + { + IJsonObject_Release( impl->parsed_object ); + return hr; + } + + trim_string( json, len ); + if (!*len || **json != ':') + { + IJsonObject_Release( impl->parsed_object ); + WindowsDeleteString( name ); + return WEB_E_INVALID_JSON_STRING; + } + (*json)++; + (*len)--; + trim_string( json, len ); + + if (!(child = calloc( 1, sizeof( *child ) ))) + { + IJsonObject_Release( impl->parsed_object ); + WindowsDeleteString( name ); + return E_OUTOFMEMORY; + } + + child->IJsonValue_iface.lpVtbl = &json_value_vtbl; + child->ref = 1; + + if (FAILED(hr = parse_json_value( json, len, child ))) + { + IJsonValue_Release( &child->IJsonValue_iface ); + IJsonObject_Release( impl->parsed_object ); + WindowsDeleteString( name ); + return hr; + } + + hr = IJsonObject_SetNamedValue( impl->parsed_object, name, &child->IJsonValue_iface ); + IJsonValue_Release( &child->IJsonValue_iface ); + if (FAILED(hr)) + { + IJsonObject_Release( impl->parsed_object ); + WindowsDeleteString( name ); + return hr; + } + + trim_string( json, len ); + if (**json == ',') (*json)++; + else if (**json != '}') return WEB_E_INVALID_JSON_STRING; + trim_string( json, len ); + } + + if (!*len) return WEB_E_INVALID_JSON_STRING; + (*json)++; + (*len)--; + + impl->json_value_type = JsonValueType_Object; + return S_OK; +} + static HRESULT parse_json_value( const WCHAR **json, UINT32 *len, struct json_value *impl ) { HRESULT hr = S_OK; - /* FIXME: Handle all JSON edge cases */ - if (!*len) return WEB_E_INVALID_JSON_STRING; if (*len >= 4 && !wcsncmp( L"null", *json, 4 )) @@ -511,8 +588,7 @@ static HRESULT parse_json_value( const WCHAR **json, UINT32 *len, struct json_va } else if (**json == '{') { - FIXME( "Object parsing not implemented!\n" ); - return WEB_E_INVALID_JSON_STRING; + if (FAILED(hr = parse_json_object( json, len, impl ))) return hr; } else { @@ -552,7 +628,7 @@ static HRESULT WINAPI json_value_statics_Parse( IJsonValueStatics *iface, HSTRIN struct json_value *impl; HRESULT hr; - FIXME( "iface %p, input %s, value %p semi-stub\n", iface, debugstr_hstring( input ), value ); + TRACE( "iface %p, input %s, value %p\n", iface, debugstr_hstring( input ), value ); if (!value) return E_POINTER; if (!input) return WEB_E_INVALID_JSON_STRING; diff --git a/dlls/windows.web/tests/web.c b/dlls/windows.web/tests/web.c index c5332bd4764..8cb66c07585 100644 --- a/dlls/windows.web/tests/web.c +++ b/dlls/windows.web/tests/web.c @@ -241,14 +241,37 @@ static void test_JsonArrayStatics(void) static void test_JsonObjectStatics(void) { + static const WCHAR *json_value_statics_name = L"Windows.Data.Json.JsonValue"; static const WCHAR *json_object_name = L"Windows.Data.Json.JsonObject"; + IJsonValueStatics *json_value_statics = (void *)0xdeadbeef; IActivationFactory *factory = (void *)0xdeadbeef; IInspectable *inspectable = (void *)0xdeadbeef; + IJsonObject *child_object = (void *)0xdeadbeef; IJsonObject *json_object = (void *)0xdeadbeef; + IJsonArray *child_array = (void *)0xdeadbeef; + IJsonValue *child_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_object_name, wcslen( json_object_name ), &str ); ok( hr == S_OK, "got hr %#lx.\n", hr ); hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); @@ -277,9 +300,179 @@ static void test_JsonObjectStatics(void) ok( hr == S_OK, "got hr %#lx.\n", hr ); check_interface( inspectable, &IID_IAgileObject ); + IInspectable_Release( inspectable ); + + hr = WindowsCreateString( L"key", wcslen( L"key" ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + /* key pair does not exist */ + + hr = IJsonObject_GetNamedValue( json_object, NULL, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedValue( json_object, str, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedValue( json_object, NULL, &child_value ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedValue( json_object, str, &child_value ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + + hr = IJsonObject_GetNamedObject( json_object, NULL, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedObject( json_object, str, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedObject( json_object, NULL, &child_object ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedObject( json_object, str, &child_object ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + + hr = IJsonObject_GetNamedArray( json_object, NULL, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedArray( json_object, str, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedArray( json_object, NULL, &child_array ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedArray( json_object, str, &child_array ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + + hr = IJsonObject_GetNamedString( json_object, NULL, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedString( json_object, str, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedString( json_object, NULL, &child_string ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedString( json_object, str, &child_string ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + + hr = IJsonObject_GetNamedNumber( json_object, NULL, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedNumber( json_object, str, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedNumber( json_object, NULL, &child_number ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedNumber( json_object, str, &child_number ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + + hr = IJsonObject_GetNamedBoolean( json_object, NULL, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedBoolean( json_object, str, NULL ); + ok( hr == E_POINTER, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedBoolean( json_object, NULL, &child_boolean ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedBoolean( json_object, str, &child_boolean ); + ok( hr == WEB_E_JSON_VALUE_NOT_FOUND, "got hr %#lx.\n", hr ); + + /* key pair exists */ + + WindowsDeleteString( str ); + hr = WindowsCreateString( L"{}", wcslen( L"{}" ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonValueStatics_Parse( json_value_statics, str, &child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + WindowsDeleteString( str ); + hr = WindowsCreateString( L"key", wcslen( L"key" ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonObject_SetNamedValue( json_object, str, child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedValue( json_object, str, &child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( child_value ); + hr = IJsonObject_GetNamedObject( json_object, str, &child_object ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonObject_Release( child_object ); + hr = IJsonObject_GetNamedArray( json_object, str, &child_array ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedString( json_object, str, &child_string ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedNumber( json_object, str, &child_number ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedBoolean( json_object, str, &child_boolean ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + + WindowsDeleteString( str ); + hr = WindowsCreateString( L"[]", wcslen( L"[]" ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonValueStatics_Parse( json_value_statics, str, &child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + WindowsDeleteString( str ); + hr = WindowsCreateString( L"key", wcslen( L"key" ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonObject_SetNamedValue( json_object, str, child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedValue( json_object, str, &child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( child_value ); + hr = IJsonObject_GetNamedObject( json_object, str, &child_object ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedArray( json_object, str, &child_array ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonArray_Release( child_array ); + hr = IJsonObject_GetNamedString( json_object, str, &child_string ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedNumber( json_object, str, &child_number ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedBoolean( json_object, str, &child_boolean ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + + hr = IJsonValueStatics_CreateStringValue( json_value_statics, str, &child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonObject_SetNamedValue( json_object, str, child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( child_value ); + hr = IJsonObject_GetNamedValue( json_object, str, &child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( child_value ); + hr = IJsonObject_GetNamedObject( json_object, str, &child_object ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedArray( json_object, str, &child_array ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedString( json_object, str, &child_string ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + WindowsDeleteString( child_string ); + hr = IJsonObject_GetNamedNumber( json_object, str, &child_number ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedBoolean( json_object, str, &child_boolean ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + + hr = IJsonValueStatics_CreateNumberValue( json_value_statics, 10, &child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonObject_SetNamedValue( json_object, str, child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( child_value ); + hr = IJsonObject_GetNamedValue( json_object, str, &child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( child_value ); + hr = IJsonObject_GetNamedObject( json_object, str, &child_object ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedArray( json_object, str, &child_array ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedString( json_object, str, &child_string ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedNumber( json_object, str, &child_number ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedBoolean( json_object, str, &child_boolean ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + + hr = IJsonValueStatics_CreateBooleanValue( json_value_statics, FALSE, &child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + hr = IJsonObject_SetNamedValue( json_object, str, child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( child_value ); + hr = IJsonObject_GetNamedValue( json_object, str, &child_value ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + IJsonValue_Release( child_value ); + hr = IJsonObject_GetNamedObject( json_object, str, &child_object ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedArray( json_object, str, &child_array ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedString( json_object, str, &child_string ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedNumber( json_object, str, &child_number ); + ok( hr == E_ILLEGAL_METHOD_CALL, "got hr %#lx.\n", hr ); + hr = IJsonObject_GetNamedBoolean( json_object, str, &child_boolean ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); IJsonObject_Release( json_object ); - IInspectable_Release( inspectable ); + IJsonValueStatics_Release( json_value_statics ); ref = IActivationFactory_Release( factory ); ok( ref == 1, "got ref %ld.\n", ref ); } @@ -306,7 +499,6 @@ static void check_json_( unsigned int line, IJsonValueStatics *json_value_static if (expected_json_value_type == JsonValueType_Number) ok_(__FILE__, line)( hr == WEB_E_INVALID_JSON_NUMBER, "got hr %#lx.\n", hr ); else - todo_wine ok_(__FILE__, line)( hr == WEB_E_INVALID_JSON_STRING, "got hr %#lx.\n", hr ); WindowsDeleteString( str ); @@ -386,7 +578,6 @@ static void check_json_( unsigned int line, IJsonValueStatics *json_value_static break; case JsonValueType_Object: hr = IJsonValue_GetObject( json_value, &json_object ); - todo_wine ok_(__FILE__, line)( hr == S_OK, "got hr %#lx.\n", hr ); if (hr == S_OK) IJsonObject_Release( json_object ); break; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10263