Skip to content

Commit 4838dcd

Browse files
committed
In JavaScriptEngineSwitcher.ChakraCore was added the ArrayPool<T> polyfill for .NET Framework 4.0
1 parent c31e72d commit 4838dcd

13 files changed

+504
-31
lines changed

Licenses/dotnet-corefx-license.txt

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) .NET Foundation and Contributors
4+
5+
All rights reserved.
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in all
15+
copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
SOFTWARE.

src/JavaScriptEngineSwitcher.ChakraCore/JavaScriptEngineSwitcher.ChakraCore.csproj

+5
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ This package does not contain the native implementations of ChakraCore. Therefor
6262
<Pack>true</Pack>
6363
<Visible>false</Visible>
6464
</Content>
65+
<Content Include="../../Licenses/dotnet-corefx-license.txt">
66+
<PackagePath>dotnet-corefx-license.txt</PackagePath>
67+
<Pack>true</Pack>
68+
<Visible>false</Visible>
69+
</Content>
6570
<Content Include="../../Licenses/jsrt-dotnet-license.txt">
6671
<PackagePath>jsrt-dotnet-license.txt</PackagePath>
6772
<Pack>true</Pack>

src/JavaScriptEngineSwitcher.ChakraCore/JsRt/JsContext.cs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
2+
#if NET45 || NET471 || NETSTANDARD
23
using System.Runtime.InteropServices;
4+
#endif
35
using System.Text;
46
#if NET40
57

src/JavaScriptEngineSwitcher.ChakraCore/JsRt/JsPropertyId.cs

+4-10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
using JavaScriptEngineSwitcher.Core.Polyfills.System.Runtime.InteropServices;
1010
#endif
1111

12+
#if NET40
13+
using JavaScriptEngineSwitcher.ChakraCore.Polyfills.System.Buffers;
14+
#endif
1215
using JavaScriptEngineSwitcher.ChakraCore.Helpers;
1316

1417
namespace JavaScriptEngineSwitcher.ChakraCore.JsRt
@@ -55,9 +58,8 @@ public string Name
5558
JsErrorHelpers.ThrowIfError(errorCode);
5659

5760
string name;
58-
bufferSize = length;
59-
#if NET45 || NET471 || NETSTANDARD
6061
var byteArrayPool = ArrayPool<byte>.Shared;
62+
bufferSize = length;
6163
buffer = byteArrayPool.Rent((int)bufferSize);
6264

6365
try
@@ -71,14 +73,6 @@ public string Name
7173
{
7274
byteArrayPool.Return(buffer, true);
7375
}
74-
#else
75-
buffer = new byte[(int)bufferSize];
76-
77-
errorCode = NativeMethods.JsCopyPropertyId(this, buffer, bufferSize, out length);
78-
JsErrorHelpers.ThrowIfError(errorCode);
79-
80-
name = Encoding.UTF8.GetString(buffer);
81-
#endif
8276

8377
return name;
8478
}

src/JavaScriptEngineSwitcher.ChakraCore/JsRt/JsValue.cs

+5-21
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#if NET40
88

99
using JavaScriptEngineSwitcher.Core.Polyfills.System.Runtime.InteropServices;
10+
11+
using JavaScriptEngineSwitcher.ChakraCore.Polyfills.System.Buffers;
1012
#endif
1113

1214
namespace JavaScriptEngineSwitcher.ChakraCore.JsRt
@@ -337,7 +339,7 @@ public static JsValue FromInt32(int value)
337339
/// <remarks>
338340
/// Requires an active script context.
339341
/// </remarks>
340-
/// <param name="value">The string to convert to a <c>String</c> value</param>
342+
/// <param name="value">The string to convert to a <c>String</c> value</param>
341343
/// <returns>The new <c>String</c> value</returns>
342344
public static JsValue FromString(string value)
343345
{
@@ -731,9 +733,8 @@ public int ToInt32()
731733
errorCode = NativeMethods.JsCopyStringUtf16(this, start, length, buffer, out written);
732734
JsErrorHelpers.ThrowIfError(errorCode);
733735

734-
length = (int)written;
735-
#if NET45 || NET471 || NETSTANDARD
736736
var charArrayPool = ArrayPool<char>.Shared;
737+
length = (int)written;
737738
buffer = charArrayPool.Rent(length);
738739

739740
try
@@ -747,14 +748,6 @@ public int ToInt32()
747748
{
748749
charArrayPool.Return(buffer, true);
749750
}
750-
#else
751-
buffer = new char[length];
752-
753-
errorCode = NativeMethods.JsCopyStringUtf16(this, start, length, buffer, out written);
754-
JsErrorHelpers.ThrowIfError(errorCode);
755-
756-
result = new string(buffer);
757-
#endif
758751
}
759752
else
760753
{
@@ -765,9 +758,8 @@ public int ToInt32()
765758
errorCode = NativeMethods.JsCopyString(this, buffer, bufferSize, out length);
766759
JsErrorHelpers.ThrowIfError(errorCode);
767760

768-
bufferSize = length;
769-
#if NET45 || NET471 || NETSTANDARD
770761
var byteArrayPool = ArrayPool<byte>.Shared;
762+
bufferSize = length;
771763
buffer = byteArrayPool.Rent((int)bufferSize);
772764

773765
try
@@ -781,14 +773,6 @@ public int ToInt32()
781773
{
782774
byteArrayPool.Return(buffer, true);
783775
}
784-
#else
785-
buffer = new byte[(int)bufferSize];
786-
787-
errorCode = NativeMethods.JsCopyString(this, buffer, bufferSize, out length);
788-
JsErrorHelpers.ThrowIfError(errorCode);
789-
790-
result = Encoding.UTF8.GetString(buffer);
791-
#endif
792776
}
793777

