Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core - Basic ArrayBuffer support for EvaluateScriptAsync #4632

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ namespace CefSharp
{
SetCefTime(list, index, obj->GetDateValue().val);
}
else if (obj->IsArrayBuffer())
{
SetArrayBuffer(list, index, obj->GetArrayBufferByteLength(), obj->GetArrayBufferData());
}
else if (obj->IsArray())
{
int arrLength = obj->GetArrayLength();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ namespace CefSharp
auto cefTime = GetCefTime(list, index);
result = CefTimeUtils::FromBaseTimeToDateTime(cefTime.val);
}
else if (IsArrayBuffer(list, index))
{
result = GetArrayBuffer(list, index);
}
else if (IsJsCallback(list, index) && javascriptCallbackFactory != nullptr)
{
auto jsCallbackDto = GetJsCallback(list, index);
Expand Down
36 changes: 35 additions & 1 deletion CefSharp.Core.Runtime/Internals/Serialization/Primitives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ namespace CefSharp
{
INT64,
CEFTIME,
JSCALLBACK
JSCALLBACK,
ARRAYBUFFER
};

template<typename TList, typename TIndex>
Expand Down Expand Up @@ -91,6 +92,39 @@ namespace CefSharp
{
return IsType(PrimitiveType::CEFTIME, list, index);
}

template<typename TList, typename TIndex>
void SetArrayBuffer(const CefRefPtr<TList>& list, TIndex index, const size_t& size, const void* value)
{
const auto src = static_cast<const uint8_t*>(value);

auto dest = new uint8_t[size + 1];
dest[0] = static_cast<uint8_t>(PrimitiveType::ARRAYBUFFER);
memcpy(&dest[1], src, size);

list->SetBinary(index, CefBinaryValue::Create(dest, size + 1));
}

template<typename TList, typename TIndex>
cli::array<Byte>^ GetArrayBuffer(const CefRefPtr<TList>& list, TIndex index)
{
auto binaryValue = list->GetBinary(index);
auto size = binaryValue->GetSize() - 1;

auto bufferByte = gcnew cli::array<Byte>(static_cast<int>(size));
pin_ptr<Byte> src = &bufferByte[0]; // pin pointer to first element in arr

binaryValue->GetData(static_cast<void*>(src), size, 1);

return bufferByte;
}

template<typename TList, typename TIndex>
bool IsArrayBuffer(const CefRefPtr<TList>& list, TIndex index)
{
return IsType(PrimitiveType::ARRAYBUFFER, list, index);
}

template<typename TList, typename TIndex>
void SetJsCallback(const CefRefPtr<TList>& list, TIndex index, JavascriptCallback^ value)
{
Expand Down
17 changes: 17 additions & 0 deletions CefSharp.Core.Runtime/Internals/Serialization/Primitives.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ namespace CefSharp
template<typename TList, typename TIndex>
bool IsCefTime(const CefRefPtr<TList>& list, TIndex index);

template<typename TList, typename TIndex>
void SetArrayBuffer(const CefRefPtr<TList>& list, TIndex index, const size_t& size, const void* value);
template<typename TList, typename TIndex>
cli::array<Byte>^ GetArrayBuffer(const CefRefPtr<TList>& list, TIndex index);
template<typename TList, typename TIndex>
bool IsArrayBuffer(const CefRefPtr<TList>& list, TIndex index);

template<typename TList, typename TIndex>
void SetJsCallback(const CefRefPtr<TList>& list, TIndex index, JavascriptCallback^ value);
template<typename TList, typename TIndex>
Expand Down Expand Up @@ -53,6 +60,16 @@ namespace CefSharp
template bool IsCefTime(const CefRefPtr<CefListValue>& list, int index);
template bool IsCefTime(const CefRefPtr<CefDictionaryValue>& list, CefString index);

template void SetArrayBuffer(const CefRefPtr<CefListValue>& list, int index, const size_t& size, const void* value);
template void SetArrayBuffer(const CefRefPtr<CefListValue>& list, size_t index, const size_t& size, const void* value);
template void SetArrayBuffer(const CefRefPtr<CefDictionaryValue>& list, CefString index, const size_t& size, const void* value);
template cli::array<Byte>^ GetArrayBuffer(const CefRefPtr<CefListValue>& list, int index);
template cli::array<Byte>^ GetArrayBuffer(const CefRefPtr<CefListValue>& list, size_t index);
template cli::array<Byte>^ GetArrayBuffer(const CefRefPtr<CefDictionaryValue>& list, CefString index);
template bool IsArrayBuffer(const CefRefPtr<CefListValue>& list, size_t index);
template bool IsArrayBuffer(const CefRefPtr<CefListValue>& list, int index);
template bool IsArrayBuffer(const CefRefPtr<CefDictionaryValue>& list, CefString index);

template void SetJsCallback(const CefRefPtr<CefListValue>& list, int index, JavascriptCallback^ value);
template void SetJsCallback(const CefRefPtr<CefListValue>& list, size_t index, JavascriptCallback^ value);
template void SetJsCallback(const CefRefPtr<CefDictionaryValue>& list, CefString index, JavascriptCallback^ value);
Expand Down
26 changes: 26 additions & 0 deletions CefSharp.Test/Javascript/EvaluateScriptAsyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Bogus;
using Xunit;
using Xunit.Abstractions;
using Xunit.Repeat;

namespace CefSharp.Test.Javascript
{
Expand Down Expand Up @@ -253,6 +256,29 @@ public async Task CanEvaluateScriptAsyncWithEncodedStringArguments()
}
}

[Theory]
[Repeat(20)]
public async Task CanEvaluateScriptAsyncReturnArrayBuffer(int iteration)
{
AssertInitialLoadComplete();

var randomizer = new Randomizer();

var expected = randomizer.Utf16String(minLength: iteration, maxLength:iteration);
var expectedBytes = Encoding.UTF8.GetBytes(expected);

var javascriptResponse = await Browser.EvaluateScriptAsync($"new TextEncoder().encode('{expected}').buffer");

Assert.True(javascriptResponse.Success);
Assert.IsType<byte[]>(javascriptResponse.Result);

var actualBytes = (byte[])javascriptResponse.Result;

Assert.Equal(expectedBytes, actualBytes);

Assert.Equal(expected, Encoding.UTF8.GetString(actualBytes));
}

[Theory]
[InlineData("(async () => { function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }; await sleep(2000); return true; })();")]
public async Task ShouldTimeout(string script)
Expand Down