Implements IReactBridge and IJavaScriptExecutor
Decided to pursue an IJavaScriptExecutor after all. The reason is because the IJavaScriptExecutor can be pre-initialized the with React Native JavaScript library, without having any of that logic leak into the bridge or catalyst instance. The IJavaScriptExecutor implementation uses Chakra, and we included some simple mapping visitors from JToken to JavaScriptValue and visa versa. The current ReactBridge is a trivial wrapper around the IJavaScriptExecutor, that has some knowledge of the React Native protocols. This changelist also includes some minor fixes to the DllImports for Chakra, which should eventually be refactored into a library (along with the JToken -> JavaScriptValue converters).
This commit is contained in:
Родитель
0935062f79
Коммит
58d5323e04
|
@ -2,6 +2,7 @@
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using ReactNative.Bridge.Queue;
|
using ReactNative.Bridge.Queue;
|
||||||
using ReactNative.Common;
|
using ReactNative.Common;
|
||||||
|
using ReactNative.Hosting.Bridge;
|
||||||
using ReactNative.Tracing;
|
using ReactNative.Tracing;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -123,7 +124,6 @@ namespace ReactNative.Bridge
|
||||||
_registry.NotifyCatalystInstanceDispose();
|
_registry.NotifyCatalystInstanceDispose();
|
||||||
_catalystQueueConfiguration.Dispose();
|
_catalystQueueConfiguration.Dispose();
|
||||||
// TODO: notify bridge idle listeners
|
// TODO: notify bridge idle listeners
|
||||||
_bridge.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task InitializeBridgeAsync()
|
private Task InitializeBridgeAsync()
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
namespace ReactNative.Bridge
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ReactNative.Bridge
|
||||||
{
|
{
|
||||||
public interface IJavaScriptExecutor
|
public interface IJavaScriptExecutor : IDisposable
|
||||||
{
|
{
|
||||||
// TODO
|
JToken Call(string moduleName, string methodName, JArray arguments);
|
||||||
|
|
||||||
|
void SetGlobalVariable(string propertyName, JToken value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace ReactNative.Bridge
|
||||||
/// Interface to the JavaScript execution environment and means of
|
/// Interface to the JavaScript execution environment and means of
|
||||||
/// transport for messages between JavaScript and the native environment.
|
/// transport for messages between JavaScript and the native environment.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IReactBridge : IDisposable
|
public interface IReactBridge
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calls a JavaScript function.
|
/// Calls a JavaScript function.
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using ReactNative.Bridge.Queue;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace ReactNative.Bridge
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class to the JavaScript execution environment and means of transport
|
|
||||||
/// for messages between JavaScript and the native environment.
|
|
||||||
/// </summary>
|
|
||||||
public class ReactBridge : IReactBridge
|
|
||||||
{
|
|
||||||
private readonly IJavaScriptExecutor _jsExecutor;
|
|
||||||
private readonly IReactCallback _reactCallback;
|
|
||||||
private readonly IMessageQueueThread _nativeModulesQueueThread;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Instantiates the <see cref="IReactBridge"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="jsExecutor">The JavaScript executor.</param>
|
|
||||||
/// <param name="reactCallback">The native callback handler.</param>
|
|
||||||
/// <param name="nativeModulesQueueThread">
|
|
||||||
/// The native modules queue thread.
|
|
||||||
/// </param>
|
|
||||||
public ReactBridge(
|
|
||||||
IJavaScriptExecutor jsExecutor,
|
|
||||||
IReactCallback reactCallback,
|
|
||||||
IMessageQueueThread nativeModulesQueueThread)
|
|
||||||
{
|
|
||||||
_jsExecutor = jsExecutor;
|
|
||||||
_reactCallback = reactCallback;
|
|
||||||
_nativeModulesQueueThread = nativeModulesQueueThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Calls a JavaScript function.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="moduleId">The module ID.</param>
|
|
||||||
/// <param name="methodId">The method ID.</param>
|
|
||||||
/// <param name="arguments">The arguments.</param>
|
|
||||||
public void CallFunction(int moduleId, int methodId, JArray arguments)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes a JavaScript callback.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="callbackID">The callback ID.</param>
|
|
||||||
/// <param name="arguments">The arguments.</param>
|
|
||||||
public void InvokeCallback(int callbackID, JArray arguments)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets a global JavaScript variable.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="propertyName">The property name.</param>
|
|
||||||
/// <param name="jsonEncodedArgument">The JSON-encoded value.</param>
|
|
||||||
public void SetGlobalVariable(string propertyName, string jsonEncodedArgument)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Disposes the bridge.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using ReactNative.Bridge;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace ReactNative.Hosting.Bridge
|
||||||
|
{
|
||||||
|
class ChakraJavaScriptExecutor : IJavaScriptExecutor
|
||||||
|
{
|
||||||
|
private readonly JavaScriptRuntime _runtime;
|
||||||
|
private readonly JavaScriptValue _globalObject;
|
||||||
|
private readonly JavaScriptValue _requireFunction;
|
||||||
|
|
||||||
|
public ChakraJavaScriptExecutor()
|
||||||
|
{
|
||||||
|
_runtime = JavaScriptRuntime.Create();
|
||||||
|
_globalObject = JavaScriptValue.GlobalObject;
|
||||||
|
var requireId = JavaScriptPropertyId.FromString("require");
|
||||||
|
_requireFunction = _globalObject.GetProperty(requireId);
|
||||||
|
|
||||||
|
InitializeChakra();
|
||||||
|
|
||||||
|
// TODO: resolve how to inject React JavaScript library
|
||||||
|
}
|
||||||
|
|
||||||
|
public JToken Call(string moduleName, string methodName, JArray arguments)
|
||||||
|
{
|
||||||
|
// Get the module
|
||||||
|
var moduleString = JavaScriptValue.FromString(moduleName);
|
||||||
|
var requireArguments = new[] { _globalObject, moduleString };
|
||||||
|
var module = _requireFunction.CallFunction(requireArguments);
|
||||||
|
|
||||||
|
// Get the method
|
||||||
|
var propertyId = JavaScriptPropertyId.FromString(methodName);
|
||||||
|
var method = module.GetProperty(propertyId);
|
||||||
|
|
||||||
|
// Set up the arguments to pass in
|
||||||
|
var callArguments = new JavaScriptValue[arguments.Count + 1];
|
||||||
|
callArguments[0] = _globalObject; // TODO: What is first argument?
|
||||||
|
|
||||||
|
for (var i = 0; i < arguments.Count; ++i)
|
||||||
|
{
|
||||||
|
callArguments[i + 1] = JTokenToJavaScriptValueConverter.Convert(arguments[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke the function
|
||||||
|
var result = method.CallFunction(callArguments);
|
||||||
|
|
||||||
|
// Convert the result
|
||||||
|
return JavaScriptValueToJTokenConverter.Convert(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetGlobalVariable(string propertyName, JToken value)
|
||||||
|
{
|
||||||
|
var javaScriptValue = JTokenToJavaScriptValueConverter.Convert(value);
|
||||||
|
var propertyId = JavaScriptPropertyId.FromString(propertyName);
|
||||||
|
_globalObject.SetProperty(propertyId, javaScriptValue, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeChakra()
|
||||||
|
{
|
||||||
|
// Set the current context
|
||||||
|
var context = _runtime.CreateContext();
|
||||||
|
JavaScriptContext.Current = context;
|
||||||
|
|
||||||
|
// Set the WinRT namespace (TODO: needed?)
|
||||||
|
Native.ThrowIfError(
|
||||||
|
Native.JsProjectWinRTNamespace("Windows"));
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
// Start debugging.
|
||||||
|
JavaScriptContext.StartDebugging();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var consolePropertyId = default(JavaScriptPropertyId);
|
||||||
|
Native.ThrowIfError(
|
||||||
|
Native.JsGetPropertyIdFromName("console", out consolePropertyId));
|
||||||
|
|
||||||
|
var consoleObject = JavaScriptValue.CreateObject();
|
||||||
|
_globalObject.SetProperty(consolePropertyId, consoleObject, true);
|
||||||
|
|
||||||
|
DefineHostCallback(consoleObject, "log", ConsoleCallback, IntPtr.Zero);
|
||||||
|
DefineHostCallback(consoleObject, "warn", ConsoleCallback, IntPtr.Zero);
|
||||||
|
DefineHostCallback(consoleObject, "error", ConsoleCallback, IntPtr.Zero);
|
||||||
|
|
||||||
|
Debug.WriteLine("Chakra initialization successful.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DefineHostCallback(
|
||||||
|
JavaScriptValue obj,
|
||||||
|
string callbackName,
|
||||||
|
JavaScriptNativeFunction callback,
|
||||||
|
IntPtr callbackData)
|
||||||
|
{
|
||||||
|
var propertyId = JavaScriptPropertyId.FromString(callbackName);
|
||||||
|
var function = JavaScriptValue.CreateFunction(callback, callbackData);
|
||||||
|
obj.SetProperty(propertyId, function, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JavaScriptValue ConsoleCallback(
|
||||||
|
JavaScriptValue callee,
|
||||||
|
bool isConstructCall,
|
||||||
|
JavaScriptValue[] arguments,
|
||||||
|
ushort argumentCount,
|
||||||
|
IntPtr callbackData)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Debug.Write("JS console> ");
|
||||||
|
|
||||||
|
// First argument is this-context (? @TODO), ignore...
|
||||||
|
foreach (var argument in arguments)
|
||||||
|
{
|
||||||
|
Debug.Write(argument.ToString() + " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.WriteLine("");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine(
|
||||||
|
"#EXCEPTION in ChakraExecutor::ConsoleCallback()! " + ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JavaScriptValue.Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_runtime.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ReactNative.Hosting.Bridge
|
||||||
|
{
|
||||||
|
sealed class JTokenToJavaScriptValueConverter
|
||||||
|
{
|
||||||
|
private static readonly JTokenToJavaScriptValueConverter s_instance =
|
||||||
|
new JTokenToJavaScriptValueConverter();
|
||||||
|
|
||||||
|
private JTokenToJavaScriptValueConverter() { }
|
||||||
|
|
||||||
|
public static JavaScriptValue Convert(JToken token)
|
||||||
|
{
|
||||||
|
return s_instance.Visit(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaScriptValue Visit(JToken token)
|
||||||
|
{
|
||||||
|
if (token == null)
|
||||||
|
throw new ArgumentNullException(nameof(token));
|
||||||
|
|
||||||
|
switch (token.Type)
|
||||||
|
{
|
||||||
|
case JTokenType.Array:
|
||||||
|
return VisitArray((JArray)token);
|
||||||
|
case JTokenType.Boolean:
|
||||||
|
return VisitBoolean((JValue)token);
|
||||||
|
case JTokenType.Float:
|
||||||
|
return VisitFloat((JValue)token);
|
||||||
|
case JTokenType.Integer:
|
||||||
|
return VisitInteger((JValue)token);
|
||||||
|
case JTokenType.Null:
|
||||||
|
return VisitNull(token);
|
||||||
|
case JTokenType.Object:
|
||||||
|
return VisitObject((JObject)token);
|
||||||
|
case JTokenType.String:
|
||||||
|
return VisitString((JValue)token);
|
||||||
|
case JTokenType.Undefined:
|
||||||
|
return VisitUndefined(token);
|
||||||
|
case JTokenType.Constructor:
|
||||||
|
case JTokenType.Property:
|
||||||
|
case JTokenType.Comment:
|
||||||
|
case JTokenType.Date:
|
||||||
|
case JTokenType.Raw:
|
||||||
|
case JTokenType.Bytes:
|
||||||
|
case JTokenType.Guid:
|
||||||
|
case JTokenType.Uri:
|
||||||
|
case JTokenType.TimeSpan:
|
||||||
|
case JTokenType.None:
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaScriptValue VisitArray(JArray token)
|
||||||
|
{
|
||||||
|
var n = token.Count;
|
||||||
|
var values = new JavaScriptValue[n];
|
||||||
|
for (var i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
values[i] = Visit(token[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var array = JavaScriptValue.CreateArray((uint)n);
|
||||||
|
for (var i = 0; i < n; ++i)
|
||||||
|
{
|
||||||
|
array.SetIndexedProperty(JavaScriptValue.FromInt32(i), values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaScriptValue VisitBoolean(JValue token)
|
||||||
|
{
|
||||||
|
return JavaScriptValue.FromBoolean(token.Value<bool>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaScriptValue VisitFloat(JValue token)
|
||||||
|
{
|
||||||
|
return JavaScriptValue.FromDouble(token.Value<double>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaScriptValue VisitInteger(JValue token)
|
||||||
|
{
|
||||||
|
return JavaScriptValue.FromDouble(token.Value<double>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaScriptValue VisitNull(JToken token)
|
||||||
|
{
|
||||||
|
return JavaScriptValue.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaScriptValue VisitObject(JObject token)
|
||||||
|
{
|
||||||
|
var jsonObject = JavaScriptValue.CreateObject();
|
||||||
|
foreach (var entry in token)
|
||||||
|
{
|
||||||
|
var value = Visit(entry.Value);
|
||||||
|
var propertyId = JavaScriptPropertyId.FromString(entry.Key);
|
||||||
|
jsonObject.SetProperty(propertyId, value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaScriptValue VisitString(JValue token)
|
||||||
|
{
|
||||||
|
return JavaScriptValue.FromString(token.Value<string>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private JavaScriptValue VisitUndefined(JToken token)
|
||||||
|
{
|
||||||
|
return JavaScriptValue.Undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ReactNative.Hosting.Bridge
|
||||||
|
{
|
||||||
|
sealed class JavaScriptValueToJTokenConverter
|
||||||
|
{
|
||||||
|
private static readonly JToken s_true = new JValue(true);
|
||||||
|
private static readonly JToken s_false = new JValue(false);
|
||||||
|
private static readonly JToken s_null = JValue.CreateNull();
|
||||||
|
private static readonly JToken s_undefined = JValue.CreateUndefined();
|
||||||
|
|
||||||
|
private static readonly JavaScriptValueToJTokenConverter s_instance =
|
||||||
|
new JavaScriptValueToJTokenConverter();
|
||||||
|
|
||||||
|
private JavaScriptValueToJTokenConverter() { }
|
||||||
|
|
||||||
|
public static JToken Convert(JavaScriptValue value)
|
||||||
|
{
|
||||||
|
return s_instance.Visit(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JToken Visit(JavaScriptValue value)
|
||||||
|
{
|
||||||
|
switch (value.ValueType)
|
||||||
|
{
|
||||||
|
case JavaScriptValueType.Array:
|
||||||
|
return VisitArray(value);
|
||||||
|
case JavaScriptValueType.Boolean:
|
||||||
|
return VisitBoolean(value);
|
||||||
|
case JavaScriptValueType.Null:
|
||||||
|
return VisitNull(value);
|
||||||
|
case JavaScriptValueType.Number:
|
||||||
|
return VisitNumber(value);
|
||||||
|
case JavaScriptValueType.Object:
|
||||||
|
return VisitObject(value);
|
||||||
|
case JavaScriptValueType.String:
|
||||||
|
return VisitString(value);
|
||||||
|
case JavaScriptValueType.Undefined:
|
||||||
|
return VisitUndefined(value);
|
||||||
|
case JavaScriptValueType.Function:
|
||||||
|
case JavaScriptValueType.Error:
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JToken VisitArray(JavaScriptValue value)
|
||||||
|
{
|
||||||
|
var count = 0;
|
||||||
|
var array = new JArray();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var index = JavaScriptValue.FromInt32(count++);
|
||||||
|
if (!value.HasIndexedProperty(index))
|
||||||
|
{
|
||||||
|
var element = value.GetIndexedProperty(index);
|
||||||
|
array.Add(Visit(element));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JToken VisitBoolean(JavaScriptValue value)
|
||||||
|
{
|
||||||
|
return value.ToBoolean() ? s_true : s_false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JToken VisitNull(JavaScriptValue value)
|
||||||
|
{
|
||||||
|
return s_null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JToken VisitNumber(JavaScriptValue value)
|
||||||
|
{
|
||||||
|
return JToken.FromObject(value.ToObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
private JToken VisitObject(JavaScriptValue value)
|
||||||
|
{
|
||||||
|
var jsonObject = new JObject();
|
||||||
|
var properties = Visit(value.GetOwnPropertyNames()).ToObject<string[]>();
|
||||||
|
foreach (var property in properties)
|
||||||
|
{
|
||||||
|
var propertyId = JavaScriptPropertyId.FromString(property);
|
||||||
|
var propertyValue = value.GetProperty(propertyId);
|
||||||
|
jsonObject.Add(property, Visit(propertyValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JToken VisitString(JavaScriptValue value)
|
||||||
|
{
|
||||||
|
return JValue.CreateString(value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private JToken VisitUndefined(JavaScriptValue value)
|
||||||
|
{
|
||||||
|
return s_undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using ReactNative.Bridge;
|
||||||
|
using ReactNative.Bridge.Queue;
|
||||||
|
|
||||||
|
namespace ReactNative.Hosting.Bridge
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class to the JavaScript execution environment and means of transport
|
||||||
|
/// for messages between JavaScript and the native environment.
|
||||||
|
/// </summary>
|
||||||
|
public class ReactBridge : IReactBridge
|
||||||
|
{
|
||||||
|
private readonly IJavaScriptExecutor _jsExecutor;
|
||||||
|
private readonly IReactCallback _reactCallback;
|
||||||
|
private readonly IMessageQueueThread _nativeModulesQueueThread;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates the <see cref="IReactBridge"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="jsExecutor">The JavaScript executor.</param>
|
||||||
|
/// <param name="reactCallback">The native callback handler.</param>
|
||||||
|
/// <param name="nativeModulesQueueThread">
|
||||||
|
/// The native modules queue thread.
|
||||||
|
/// </param>
|
||||||
|
public ReactBridge(
|
||||||
|
IJavaScriptExecutor jsExecutor,
|
||||||
|
IReactCallback reactCallback,
|
||||||
|
IMessageQueueThread nativeModulesQueueThread)
|
||||||
|
{
|
||||||
|
_jsExecutor = jsExecutor;
|
||||||
|
_reactCallback = reactCallback;
|
||||||
|
_nativeModulesQueueThread = nativeModulesQueueThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls a JavaScript function.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="moduleId">The module ID.</param>
|
||||||
|
/// <param name="methodId">The method ID.</param>
|
||||||
|
/// <param name="arguments">The arguments.</param>
|
||||||
|
public void CallFunction(int moduleId, int methodId, JArray arguments)
|
||||||
|
{
|
||||||
|
var allArgs = new JArray
|
||||||
|
{
|
||||||
|
moduleId,
|
||||||
|
methodId,
|
||||||
|
arguments,
|
||||||
|
};
|
||||||
|
|
||||||
|
var message = new JObject
|
||||||
|
{
|
||||||
|
{ "module", "BatchedBridge" },
|
||||||
|
{ "method", "callFunctionReturnFlushedQueue" },
|
||||||
|
{ "context", 15 },
|
||||||
|
{ "args", allArgs },
|
||||||
|
};
|
||||||
|
|
||||||
|
var messageArray = new JArray
|
||||||
|
{
|
||||||
|
message,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: actually introduce batching here...
|
||||||
|
var processBatchArgs = new JArray
|
||||||
|
{
|
||||||
|
messageArray,
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = _jsExecutor.Call("BatchedBridge", "processBatch", processBatchArgs);
|
||||||
|
|
||||||
|
ProcessResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes a JavaScript callback.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callbackId">The callback ID.</param>
|
||||||
|
/// <param name="arguments">The arguments.</param>
|
||||||
|
public void InvokeCallback(int callbackId, JArray arguments)
|
||||||
|
{
|
||||||
|
var allArgs = new JArray
|
||||||
|
{
|
||||||
|
callbackId,
|
||||||
|
arguments,
|
||||||
|
};
|
||||||
|
|
||||||
|
var message = new JObject
|
||||||
|
{
|
||||||
|
{ "module", "BatchedBridge" },
|
||||||
|
{ "method", "invokeCallbackAndReturnFlushedQueue" },
|
||||||
|
{ "args", allArgs },
|
||||||
|
};
|
||||||
|
|
||||||
|
var messageArray = new JArray
|
||||||
|
{
|
||||||
|
message,
|
||||||
|
};
|
||||||
|
|
||||||
|
var processBatchArgs = new JArray
|
||||||
|
{
|
||||||
|
messageArray,
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = _jsExecutor.Call("BatchedBridge", "processBatch", processBatchArgs);
|
||||||
|
|
||||||
|
ProcessResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a global JavaScript variable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyName">The property name.</param>
|
||||||
|
/// <param name="jsonEncodedArgument">The JSON-encoded value.</param>
|
||||||
|
public void SetGlobalVariable(string propertyName, string jsonEncodedArgument)
|
||||||
|
{
|
||||||
|
_jsExecutor.SetGlobalVariable(propertyName, JToken.Parse(jsonEncodedArgument));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes the bridge.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessResponse(JToken response)
|
||||||
|
{
|
||||||
|
var messages = response as JArray;
|
||||||
|
if (messages == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var moduleIds = messages[0].ToObject<int[]>();
|
||||||
|
var methodIds = messages[0].ToObject<int[]>();
|
||||||
|
var paramsArray = (JArray)messages[2];
|
||||||
|
|
||||||
|
_nativeModulesQueueThread.RunOnQueue(() =>
|
||||||
|
{
|
||||||
|
for (var i = 0; i < moduleIds.Length; i++)
|
||||||
|
{
|
||||||
|
var moduleId = moduleIds[i];
|
||||||
|
var methodId = methodIds[i];
|
||||||
|
var args = (JArray)paramsArray[i];
|
||||||
|
|
||||||
|
_reactCallback.Invoke(moduleId, methodId, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
_reactCallback.OnBatchComplete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -354,24 +354,13 @@
|
||||||
Native.ThrowIfError(Native.JsSetException(exception));
|
Native.ThrowIfError(Native.JsSetException(exception));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RELEASE64
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starts debugging in the context.
|
/// Starts debugging in the context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="debugApplication">The debug application to use for debugging.</param>
|
/// <param name="debugApplication">The debug application to use for debugging.</param>
|
||||||
public static void StartDebugging(Native.IDebugApplication64 debugApplication)
|
public static void StartDebugging()
|
||||||
{
|
{
|
||||||
Native.ThrowIfError(Native.JsStartDebugging(debugApplication));
|
Native.ThrowIfError(Native.JsStartDebugging());
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Starts debugging in the context.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="debugApplication">The debug application to use for debugging.</param>
|
|
||||||
public static void StartDebugging(Native.IDebugApplication32 debugApplication)
|
|
||||||
{
|
|
||||||
Native.ThrowIfError(Native.JsStartDebugging(debugApplication));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -98,13 +98,12 @@
|
||||||
/// Creates a new runtime.
|
/// Creates a new runtime.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="attributes">The attributes of the runtime to be created.</param>
|
/// <param name="attributes">The attributes of the runtime to be created.</param>
|
||||||
/// <param name="version">The version of the runtime to be created.</param>
|
|
||||||
/// <param name="threadServiceCallback">The thread service for the runtime. Can be null.</param>
|
/// <param name="threadServiceCallback">The thread service for the runtime. Can be null.</param>
|
||||||
/// <returns>The runtime created.</returns>
|
/// <returns>The runtime created.</returns>
|
||||||
public static JavaScriptRuntime Create(JavaScriptRuntimeAttributes attributes, JavaScriptRuntimeVersion version, JavaScriptThreadServiceCallback threadServiceCallback)
|
public static JavaScriptRuntime Create(JavaScriptRuntimeAttributes attributes, JavaScriptThreadServiceCallback threadServiceCallback)
|
||||||
{
|
{
|
||||||
JavaScriptRuntime handle;
|
JavaScriptRuntime handle;
|
||||||
Native.ThrowIfError(Native.JsCreateRuntime(attributes, version, threadServiceCallback, out handle));
|
Native.ThrowIfError(Native.JsCreateRuntime(attributes, threadServiceCallback, out handle));
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,11 +111,10 @@
|
||||||
/// Creates a new runtime.
|
/// Creates a new runtime.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="attributes">The attributes of the runtime to be created.</param>
|
/// <param name="attributes">The attributes of the runtime to be created.</param>
|
||||||
/// <param name="version">The version of the runtime to be created.</param>
|
|
||||||
/// <returns>The runtime created.</returns>
|
/// <returns>The runtime created.</returns>
|
||||||
public static JavaScriptRuntime Create(JavaScriptRuntimeAttributes attributes, JavaScriptRuntimeVersion version)
|
public static JavaScriptRuntime Create(JavaScriptRuntimeAttributes attributes)
|
||||||
{
|
{
|
||||||
return Create(attributes, version, null);
|
return Create(attributes, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -125,7 +123,7 @@
|
||||||
/// <returns>The runtime created.</returns>
|
/// <returns>The runtime created.</returns>
|
||||||
public static JavaScriptRuntime Create()
|
public static JavaScriptRuntime Create()
|
||||||
{
|
{
|
||||||
return Create(JavaScriptRuntimeAttributes.None, JavaScriptRuntimeVersion.Version11, null);
|
return Create(JavaScriptRuntimeAttributes.None, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -207,7 +205,6 @@
|
||||||
Native.ThrowIfError(Native.JsSetRuntimeBeforeCollectCallback(this, callbackState, beforeCollectCallback));
|
Native.ThrowIfError(Native.JsSetRuntimeBeforeCollectCallback(this, callbackState, beforeCollectCallback));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if RELEASE64
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a debug script context for running scripts.
|
/// Creates a debug script context for running scripts.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -215,50 +212,11 @@
|
||||||
/// Each script context has its own global object that is isolated from all other script
|
/// Each script context has its own global object that is isolated from all other script
|
||||||
/// contexts.
|
/// contexts.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="debugApplication">The debug application to use.</param>
|
|
||||||
/// <returns>The created script context.</returns>
|
|
||||||
public JavaScriptContext CreateContext(Native.IDebugApplication64 debugApplication)
|
|
||||||
{
|
|
||||||
JavaScriptContext reference;
|
|
||||||
Native.ThrowIfError(Native.JsCreateContext(this, debugApplication, out reference));
|
|
||||||
return reference;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !RELEASE64
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a debug script context for running scripts.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Each script context has its own global object that is isolated from all other script
|
|
||||||
/// contexts.
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="debugApplication">The debug application to use.</param>
|
|
||||||
/// <returns>The created script context.</returns>
|
|
||||||
public JavaScriptContext CreateContext(Native.IDebugApplication32 debugApplication)
|
|
||||||
{
|
|
||||||
JavaScriptContext reference;
|
|
||||||
Native.ThrowIfError(Native.JsCreateContext(this, debugApplication, out reference));
|
|
||||||
return reference;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a script context for running scripts.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Each script context has its own global object that is isolated from all other script
|
|
||||||
/// contexts.
|
|
||||||
/// </remarks>
|
|
||||||
/// <returns>The created script context.</returns>
|
/// <returns>The created script context.</returns>
|
||||||
public JavaScriptContext CreateContext()
|
public JavaScriptContext CreateContext()
|
||||||
{
|
{
|
||||||
JavaScriptContext reference;
|
JavaScriptContext reference;
|
||||||
#if RELEASE64
|
Native.ThrowIfError(Native.JsCreateContext(this, out reference));
|
||||||
Native.JsCreateContext(this, (Native.IDebugApplication64)null, out reference);
|
|
||||||
#else
|
|
||||||
Native.JsCreateContext(this, (Native.IDebugApplication32)null, out reference);
|
|
||||||
#endif
|
|
||||||
return reference;
|
return reference;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -556,8 +556,7 @@
|
||||||
UIntPtr length;
|
UIntPtr length;
|
||||||
Native.ThrowIfError(Native.JsStringToPointer(this, out buffer, out length));
|
Native.ThrowIfError(Native.JsStringToPointer(this, out buffer, out length));
|
||||||
|
|
||||||
//return Marshal.PtrToStringAuto(buffer, (int)length);
|
return Marshal.PtrToStringUni(buffer, (int)length);
|
||||||
return /* TODO */ null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -369,7 +369,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("chakra.dll")]
|
[DllImport("chakra.dll")]
|
||||||
internal static extern JavaScriptErrorCode JsCreateRuntime(JavaScriptRuntimeAttributes attributes, JavaScriptRuntimeVersion runtimeVersion, JavaScriptThreadServiceCallback threadService, out JavaScriptRuntime runtime);
|
internal static extern JavaScriptErrorCode JsCreateRuntime(JavaScriptRuntimeAttributes attributes, JavaScriptThreadServiceCallback threadService, out JavaScriptRuntime runtime);
|
||||||
|
|
||||||
[DllImport("chakra.dll")]
|
[DllImport("chakra.dll")]
|
||||||
internal static extern JavaScriptErrorCode JsCollectGarbage(JavaScriptRuntime handle);
|
internal static extern JavaScriptErrorCode JsCollectGarbage(JavaScriptRuntime handle);
|
||||||
|
@ -405,10 +405,7 @@
|
||||||
internal static extern JavaScriptErrorCode JsRelease(JavaScriptValue reference, out uint count);
|
internal static extern JavaScriptErrorCode JsRelease(JavaScriptValue reference, out uint count);
|
||||||
|
|
||||||
[DllImport("chakra.dll")]
|
[DllImport("chakra.dll")]
|
||||||
internal static extern JavaScriptErrorCode JsCreateContext(JavaScriptRuntime runtime, IDebugApplication64 debugSite, out JavaScriptContext newContext);
|
internal static extern JavaScriptErrorCode JsCreateContext(JavaScriptRuntime runtime, out JavaScriptContext newContext);
|
||||||
|
|
||||||
[DllImport("chakra.dll")]
|
|
||||||
internal static extern JavaScriptErrorCode JsCreateContext(JavaScriptRuntime runtime, IDebugApplication32 debugSite, out JavaScriptContext newContext);
|
|
||||||
|
|
||||||
[DllImport("chakra.dll")]
|
[DllImport("chakra.dll")]
|
||||||
internal static extern JavaScriptErrorCode JsGetCurrentContext(out JavaScriptContext currentContext);
|
internal static extern JavaScriptErrorCode JsGetCurrentContext(out JavaScriptContext currentContext);
|
||||||
|
@ -420,10 +417,7 @@
|
||||||
internal static extern JavaScriptErrorCode JsGetRuntime(JavaScriptContext context, out JavaScriptRuntime runtime);
|
internal static extern JavaScriptErrorCode JsGetRuntime(JavaScriptContext context, out JavaScriptRuntime runtime);
|
||||||
|
|
||||||
[DllImport("chakra.dll")]
|
[DllImport("chakra.dll")]
|
||||||
internal static extern JavaScriptErrorCode JsStartDebugging(IDebugApplication64 debugApplication);
|
internal static extern JavaScriptErrorCode JsStartDebugging();
|
||||||
|
|
||||||
[DllImport("chakra.dll")]
|
|
||||||
internal static extern JavaScriptErrorCode JsStartDebugging(IDebugApplication32 debugApplication);
|
|
||||||
|
|
||||||
[DllImport("chakra.dll")]
|
[DllImport("chakra.dll")]
|
||||||
internal static extern JavaScriptErrorCode JsIdle(out uint nextIdleTick);
|
internal static extern JavaScriptErrorCode JsIdle(out uint nextIdleTick);
|
||||||
|
@ -635,6 +629,9 @@
|
||||||
[DllImport("chakra.dll")]
|
[DllImport("chakra.dll")]
|
||||||
internal static extern JavaScriptErrorCode JsIsEnumeratingHeap(out bool isEnumeratingHeap);
|
internal static extern JavaScriptErrorCode JsIsEnumeratingHeap(out bool isEnumeratingHeap);
|
||||||
|
|
||||||
|
[DllImport("chakra.dll", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern JavaScriptErrorCode JsProjectWinRTNamespace(string namespaceName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ProcessDebugManager COM interface.
|
/// ProcessDebugManager COM interface.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -133,7 +133,10 @@
|
||||||
<Compile Include="Bridge\Queue\MessageQueueThreadExtensions.cs" />
|
<Compile Include="Bridge\Queue\MessageQueueThreadExtensions.cs" />
|
||||||
<Compile Include="Bridge\Queue\MessageQueueThreadKind.cs" />
|
<Compile Include="Bridge\Queue\MessageQueueThreadKind.cs" />
|
||||||
<Compile Include="Bridge\Queue\MessageQueueThreadSpec.cs" />
|
<Compile Include="Bridge\Queue\MessageQueueThreadSpec.cs" />
|
||||||
<Compile Include="Bridge\ReactBridge.cs" />
|
<Compile Include="Hosting\Bridge\ChakraJavaScriptExecutor.cs" />
|
||||||
|
<Compile Include="Hosting\Bridge\JavaScriptValueToJTokenConverter.cs" />
|
||||||
|
<Compile Include="Hosting\Bridge\JTokenToJavaScriptValueConverter.cs" />
|
||||||
|
<Compile Include="Hosting\Bridge\ReactBridge.cs" />
|
||||||
<Compile Include="Bridge\ReactContext.cs" />
|
<Compile Include="Bridge\ReactContext.cs" />
|
||||||
<Compile Include="Bridge\ReactContextNativeModuleBase.cs" />
|
<Compile Include="Bridge\ReactContextNativeModuleBase.cs" />
|
||||||
<Compile Include="Common\ReactConstants.cs" />
|
<Compile Include="Common\ReactConstants.cs" />
|
||||||
|
|
Загрузка…
Ссылка в новой задаче