/// <summary> /// Creates a new <see cref="JsBinding"/> instance. /// </summary> public JsBinding(JsContextScope scope, JsBinder binder, JsInterop interop, JavaScriptValue value) { _scope = scope; _binder = binder; _interop = interop; _value = value; }
/// <summary> /// Determine if the <see cref="Type"/> provided is suitable to be passed the provided JS value. /// </summary> public static bool IsAssignable(JavaScriptValue value, JsBinder bindingData, Type toType) { switch (value.ValueType) { case JavaScriptValueType.Undefined: return(true); case JavaScriptValueType.Null: return(true); case JavaScriptValueType.Boolean: return(IsBoolType(toType)); case JavaScriptValueType.String: return(IsStringType(toType)); case JavaScriptValueType.Number: return(IsNumberType(toType)); case JavaScriptValueType.Function: return(IsFunctionType(toType)); case JavaScriptValueType.Array: return(IsArrayType(value, bindingData, toType)); case JavaScriptValueType.TypedArray: return(IsArrayType(value, bindingData, toType)); case JavaScriptValueType.Object: return(IsObjectAssignable(value, bindingData, toType)); default: { Log.Warning(null, "IsAssignable doesn't support the JS Value Type: {0}", value.ValueType); return(false); } } }
/// <summary> /// This method should be used to perform type checking when the <see cref="JavaScriptValue"/> is of /// value type <see cref="JavaScriptValueType.Object"/>. It will use the live binding data to reverse /// lookup types bound to JS objects. /// </summary> private static bool IsObjectAssignable(JavaScriptValue value, JsBinder bindingData, Type toType) { // Naive Case if (typeof(object) == toType) { return(true); } // Attempt to locate the type from live binding data, determine if assignable if (TryGetJsObjectType(value, bindingData, out var objectType)) { return(toType.IsAssignableFrom(objectType)); } return(false); }
/// <summary> /// Attempts to get the <see cref="Type"/> bound to the JS value as long as the JS value has /// a the value type of <see cref="JavaScriptValueType.Object"/> /// </summary> private static bool TryGetJsObjectType(JavaScriptValue value, JsBinder bindingData, out Type type) { if (!value.IsValid || value.ValueType != JavaScriptValueType.Object) { type = typeof(void); return(false); } var boundObject = bindingData.ObjectLinkedTo(value); if (null == boundObject) { type = typeof(void); return(false); } type = boundObject.GetType(); return(true); }
/// <summary> /// Determines whether or not the <see cref="Type"/> is a valid JS type for array conversions. /// </summary> private static bool IsArrayType(JavaScriptValue value, JsBinder bindingData, Type type) { if (!type.IsArray) { return(false); } // Check length, if empty, we can assume it matches any of the array types var length = value.GetProperty(JavaScriptPropertyId.FromString("length")).ToInt32(); if (length <= 0) { return(true); } // Look at the first element, type check against the host array element type var firstElement = value.GetIndexedProperty(JavaScriptValue.FromInt32(0)); var elementType = type.GetElementType(); return(IsAssignable(firstElement, bindingData, elementType)); }
/// <summary> /// Creates a new <see cref="JsInterop"/> instance. /// </summary> /// <param name="scope"></param> public JsInterop(JsExecutionContext context, JsContextScope scope, JsBinder binder) { _context = context; _scope = scope; _binder = binder; }
/// <summary> /// Creates a new <see cref="JsBindingBuilder"/> instance. /// </summary> public JsBindingBuilder(JsContextScope scope, JsBinder binder, JsInterop interop) { _scope = scope; _binder = binder; _interop = interop; }