Skip to content

Commit 098b023

Browse files
committed
Fixed a error #65 “Memory leak using EmbedHostObject”
1 parent 715df3a commit 098b023

15 files changed

+1223
-687
lines changed

src/JavaScriptEngineSwitcher.ChakraCore/ChakraCoreJsEngine.cs

Lines changed: 14 additions & 658 deletions
Large diffs are not rendered by default.

src/JavaScriptEngineSwitcher.ChakraCore/JavaScriptEngineSwitcher.ChakraCore.csproj

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,7 @@ This package does not contain the native implementations of ChakraCore. Therefor
2222
* JavaScriptEngineSwitcher.ChakraCore.Native.osx-x64</Description>
2323
<PackageIconUrl>https://raw.githubusercontent.com/Taritsyn/JavaScriptEngineSwitcher/master/Icons/JavaScriptEngineSwitcher_ChakraCore_Logo128x128.png</PackageIconUrl>
2424
<PackageTags>JavaScriptEngineSwitcher;JavaScript;ECMAScript;ChakraCore</PackageTags>
25-
<PackageReleaseNotes>1. ChakraCore was updated to version 1.11.4;
26-
2. No longer used the old ChakraCore API for Windows (Internet Explorer-like API);
27-
3. Added a ability to interrupt execution of the script;
28-
4. Added a ability to pre-compile scripts;
29-
5. In configuration settings of the ChakraCore JS engine was added one new property - `MaxStackSize` (default `492` or `984` KB);
30-
6. Added support of .NET Framework 4.7.1, .NET Standard 2.0 and .NET Core App 2.1.</PackageReleaseNotes>
25+
<PackageReleaseNotes>Fixed a error #65 “Memory leak using EmbedHostObject”.</PackageReleaseNotes>
3126
</PropertyGroup>
3227

3328
<Import Project="../../build/common.props" />

