static void SetAsIntPtr(IntPtr myMetArgN, int index, IntPtr value) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; (arr + index)->Ptr = value; } }
static bool GetAsBool(IntPtr myMetArgN, int index) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; return((arr + index)->I32 != 0); } }
static uint GetAsUInt32(IntPtr myMetArgN, int index) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; return((uint)(arr + index)->I32); } }
static IntPtr GetAsIntPtr(IntPtr myMetArgN, int index) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; return((arr + index)->Ptr); //return ((JsValue*)varr + index)->Ptr; } }
static float GetAsFloat(IntPtr myMetArgN, int index) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; return((float)(arr + index)->Num); //return (float)((JsValue*)varr + index)->Num; } }
static double GetAsDouble(IntPtr myMetArgN, int index) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; return((arr + index)->Num); //return ((JsValue*)varr + index)->Num; } }
static ulong GetAsUInt64(IntPtr myMetArgN, int index) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; return((ulong)(arr + index)->I64); //return (ulong)((JsValue*)varr + index)->I64; } }
static void SetAsInt32(IntPtr myMetArgN, int index, int value) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; (arr + index)->I32 = value; // ((JsValue*)varr + index)->I32 = value; } }
static int GetAsInt32(IntPtr myMetArgN, int index) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; return((arr + index)->I32); //return ((JsValue*)varr + index)->I32; } }
static string GetAsString(IntPtr myMetArgN, int index) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; return(MyCefJsReadString(arr + index)); //return MyCefJsReadString(((MyMetArgsN*)varr)->jsArr[index]); } }
static void SetBoolToAddress(IntPtr myMetArgN, int index, bool value) { unsafe { MyMetArgsN *metArg = (MyMetArgsN *)myMetArgN; JsValue * arr = metArg->jsArr; *((bool *)(arr + index)->Ptr) = value; //JsValue* jsvalue = ((JsValue*)myMetArgN + index); //*((bool*)jsvalue->Ptr) = value; } }
/// <summary> /// fill array to native js value /// </summary> /// <param name="arr"></param> /// <param name="output"></param> public void ToJsValue(object[] arr, ref JsValue output) { int len = arr.Length; //alloc array JsContext.jsvalue_alloc_array(len, ref output); if (output.I32 != len) { throw new JsInteropException("can't allocate memory on the unmanaged side"); } unsafe { JsValue *nativeArr = (JsValue *)output.Ptr; for (int i = 0; i < len; i++) { AnyToJsValuePtr(arr[i], nativeArr + i); } } }
JsObject CreateJsDictionaryObject(ref JsValue v) { //js dic is key-pair object JsObject obj = new JsObject(_context, v.Ptr); int count = v.I32 * 2;//key and value unsafe { JsValue *arr = (JsValue *)v.Ptr; for (int i = 0; i < count;) { JsValue *key = arr + i; JsValue *value = arr + i + 1; //TODO: review when key is not string obj[(string)FromJsValuePtr(key)] = FromJsValuePtr(value); i += 2; } } return(obj); }
unsafe JsObject CreateJsDictionaryObjectFromPtr(JsValue *v) { //js dic is key-pair JsObject obj = new JsObject(this._context, v->Ptr); int count = v->I32 * 2;//key and value unsafe { JsValue **arr = (JsValue **)v->Ptr; for (int i = 0; i < count;) { JsValue *key = arr[i]; JsValue *value = arr[i + 1]; //TODO: review when key is not string obj[(string)FromJsValuePtr(key)] = FromJsValuePtr(value); i += 2; } } return(obj); }
unsafe static string MyCefJsReadString(JsValue *jsval) { int actualLen; int buffLen = jsval->I32 + 1; //string len //check if string is on method-call's frame stack or heap if (jsval->Type == JsValueType.NativeCefString) { char *rawCefString_char16_t; Cef3Binder.MyCefStringGetRawPtr(jsval->Ptr, out rawCefString_char16_t, out actualLen); return(new string(rawCefString_char16_t, 0, actualLen)); } if (buffLen < 1024) { char *buffHead = stackalloc char[buffLen]; Cef3Binder.MyCefStringHolder_Read(jsval->Ptr, buffHead, buffLen, out actualLen); if (actualLen > buffLen) { //read more } return(new string(buffHead, 0, actualLen)); } else { char[] buffHead = new char[buffLen]; fixed(char *h = &buffHead[0]) { Cef3Binder.MyCefStringHolder_Read(jsval->Ptr, h, buffLen, out actualLen); if (actualLen > buffLen) { //read more } } return(new string(buffHead, 0, actualLen)); } }
public static extern JsValue *JsObjectMakeTypedArrayWithArrayBufferAndOffset([NativeTypeName("JSContextRef")] JsContext *ctx, JsTypedArrayType arrayType, [NativeTypeName("JSObjectRef")] JsValue *buffer, [NativeTypeName("size_t")] UIntPtr byteOffset, [NativeTypeName("size_t")] UIntPtr length, [NativeTypeName("JSValueRef *")] JsValue **exception);
static internal unsafe extern void jsvalue_alloc_string( string str, JsValue *output);
public static extern OneByteBoolean JsValueIsInstanceOfConstructor([NativeTypeName("JSContextRef")] JsContext *ctx, [NativeTypeName("JSValueRef")] JsValue *value, [NativeTypeName("JSObjectRef")] JsValue *constructor, [NativeTypeName("JSValueRef *")] JsValue **exception);
public static extern OneByteBoolean JsValueIsStrictEqual([NativeTypeName("JSContextRef")] JsContext *ctx, [NativeTypeName("JSValueRef")] JsValue *a, [NativeTypeName("JSValueRef")] JsValue *b);
public static extern OneByteBoolean JsValueIsEqual([NativeTypeName("JSContextRef")] JsContext *ctx, [NativeTypeName("JSValueRef")] JsValue *a, [NativeTypeName("JSValueRef")] JsValue *b, [NativeTypeName("JSValueRef *")] JsValue **exception);
public static extern JsTypedArrayType JsValueGetTypedArrayType([NativeTypeName("JSContextRef")] JsContext *ctx, [NativeTypeName("JSValueRef")] JsValue *value, [NativeTypeName("JSValueRef *")] JsValue **exception);
public static extern OneByteBoolean JsValueIsDate([NativeTypeName("JSContextRef")] JsContext *ctx, [NativeTypeName("JSValueRef")] JsValue *value);
public static extern OneByteBoolean JsValueIsObjectOfClass([NativeTypeName("JSContextRef")] JsContext *ctx, [NativeTypeName("JSValueRef")] JsValue *value, [NativeTypeName("JSClassRef")] JsClass *jsClass);
public static extern UIntPtr JsObjectGetArrayBufferByteLength([NativeTypeName("JSContextRef")] JsContext *ctx, [NativeTypeName("JSObjectRef")] JsValue * @object, [NativeTypeName("JSValueRef *")] JsValue **exception);
static internal unsafe extern void jsvalue_alloc_string2( char *str, int strLen, JsValue *output);
/// <summary> /// convert from jsvalue to managed value /// </summary> /// <param name="v"></param> /// <returns></returns> public object FromJsValue(ref JsValue v) { #if DEBUG_TRACE_API Console.WriteLine("Converting Js value to .net"); #endif switch (v.Type) { case JsValueType.Empty: case JsValueType.Null: return(null); case JsValueType.Boolean: return(v.I32 != 0); case JsValueType.Integer: return(v.I32); case JsValueType.Index: return((UInt32)v.I64); case JsValueType.Number: return(v.Num); case JsValueType.String: return(Marshal.PtrToStringUni(v.Ptr)); case JsValueType.Date: /* * // The formula (v.num * 10000) + 621355968000000000L was taken from a StackOverflow * // question and should be OK. Then why do we need to compensate by -26748000000000L * // (a value determined from the failing tests)?! * return new DateTime((long)(v.Num * 10000) + 621355968000000000L - 26748000000000L); */ //var msFromJsTime = v.I64 % 1000; return(EPOCH_LocalTime.AddMilliseconds(v.I64)); case JsValueType.Array: { int len = v.I32; object[] newarr = new object[len]; unsafe { JsValue *arr = (JsValue *)v.Ptr; for (int i = 0; i < len; ++i) { newarr[i] = FromJsValuePtr((arr + i)); } } return(newarr); } case JsValueType.UnknownError: if (v.Ptr != IntPtr.Zero) { return(new JsException(Marshal.PtrToStringUni(v.Ptr))); } return(new JsInteropException("unknown error without reason")); case JsValueType.StringError: return(new JsException(Marshal.PtrToStringUni(v.Ptr))); case JsValueType.Managed: return(_context.KeepAliveGet(v.I32)); case JsValueType.JsTypeWrap: //auto unwrap return(_context.GetObjectProxy(v.I32).WrapObject); case JsValueType.ManagedError: Exception inner = _context.KeepAliveGet(v.I32) as Exception; string msg = null; if (v.Ptr != IntPtr.Zero) { msg = Marshal.PtrToStringUni(v.Ptr); } else if (inner != null) { msg = inner.Message; } return(new JsException(msg, inner)); case JsValueType.Dictionary: return(CreateJsDictionaryObject(ref v)); case JsValueType.Wrapped: return(new JsObject(_context, v.Ptr)); case JsValueType.Error: return(JsException.Create(this, v.Ptr)); case JsValueType.Function: //convert from js function delegate to managed //this compose of function ptr and delegate's target unsafe { JsValue *arr = (JsValue *)v.Ptr; return(new JsFunction(_context, (arr)->Ptr, (arr + 1)->Ptr)); } default: throw new InvalidOperationException("unknown type code: " + v.Type); } }
public unsafe void AnyToJsValuePtr(object obj, 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 *b = strdata) { JsContext.jsvalue_alloc_string2(b, strdata.Length, 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; JsContext.jsvalue_alloc_array(arrLen, output); if (output->I32 != arrLen) { throw new JsInteropException("can't allocate memory on the unmanaged side"); } // output->Type = JsValueType.Array; unsafe { JsValue *arr = (JsValue *)output->Ptr; for (int i = 0; i < arrLen; i++) { AnyToJsValuePtr(array[i], arr + 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 static extern UIntPtr JsObjectGetTypedArrayByteOffset([NativeTypeName("JSContextRef")] JsContext *ctx, [NativeTypeName("JSObjectRef")] JsValue * @object, [NativeTypeName("JSValueRef *")] JsValue **exception);
static internal unsafe extern void jsvalue_alloc_array(int length, JsValue *output);
public static extern JsValue *JsObjectGetTypedArrayBuffer([NativeTypeName("JSContextRef")] JsContext *ctx, [NativeTypeName("JSObjectRef")] JsValue * @object, [NativeTypeName("JSValueRef *")] JsValue **exception);