Skip to content

Commit 9070e99

Browse files
authored
fix(ChakraJavaScriptExecutor): Ensure JS arguments are not GC'd (microsoft#752)
A number of users were seeing AccessViolationExceptions, especially in Release builds, where JS strings were being GC'd prior to use. I suspect this is because we need to increment the ref count of the marshalled arguments so they are not collected before use as call arguments. Fixes microsoft#751
1 parent 6ae4661 commit 9070e99

File tree

1 file changed

+43
-19
lines changed

1 file changed

+43
-19
lines changed

ReactWindows/ReactNative/Chakra/Executor/ChakraJavaScriptExecutor.cs

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,26 @@ public JToken CallFunctionReturnFlushedQueue(string moduleName, string methodNam
6464
if (arguments == null)
6565
throw new ArgumentNullException(nameof(arguments));
6666

67-
var method = EnsureCallFunction();
67+
var moduleNameValue = JavaScriptValue.FromString(moduleName);
68+
moduleNameValue.AddRef();
69+
var methodNameValue = JavaScriptValue.FromString(methodName);
70+
methodNameValue.AddRef();
71+
var argumentsValue = ConvertJson(arguments);
72+
argumentsValue.AddRef();
73+
6874
var callArguments = new JavaScriptValue[4];
6975
callArguments[0] = EnsureGlobalObject();
70-
callArguments[1] = JavaScriptValue.FromString(moduleName);
71-
callArguments[2] = JavaScriptValue.FromString(methodName);
72-
callArguments[3] = ConvertJson(arguments);
73-
return ConvertJson(method.CallFunction(callArguments));
76+
callArguments[1] = moduleNameValue;
77+
callArguments[2] = methodNameValue;
78+
callArguments[3] = argumentsValue;
79+
var method = EnsureCallFunction();
80+
var flushedQueue = ConvertJson(method.CallFunction(callArguments));
81+
82+
argumentsValue.Release();
83+
methodNameValue.Release();
84+
moduleNameValue.Release();
85+
86+
return flushedQueue;
7487
}
7588

7689
/// <summary>
@@ -96,12 +109,22 @@ public JToken InvokeCallbackAndReturnFlushedQueue(int callbackId, JArray argumen
96109
if (arguments == null)
97110
throw new ArgumentNullException(nameof(arguments));
98111

99-
var method = EnsureInvokeFunction();
112+
var callbackIdValue = JavaScriptValue.FromInt32(callbackId);
113+
callbackIdValue.AddRef();
114+
var argumentsValue = ConvertJson(arguments);
115+
argumentsValue.AddRef();
116+
100117
var callArguments = new JavaScriptValue[3];
101118
callArguments[0] = EnsureGlobalObject();
102-
callArguments[1] = JavaScriptValue.FromInt32(callbackId);
103-
callArguments[2] = ConvertJson(arguments);
104-
return ConvertJson(method.CallFunction(callArguments));
119+
callArguments[1] = callbackIdValue;
120+
callArguments[2] = argumentsValue;
121+
var method = EnsureInvokeFunction();
122+
var flushedQueue = ConvertJson(method.CallFunction(callArguments));
123+
124+
argumentsValue.Release();
125+
callbackIdValue.Release();
126+
127+
return flushedQueue;
105128
}
106129

107130
/// <summary>
@@ -229,22 +252,23 @@ private JToken ConvertJson(JavaScriptValue value)
229252
#else
230253
private JavaScriptValue ConvertJson(JToken token)
231254
{
255+
var jsonString = token.ToString(Formatting.None);
256+
var jsonStringValue = JavaScriptValue.FromString(jsonString);
257+
jsonStringValue.AddRef();
232258
var parseFunction = EnsureParseFunction();
233-
234-
var json = token.ToString(Formatting.None);
235-
var jsonValue = JavaScriptValue.FromString(json);
236-
237-
return parseFunction.CallFunction(_globalObject, jsonValue);
259+
var jsonValue = parseFunction.CallFunction(_globalObject, jsonStringValue);
260+
jsonStringValue.Release();
261+
return jsonValue;
238262
}
239263

240264
private JToken ConvertJson(JavaScriptValue value)
241265
{
242266
var stringifyFunction = EnsureStringifyFunction();
243-
244-
var jsonValue = stringifyFunction.CallFunction(_globalObject, value);
245-
var json = jsonValue.ToString();
246-
247-
return JToken.Parse(json);
267+
var jsonStringValue = stringifyFunction.CallFunction(_globalObject, value);
268+
jsonStringValue.AddRef();
269+
var jsonString = jsonStringValue.ToString();
270+
jsonStringValue.Release();
271+
return JToken.Parse(jsonString);
248272
}
249273
#endif
250274

0 commit comments

Comments
 (0)