794778
return result;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#if NET40
2+
// Licensed to the .NET Foundation under one or more agreements.
3+
// The .NET Foundation licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for more information.
5+
6+
using System.Runtime.CompilerServices;
7+
using System.Threading;
8+
9+
using JavaScriptEngineSwitcher.ChakraCore.Polyfills.System.Threading;
10+
11+
namespace JavaScriptEngineSwitcher.ChakraCore.Polyfills.System.Buffers
12+
{
13+
/// <summary>
14+
/// Provides a resource pool that enables reusing instances of type <see cref="T:T[]"/>
15+
/// </summary>
16+
/// <remarks>
17+
/// <para>
18+
/// Renting and returning buffers with an <see cref="ArrayPool{T}"/> can increase performance
19+
/// in situations where arrays are created and destroyed frequently, resulting in significant
20+
/// memory pressure on the garbage collector.
21+
/// </para>
22+
/// <para>
23+
/// This class is thread-safe. All members may be used by multiple threads concurrently.
24+
/// </para>
25+
/// </remarks>
26+
internal abstract class ArrayPool<T>
27+
{
28+
/// <summary>
29+
/// The lazily-initialized shared pool instance
30+
/// </summary>
31+
private static ArrayPool<T> s_sharedInstance = null;
32+
33+
/// <summary>
34+
/// Retrieves a shared <see cref="ArrayPool{T}"/> instance
35+
/// </summary>
36+
/// <remarks>
37+
/// The shared pool provides a default implementation of <see cref="ArrayPool{T}"/>
38+
/// that's intended for general applicability. It maintains arrays of multiple sizes, and
39+
/// may hand back a larger array than was actually requested, but will never hand back a smaller
40+
/// array than was requested. Renting a buffer from it with <see cref="Rent"/> will result in an
41+
/// existing buffer being taken from the pool if an appropriate buffer is available or in a new
42+
/// buffer being allocated if one is not available.
43+
/// </remarks>
44+
public static ArrayPool<T> Shared
45+
{
46+
[MethodImpl((MethodImplOptions)256 /* AggressiveInlining */)]
47+
get
48+
{
49+
return Volatile.Read(ref s_sharedInstance) ?? EnsureSharedCreated();
50+
}
51+
}
52+
53+
54+
/// <summary>
55+
/// Ensures that <see cref="s_sharedInstance"/> has been initialized to a pool and returns it
56+
/// </summary>
57+
[MethodImpl(MethodImplOptions.NoInlining)]
58+
private static ArrayPool<T> EnsureSharedCreated()
59+
{
60+
Interlocked.CompareExchange(ref s_sharedInstance, new DefaultArrayPool<T>(), null);
61+
return s_sharedInstance;
62+
}
63+
64+
/// <summary>
65+
/// Retrieves a buffer that is at least the requested length
66+
/// </summary>
67+
/// <remarks>
68+
/// This buffer is loaned to the caller and should be returned to the same pool via
69+
/// <see cref="Return"/> so that it may be reused in subsequent usage of <see cref="Rent"/>.
70+
/// It is not a fatal error to not return a rented buffer, but failure to do so may lead to
71+
/// decreased application performance, as the pool may need to create a new buffer to replace
72+
/// the one lost.
73+
/// </remarks>
74+
/// <param name="minimumLength">The minimum length of the array needed</param>
75+
/// <returns>An <see cref="T:T[]"/> that is at least <paramref name="minimumLength"/> in length</returns>
76+
public abstract T[] Rent(int minimumLength);
77+
78+
/// <summary>
79+
/// Returns to the pool an array that was previously obtained via <see cref="Rent"/> on the same
80+
/// <see cref="ArrayPool{T}"/> instance
81+
/// </summary>
82+
/// <remarks>
83+
/// Once a buffer has been returned to the pool, the caller gives up all ownership of the buffer
84+
/// and must not use it. The reference returned from a given call to <see cref="Rent"/> must only be
85+
/// returned via <see cref="Return"/> once. The default <see cref="ArrayPool{T}"/>
86+
/// may hold onto the returned buffer in order to rent it again, or it may release the returned buffer
87+
/// if it's determined that the pool already has enough buffers stored.
88+
/// </remarks>
89+
/// <param name="array">The buffer previously obtained from <see cref="Rent"/> to return to the pool</param>
90+
/// <param name="clearArray">If <c>true</c> and if the pool will store the buffer to enable subsequent
91+
/// reuse, <see cref="Return"/> will clear <paramref name="array"/> of its contents so that a subsequent
92+
/// consumer via <see cref="Rent"/> will not see the previous consumer's content. If <c>false</c> or
93+
/// if the pool will release the buffer, the array's contents are left unchanged.</param>
94+
public abstract void Return(T[] array, bool clearArray = false);
95+
}
96+
}
97+
#endif

0 commit comments

Comments
 (0)