WinRT DataReader.ReadBytes throws "Invalid number of parameters" error on WebView2
Description
The documentation for DataReader.ReadBytes (https://learn.microsoft.com/en-us/uwp/api/windows.storage.streams.datareader.readbytes?view=winrt-22621) shows that we need to pass an array that will store the bytes that are read. This is how we were using it on WebView1 from JavaScript as well.
On WebView2, calling this method in the same way from JavaScript throws an Invalid number of parameters. 0x8002000E error.
Version WebView2 Version: 1.0.1777-prerelease Framework: UWP, WinRT OS: Win10
Repro Steps:
- Create a WinRT on UWP project with WebView2 following https://learn.microsoft.com/en-us/microsoft-edge/webview2/how-to/winrt-from-js?tabs=winui2%2Cwinrtcsharp
- Run the app. Open the DevTools console and try the following:
const Windows = chrome.webview.hostObjects.sync.Windows;
const capacity = 10;
const buffer = new Windows.Storage.Streams.Buffer(capacity);
const dataReader = Windows.Storage.Streams.DataReader.FromBuffer(buffer);
const bytes = new Uint8Array(capacity);
dataReader.readBytes(bytes);
Output:
Uncaught Error: Invalid number of parameters. (0x8002000E)
at RemoteMessenger.postSyncRequestMessage (<anonymous>:1:16533)
at Function.applyHostFunction (<anonymous>:1:32907)
at Object.apply (<anonymous>:1:22804)
at <anonymous>:1:12
Additional Context
- If I'm understanding the
Windows.Storage.Streams.g.cppfile generated fromwv2winrtcorrectly, this seems to expect no parameters despite the documentation:
// Invoke for method ReadBytes
if (0 == dispParams->cArgs)
{
hr = S_OK;
try
{
auto innerObject = m_innerObject.as<winrt::Windows::Storage::Streams::IDataReader>();
// IDispatch::Invoke DISPPARAMS are in reverse order so we do Count - ParamIdx - 1 below
innerObject.ReadBytes(
RefConverter<winrt::array_view<uint8_t>, VARIANT>(m_dispatchAdapter).ConvertOut(
result
) // Out
);
}
catch (winrt::hresult_error)
{
hr = winrt::to_hresult();
}
catch (...)
{
hr = E_UNEXPECTED;
}
}
else
{
hr = DISP_E_BADPARAMCOUNT;
}
- Calling
DataReader.readBytes()with no paramaters goes through and it returns an array, but the returned array is empty.
Input:
Windows.Storage.FileIO.ReadBufferAsync(file)
.then((buffer) => {
const dataReader = Windows.Storage.Streams.DataReader.FromBuffer(buffer);
console.log(dataReader.readBytes());
});
Output:
[]
Thanks for reporting this issue! ReadBytes has one out parameter and since JavaScript doesn't support out parameters wv2winrt turns that into a return value (see more info on how wv2winrt handles out parameters) - which you figured out from looking at the generated code. So it should be dataReader.readBytes() like you have, but it should be giving you a JavaScript array of the bytes of the file and not an empty array. I've filed a bug to track this, thanks!
Any update on this @david-risney ? It is blocking us from implementing some critical functionality in a webview2 app.
Unfortunately no update yet. You may be able to workaround the issue by creating your own WinRT runtimeclass with method to operate on the data reader or return the values you need with a different type.
This is now fixed in edge 126 and webview2 sdk 1.0.2535.41.
you'll need to set the host objects option for chrome.webview.hostObjects.options.shouldPassTypedArraysAsArrays to true.
Also readBytes is not returning the result not the passed out param.
Please feel free to resolve.
Thanks for confirming @josephsobhy!