public void SetResultAutoWrap <T>(T result) where T : class, new() { Type actualType = result.GetType(); JsTypeDefinition jsTypeDef = _context.GetJsTypeDefinition(actualType); INativeScriptable proxy = _context.CreateWrapper(result, jsTypeDef); JsValue output = new JsValue(); _context.Converter.ToJsValue(proxy, ref output); NativeV8JsInterOp.ResultSetValue(_metArgsPtr, ref output); }
/// <summary> /// convert any object to jsvalue /// </summary> /// <param name="obj"></param> /// <param name="output"></param> public void AnyToJsValue(object obj, ref JsValue output) { if (obj == null) { output.Type = JsValueType.Null; return; } //----- if (obj is INativeRef) { //extension INativeRef prox = (INativeRef)obj; output.I32 = _context.KeepAliveAdd(obj); output.Type = JsValueType.JsTypeWrap; output.Ptr = prox.UnmanagedPtr; return; } //----- Type type = obj.GetType(); // Check for nullable types (we will cast the value out of the box later). Type innerTypeOfNullable = type.ExtGetInnerTypeIfNullableValue(); if (innerTypeOfNullable != null) { type = innerTypeOfNullable; } // if (type == typeof(Boolean)) { output.Type = JsValueType.Boolean; output.I32 = (bool)obj ? 1 : 0; return; } if (type == typeof(String) || type == typeof(Char)) { // We need to allocate some memory on the other side; // will be free'd by unmanaged code. string strdata = obj.ToString(); unsafe { fixed(char *buffer = strdata) { JsContext.jsvalue_alloc_string(buffer, strdata.Length, ref output); } } output.Type = JsValueType.String; return; } //----------------------------------------------------------- if (type == typeof(Byte)) { output.Type = JsValueType.Integer; output.I32 = (int)(byte)obj; return; } if (type == typeof(Int16)) { output.Type = JsValueType.Integer; output.I32 = (int)(Int16)obj; return; } if (type == typeof(UInt16)) { output.Type = JsValueType.Integer; output.I32 = (int)(UInt16)obj; return; } if (type == typeof(Int32)) { output.Type = JsValueType.Integer; output.I32 = (int)obj; return; } if (type == typeof(UInt32)) { //TODO: review Type here when send to native side output.Type = JsValueType.Integer; output.I32 = (int)(uint)obj; return; } if (type == typeof(Int64)) { output.Type = JsValueType.Number; output.Num = (double)(Int64)obj; return; } if (type == typeof(UInt64)) { output.Type = JsValueType.Number; output.Num = (double)(UInt64)obj; return; } if (type == typeof(Single)) { output.Type = JsValueType.Number; output.Num = (double)(Single)obj; return; } if (type == typeof(Double)) { output.Type = JsValueType.Number; output.Num = (double)obj; return; } if (type == typeof(Decimal)) { //TODO: review here //.net decimal is larger than double? output.Type = JsValueType.Number; output.Num = (double)(Decimal)obj; return; } if (type == typeof(DateTime)) { output.Type = JsValueType.Date; output.Num = Convert.ToInt64(((DateTime)obj).Subtract(EPOCH).TotalMilliseconds); /*(((DateTime)obj).Ticks - 621355968000000000.0 + 26748000000000.0)/10000.0*/ return; } // Arrays of anything that can be cast to object[] are recursively convertef after // allocating an appropriate jsvalue on the unmanaged side. var array = obj as object[]; if (array != null) { //alloc space for array int arrLen = array.Length; output.Type = JsValueType.Array; JsContext.jsvalue_alloc_array(arrLen, ref output); if (output.I32 != arrLen) { throw new JsInteropException("can't allocate memory on the unmanaged side"); } unsafe { JsValue *jsarr = (JsValue *)output.Ptr; for (int i = 0; i < arrLen; i++) { AnyToJsValuePtr(array[i], (jsarr + i)); } } return; } // Every object explicitly converted to a value becomes an entry of the // _keepalives list, to make sure the GC won't collect it while still in // use by the unmanaged Javascript engine. We don't try to track duplicates // because adding the same object more than one time acts more or less as // reference counting. //check JsTypeDefinition jsTypeDefinition = _context.GetJsTypeDefinition(type); INativeRef prox2 = _context.CreateWrapper(obj, jsTypeDefinition); // output.Type = JsValueType.JsTypeWrap; output.Ptr = prox2.UnmanagedPtr; output.I32 = prox2.ManagedIndex; }
public JsValue AnyToJsValue(object obj) { if (obj == null) { return new JsValue { Type = JsValueType.Null } } ; if (obj is INativeRef) { //extension INativeRef prox = (INativeRef)obj; int keepAliveId = _context.KeepAliveAdd(obj); return(new JsValue { Type = JsValueType.JsTypeWrap, Ptr = prox.UnmanagedPtr, Index = keepAliveId }); } Type type = obj.GetType(); // Check for nullable types (we will cast the value out of the box later). if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>)) { type = type.GetGenericArguments()[0]; } if (type == typeof(Boolean)) { return new JsValue { Type = JsValueType.Boolean, I32 = (bool)obj ? 1 : 0 } } ; if (type == typeof(String) || type == typeof(Char)) { // We need to allocate some memory on the other side; will be free'd by unmanaged code. return(JsContext.jsvalue_alloc_string(obj.ToString())); } if (type == typeof(Byte)) { return new JsValue { Type = JsValueType.Integer, I32 = (int)(Byte)obj } } ; if (type == typeof(Int16)) { return new JsValue { Type = JsValueType.Integer, I32 = (int)(Int16)obj } } ; if (type == typeof(UInt16)) { return new JsValue { Type = JsValueType.Integer, I32 = (int)(UInt16)obj } } ; if (type == typeof(Int32)) { return new JsValue { Type = JsValueType.Integer, I32 = (int)obj } } ; if (type == typeof(UInt32)) { return new JsValue { Type = JsValueType.Integer, I32 = (int)(UInt32)obj } } ; if (type == typeof(Int64)) { return new JsValue { Type = JsValueType.Number, Num = (double)(Int64)obj } } ; if (type == typeof(UInt64)) { return new JsValue { Type = JsValueType.Number, Num = (double)(UInt64)obj } } ; if (type == typeof(Single)) { return new JsValue { Type = JsValueType.Number, Num = (double)(Single)obj } } ; if (type == typeof(Double)) { return new JsValue { Type = JsValueType.Number, Num = (double)obj } } ; if (type == typeof(Decimal)) { return new JsValue { Type = JsValueType.Number, Num = (double)(Decimal)obj } } ; if (type == typeof(DateTime)) { return new JsValue { Type = JsValueType.Date, Num = Convert.ToInt64(((DateTime)obj).Subtract(EPOCH).TotalMilliseconds) /*(((DateTime)obj).Ticks - 621355968000000000.0 + 26748000000000.0)/10000.0*/ } } ; // Arrays of anything that can be cast to object[] are recursively convertef after // allocating an appropriate jsvalue on the unmanaged side. var array = obj as object[]; if (array != null) { JsValue v = JsContext.jsvalue_alloc_array(array.Length); if (v.Length != array.Length) { throw new JsInteropException("can't allocate memory on the unmanaged side"); } for (int i = 0; i < array.Length; i++) { Marshal.StructureToPtr(AnyToJsValue(array[i]), new IntPtr(v.Ptr.ToInt64() + (16 * i)), false); } return(v); } // Every object explicitly converted to a value becomes an entry of the // _keepalives list, to make sure the GC won't collect it while still in // use by the unmanaged Javascript engine. We don't try to track duplicates // because adding the same object more than one time acts more or less as // reference counting. //check var jsTypeDefinition = _context.GetJsTypeDefinition(type); INativeRef prox2 = _context.CreateWrapper(obj, jsTypeDefinition); //int keepAliveId2 = _context.KeepAliveAdd(prox2); return(new JsValue { Type = JsValueType.JsTypeWrap, Ptr = prox2.UnmanagedPtr, Index = prox2.ManagedIndex }); //return new JsValue { Type = JsValueType.JsTypeWrap, Ptr = prox2.UnmanagedPtr, Index = keepAliveId2 }; //return new JsValue { Type = JsValueType.Managed, Index = _context.KeepAliveAdd(obj) }; }