src/JavaScriptEngineSwitcher.ChakraCore/JsRt/DefaultExternalBufferFinalizeCallback.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ internal static class DefaultExternalBufferFinalizeCallback
1010
/// <summary>
1111
/// Gets a instance of default callback for finalization of external buffer
1212
/// </summary>
13-
public static readonly JsObjectFinalizeCallback Instance = Marshal.FreeHGlobal;
13+
public static readonly JsFinalizeCallback Instance = Marshal.FreeHGlobal;
1414
}
1515
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
using JavaScriptEngineSwitcher.Core.Utilities;
5+
6+
namespace JavaScriptEngineSwitcher.ChakraCore.JsRt.Embedding
7+
{
8+
/// <summary>
9+
/// Embedded item
10+
/// </summary>
11+
internal abstract class EmbeddedItem : IDisposable
12+
{
13+
/// <summary>
14+
/// Host type
15+
/// </summary>
16+
private Type _hostType;
17+
18+
/// <summary>
19+
/// Instance of host type
20+
/// </summary>
21+
private object _hostObject;
22+
23+
/// <summary>
24+
/// JavaScript value created from an host item
25+
/// </summary>
26+
private readonly JsValue _scriptValue;
27+
28+
/// <summary>
29+
/// List of native functions, that used to access to members of host item
30+
/// </summary>
31+
private IList<JsNativeFunction> _nativeFunctions;
32+
33+
/// <summary>
34+
/// Flag indicating whether this object is disposed
35+
/// </summary>
36+
private readonly InterlockedStatedFlag _disposedFlag = new InterlockedStatedFlag();
37+
38+
/// <summary>
39+
/// Gets a host type
40+
/// </summary>
41+
public Type HostType
42+
{
43+
get { return _hostType; }
44+
}
45+
46+
/// <summary>
47+
/// Gets a instance of host type
48+
/// </summary>
49+
public object HostObject
50+
{
51+
get { return _hostObject; }
52+
}
53+
54+
/// <summary>
55+
/// Gets a JavaScript value created from an host item
56+
/// </summary>
57+
public JsValue ScriptValue
58+
{
59+
get { return _scriptValue; }
60+
}
61+
62+
/// <summary>
63+
/// Gets a list of native functions, that used to access to members of host item
64+
/// </summary>
65+
public IList<JsNativeFunction> NativeFunctions
66+
{
67+
get { return _nativeFunctions; }
68+
}
69+
70+
/// <summary>
71+
/// Gets a value that indicates if the host item is an instance
72+
/// </summary>
73+
public abstract bool IsInstance
74+
{
75+
get;
76+
}
77+
78+
79+
/// <summary>
80+
/// Constructs an instance of the embedded item
81+
/// </summary>
82+
/// <param name="hostType">Host type</param>
83+
/// <param name="hostObject">Instance of host type</param>
84+
/// <param name="scriptValue">JavaScript value created from an host item</param>
85+
/// <param name="nativeFunctions">List of native functions, that used to access to members of host item</param>
86+
protected EmbeddedItem(Type hostType, object hostObject, JsValue scriptValue,
87+
IList<JsNativeFunction> nativeFunctions)
88+
{
89+
_hostType = hostType;
90+
_hostObject = hostObject;
91+
_scriptValue = scriptValue;
92+
_nativeFunctions = nativeFunctions;
93+
}
94+
95+
96+
#region IDisposable implementation
97+
98+
/// <summary>
99+
/// Disposes the embedded item
100+
/// </summary>
101+
public void Dispose()
102+
{
103+
if (_disposedFlag.Set())
104+
{
105+
_hostType = null;
106+
_hostObject = null;
107+
108+
IList<JsNativeFunction> nativeFunctions = _nativeFunctions;
109+
if (nativeFunctions != null)
110+
{
111+
nativeFunctions.Clear();
112+
_nativeFunctions = null;
113+
}
114+
}
115+
}
116+
117+
#endregion
118+
}
119+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System.Collections.Generic;
2+
3+
namespace JavaScriptEngineSwitcher.ChakraCore.JsRt.Embedding
4+
{
5+
/// <summary>
6+
/// Embedded object
7+
/// </summary>
8+
internal sealed class EmbeddedObject : EmbeddedItem
9+
{
10+
/// <summary>
11+
/// Constructs an instance of the embedded object
12+
/// </summary>
13+
/// <param name="hostObject">Instance of host type</param>
14+
/// <param name="scriptValue">JavaScript value created from an host object</param>
15+
public EmbeddedObject(object hostObject, JsValue scriptValue)
16+
: base(hostObject.GetType(), hostObject, scriptValue, new List<JsNativeFunction>())
17+
{ }
18+
19+
/// <summary>
20+
/// Constructs an instance of the embedded object
21+
/// </summary>
22+
/// <param name="hostObject">Instance of host type</param>
23+
/// <param name="scriptValue">JavaScript value created from an host object</param>
24+
/// <param name="nativeFunctions">List of native functions, that used to access to members of host object</param>
25+
public EmbeddedObject(object hostObject, JsValue scriptValue,
26+
IList<JsNativeFunction> nativeFunctions)
27+
: base(hostObject.GetType(), hostObject, scriptValue, nativeFunctions)
28+
{ }
29+
30+
#region EmbeddedItem overrides
31+
32+
/// <summary>
33+
/// Gets a value that indicates if the host item is an instance
34+
/// </summary>
35+
public override bool IsInstance
36+
{
37+
get { return true; }
38+
}
39+
40+
#endregion
41+
}
42+
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
5+
using JavaScriptEngineSwitcher.ChakraCore.Resources;
6+
7+
namespace JavaScriptEngineSwitcher.ChakraCore.JsRt.Embedding
8+
{
9+
/// <summary>
10+
/// Key for storage of embedded objects
11+
/// </summary>
12+
internal struct EmbeddedObjectKey : IEquatable<EmbeddedObjectKey>, IStructuralEquatable,
13+
IComparable, IComparable<EmbeddedObjectKey>, IStructuralComparable
14+
{
15+
/// <summary>
16+
/// Name of host type
17+
/// </summary>
18+
public readonly string HostTypeName;
19+
20+
/// <summary>
21+
/// Instance of host type
22+
/// </summary>
23+
public readonly object HostObject;
24+
25+
26+
/// <summary>
27+
/// Constructs an instance of the key for storage of embedded objects
28+
/// </summary>
29+
/// <param name="hostObject">Instance of host type</param>
30+
public EmbeddedObjectKey(object hostObject)
31+
{
32+
HostTypeName = hostObject.GetType().AssemblyQualifiedName;
33+
HostObject = hostObject;
34+
}
35+
36+
37+
private static int CombineHashCodes(int h1, int h2)
38+
{
39+
return ((h1 << 5) + h1) ^ h2;
40+
}
41+
42+
#region IEquatable<EmbeddedObjectKey> implementation
43+
44+
public bool Equals(EmbeddedObjectKey other)
45+
{
46+
return EqualityComparer<string>.Default.Equals(HostTypeName, other.HostTypeName)
47+
&& EqualityComparer<object>.Default.Equals(HostObject, other.HostObject);
48+
}
49+
50+
#endregion
51+
52+
#region IStructuralEquatable implementation
53+
54+
bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
55+
{
56+
if (other == null || !(other is EmbeddedObjectKey))
57+
{
58+
return false;
59+
}
60+
61+
var embeddedObjectKey = (EmbeddedObjectKey)other;
62+
63+
return comparer.Equals(HostTypeName, embeddedObjectKey.HostTypeName)
64+
&& comparer.Equals(HostObject, embeddedObjectKey.HostObject);
65+
}
66+
67+
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
68+
{
69+
return CombineHashCodes(comparer.GetHashCode(HostTypeName), comparer.GetHashCode(HostObject));
70+
}
71+
72+
#endregion
73+
74+
#region IComparable implementation
75+
76+
int IComparable.CompareTo(object other)
77+
{
78+
if (other == null)
79+
{
80+
return 1;
81+
}
82+
83+
if (!(other is EmbeddedObjectKey))
84+
{
85+
throw new ArgumentException(
86+
string.Format(Strings.Common_ArgumentHasIncorrectType, nameof(other), other.GetType().Name),
87+
nameof(other)
88+
);
89+
}
90+
91+
return CompareTo((EmbeddedObjectKey)other);
92+
}
93+
94+
#endregion
95+
96+
#region IComparable<EmbeddedObjectKey> implementation
97+
98+
public int CompareTo(EmbeddedObjectKey other)
99+
{
100+
int c = Comparer<string>.Default.Compare(HostTypeName, other.HostTypeName);
101+
if (c != 0)
102+
{
103+
return c;
104+
}
105+
106+
return Comparer<object>.Default.Compare(HostObject, other.HostObject);
107+
}
108+
109+
#endregion
110+
111+
#region IStructuralComparable implementation
112+
113+
int IStructuralComparable.CompareTo(object other, IComparer comparer)
114+
{
115+
if (other == null)
116+
{
117+
return 1;
118+
}
119+
120+
if (!(other is EmbeddedObjectKey))
121+
{
122+
throw new ArgumentException(
123+
string.Format(Strings.Common_ArgumentHasIncorrectType, nameof(other), other.GetType().Name),
124+
nameof(other)
125+
);
126+
}
127+
128+
var embeddedObjectKey = (EmbeddedObjectKey)other;
129+
130+
int c = comparer.Compare(HostTypeName, embeddedObjectKey.HostTypeName);
131+
if (c != 0)
132+
{
133+
return c;
134+
}
135+
136+
return comparer.Compare(HostObject, embeddedObjectKey.HostObject);
137+
}
138+
139+
#endregion
140+
141+
#region Object overrides
142+
143+
public override bool Equals(object obj)
144+
{
145+
return obj is EmbeddedObjectKey && Equals((EmbeddedObjectKey)obj);
146+
}
147+
148+
public override int GetHashCode()
149+
{
150+
return CombineHashCodes(EqualityComparer<string>.Default.GetHashCode(HostTypeName),
151+
EqualityComparer<object>.Default.GetHashCode(HostObject));
152+
}
153+
154+
public override string ToString()
155+
{
156+
return "(" + HostTypeName?.ToString() + ", " + HostObject?.ToString() + ")";
157+
}
158+
159+
#endregion
160+
}
161+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace JavaScriptEngineSwitcher.ChakraCore.JsRt.Embedding
5+
{
6+
/// <summary>
7+
/// Embedded type
8+
/// </summary>
9+
internal sealed class EmbeddedType : EmbeddedItem
10+
{
11+
/// <summary>
12+
/// Constructs an instance of the embedded type
13+
/// </summary>
14+
/// <param name="hostType">Host type</param>
15+
/// <param name="scriptValue">JavaScript value created from an host type</param>
16+
public EmbeddedType(Type hostType, JsValue scriptValue)
17+
: base(hostType, null, scriptValue, new List<JsNativeFunction>())
18+
{ }
19+
20+
/// <summary>
21+
/// Constructs an instance of the embedded type
22+
/// </summary>
23+
/// <param name="hostType">Host type</param>
24+
/// <param name="scriptValue">JavaScript value created from an host type</param>
25+
/// <param name="nativeFunctions">List of native functions, that used to access to members of type</param>
26+
public EmbeddedType(Type hostType, JsValue scriptValue, IList<JsNativeFunction> nativeFunctions)
27+
: base(hostType, null, scriptValue, nativeFunctions)
28+
{ }
29+
30+
#region EmbeddedItem overrides
31+
32+
/// <summary>
33+
/// Gets a value that indicates if the host item is an instance
34+
/// </summary>
35+
public override bool IsInstance
36+
{
37+
get { return false; }
38+
}
39+
40+
#endregion
41+
}
42+
}

0 commit comments

Comments
 (0)