Skip to content

Commit f835a49

Browse files
committed
Core - Basic ArrayBuffer support for EvaluateScriptAsync
1 parent f21a973 commit f835a49

File tree

5 files changed

+86
-1
lines changed

5 files changed

+86
-1
lines changed

CefSharp.BrowserSubprocess.Core/Serialization/V8Serialization.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ namespace CefSharp
7171
{
7272
SetCefTime(list, index, obj->GetDateValue().val);
7373
}
74+
else if (obj->IsArrayBuffer())
75+
{
76+
SetArrayBuffer(list, index, obj->GetArrayBufferByteLength(), obj->GetArrayBufferData());
77+
}
7478
else if (obj->IsArray())
7579
{
7680
int arrLength = obj->GetArrayLength();

CefSharp.Core.Runtime/Internals/Serialization/ObjectsSerialization.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ namespace CefSharp
3838
auto cefTime = GetCefTime(list, index);
3939
result = CefTimeUtils::FromBaseTimeToDateTime(cefTime.val);
4040
}
41+
else if (IsArrayBuffer(list, index))
42+
{
43+
result = GetArrayBuffer(list, index);
44+
}
4145
else if (IsJsCallback(list, index) && javascriptCallbackFactory != nullptr)
4246
{
4347
auto jsCallbackDto = GetJsCallback(list, index);

CefSharp.Core.Runtime/Internals/Serialization/Primitives.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ namespace CefSharp
1919
{
2020
INT64,
2121
CEFTIME,
22-
JSCALLBACK
22+
JSCALLBACK,
23+
ARRAYBUFFER
2324
};
2425

2526
template<typename TList, typename TIndex>
@@ -91,6 +92,39 @@ namespace CefSharp
9192
{
9293
return IsType(PrimitiveType::CEFTIME, list, index);
9394
}
95+
96+
template<typename TList, typename TIndex>
97+
void SetArrayBuffer(const CefRefPtr<TList>& list, TIndex index, const size_t& size, const void* value)
98+
{
99+
const auto src = static_cast<const uint8_t*>(value);
100+
101+
auto dest = new uint8_t[size + 1];
102+
dest[0] = static_cast<uint8_t>(PrimitiveType::ARRAYBUFFER);
103+
memcpy(&dest[1], src, size);
104+
105+
list->SetBinary(index, CefBinaryValue::Create(dest, size + 1));
106+
}
107+
108+
template<typename TList, typename TIndex>
109+
cli::array<Byte>^ GetArrayBuffer(const CefRefPtr<TList>& list, TIndex index)
110+
{
111+
auto binaryValue = list->GetBinary(index);
112+
auto size = binaryValue->GetSize() - 1;
113+
114+
auto bufferByte = gcnew cli::array<Byte>(static_cast<int>(size));
115+
pin_ptr<Byte> src = &bufferByte[0]; // pin pointer to first element in arr
116+
117+
binaryValue->GetData(static_cast<void*>(src), size, 1);
118+
119+
return bufferByte;
120+
}
121+
122+
template<typename TList, typename TIndex>
123+
bool IsArrayBuffer(const CefRefPtr<TList>& list, TIndex index)
124+
{
125+
return IsType(PrimitiveType::ARRAYBUFFER, list, index);
126+
}
127+
94128
template<typename TList, typename TIndex>
95129
void SetJsCallback(const CefRefPtr<TList>& list, TIndex index, JavascriptCallback^ value)
96130
{

CefSharp.Core.Runtime/Internals/Serialization/Primitives.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ namespace CefSharp
2626
template<typename TList, typename TIndex>
2727
bool IsCefTime(const CefRefPtr<TList>& list, TIndex index);
2828

29+
template<typename TList, typename TIndex>
30+
void SetArrayBuffer(const CefRefPtr<TList>& list, TIndex index, const size_t& size, const void* value);
31+
template<typename TList, typename TIndex>
32+
cli::array<Byte>^ GetArrayBuffer(const CefRefPtr<TList>& list, TIndex index);
33+
template<typename TList, typename TIndex>
34+
bool IsArrayBuffer(const CefRefPtr<TList>& list, TIndex index);
35+
2936
template<typename TList, typename TIndex>
3037
void SetJsCallback(const CefRefPtr<TList>& list, TIndex index, JavascriptCallback^ value);
3138
template<typename TList, typename TIndex>
@@ -53,6 +60,16 @@ namespace CefSharp
5360
template bool IsCefTime(const CefRefPtr<CefListValue>& list, int index);
5461
template bool IsCefTime(const CefRefPtr<CefDictionaryValue>& list, CefString index);
5562

63+
template void SetArrayBuffer(const CefRefPtr<CefListValue>& list, int index, const size_t& size, const void* value);
64+
template void SetArrayBuffer(const CefRefPtr<CefListValue>& list, size_t index, const size_t& size, const void* value);
65+
template void SetArrayBuffer(const CefRefPtr<CefDictionaryValue>& list, CefString index, const size_t& size, const void* value);
66+
template cli::array<Byte>^ GetArrayBuffer(const CefRefPtr<CefListValue>& list, int index);
67+
template cli::array<Byte>^ GetArrayBuffer(const CefRefPtr<CefListValue>& list, size_t index);
68+
template cli::array<Byte>^ GetArrayBuffer(const CefRefPtr<CefDictionaryValue>& list, CefString index);
69+
template bool IsArrayBuffer(const CefRefPtr<CefListValue>& list, size_t index);
70+
template bool IsArrayBuffer(const CefRefPtr<CefListValue>& list, int index);
71+
template bool IsArrayBuffer(const CefRefPtr<CefDictionaryValue>& list, CefString index);
72+
5673
template void SetJsCallback(const CefRefPtr<CefListValue>& list, int index, JavascriptCallback^ value);
5774
template void SetJsCallback(const CefRefPtr<CefListValue>& list, size_t index, JavascriptCallback^ value);
5875
template void SetJsCallback(const CefRefPtr<CefDictionaryValue>& list, CefString index, JavascriptCallback^ value);

CefSharp.Test/Javascript/EvaluateScriptAsyncTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
using System;
66
using System.Globalization;
77
using System.Linq;
8+
using System.Text;
89
using System.Threading.Tasks;
10+
using Bogus;
911
using Xunit;
1012
using Xunit.Abstractions;
13+
using Xunit.Repeat;
1114

1215
namespace CefSharp.Test.Javascript
1316
{
@@ -253,6 +256,29 @@ public async Task CanEvaluateScriptAsyncWithEncodedStringArguments()
253256
}
254257
}
255258

259+
[Theory]
260+
[Repeat(20)]
261+
public async Task CanEvaluateScriptAsyncReturnArrayBuffer(int iteration)
262+
{
263+
AssertInitialLoadComplete();
264+
265+
var randomizer = new Randomizer();
266+
267+
var expected = randomizer.Utf16String(minLength: iteration, maxLength:iteration);
268+
var expectedBytes = Encoding.UTF8.GetBytes(expected);
269+
270+
var javascriptResponse = await Browser.EvaluateScriptAsync($"new TextEncoder().encode('{expected}').buffer");
271+
272+
Assert.True(javascriptResponse.Success);
273+
Assert.IsType<byte[]>(javascriptResponse.Result);
274+
275+
var actualBytes = (byte[])javascriptResponse.Result;
276+
277+
Assert.Equal(expectedBytes, actualBytes);
278+
279+
Assert.Equal(expected, Encoding.UTF8.GetString(actualBytes));
280+
}
281+
256282
[Theory]
257283
[InlineData("(async () => { function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }; await sleep(2000); return true; })();")]
258284
public async Task ShouldTimeout(string script)

0 commit comments

Comments
 (0)