/// <summary> /// Calls the native V8 proxy library to create a JavaScript array for use within the V8 JavaScript environment. /// </summary> public InternalHandle CreateArray(params InternalHandle[] items) { HandleProxy **nativeArrayMem = items.Length > 0 ? Utilities.MakeHandleProxyArray(items) : null; InternalHandle handle = V8NetProxy.CreateArray(_NativeV8EngineProxy, nativeArrayMem, items.Length); Utilities.FreeNativeMemory((IntPtr)nativeArrayMem); return(handle); }
/// <summary> /// Allocates native memory to marshal an array of proxy handles. /// Uses 'Utilities.AllocPointerArray()', so be sure to call 'Utilities.FreeNativeMemory()' when done. /// </summary> public static HandleProxy **MakeHandleProxyArray(InternalHandle[] items) { HandleProxy **nativeArrayMem = (HandleProxy **)Utilities.AllocPointerArray(items.Length); for (var i = 0; i < items.Length; i++) { nativeArrayMem[i] = (HandleProxy *)items[i]; } return(nativeArrayMem); }
/// <summary> /// Allocates native memory to marshal an array of proxy handles. /// Uses 'Utilities.AllocPointerArray()', so be sure to call 'Utilities.FreeNativeMemory()' when done. /// </summary> public static HandleProxy **MakeHandleProxyArray(InternalHandle[] items) { // (Note: items may be NULL, which is equivalent to "undefined") HandleProxy **nativeArrayMem = (HandleProxy **)Utilities.AllocPointerArray(items.Length); for (var i = 0; i < items.Length; i++) { nativeArrayMem[i] = (HandleProxy *)items[i]; } return(nativeArrayMem); }
/// <summary> /// Allocates native memory to marshal an array of proxy handles. /// Uses 'Utilities.AllocPointerArray()', so be sure to call 'Utilities.FreeNativeMemory()' when done. /// </summary> public static HandleProxy **MakeHandleProxyArray <T>(T[] items) where T : INativeHandleBased { // (Note: items may be NULL, which is equivalent to "undefined") HandleProxy **nativeArrayMem = (HandleProxy **)Utilities.AllocPointerArray(items.Length); for (var i = 0; i < items.Length; i++) { nativeArrayMem[i] = items[i].GetNativeHandleProxy(); } return(nativeArrayMem); }
// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// Calls the underlying native function to create and return a new instance, which will be wrapped in the specified managed object type. /// </summary> /// <typeparam name="T">A managed object type to wrap the new native object handle.</typeparam> /// <param name="args">Arguments to pass to the function to construct the new native instance.</param> /// <returns>A new instance of 'T'.</returns> public V8ManagedObject CreateInstance <T>(params InternalHandle[] args) // TODO: Parameter passing needs testing. where T : V8ManagedObject, new() { HandleProxy **_args = null; if (args.Length > 0) { _args = (HandleProxy **)Utilities.AllocPointerArray(args.Length); for (var i = 0; i < args.Length; i++) { _args[i] = args[i]; } } // (note: the special case here is that the native function object will use its own template to create instances) T obj = _Engine._CreateManagedObject <T>(this, null); obj.Template = InstanceTemplate; try { obj._Handle.Set(V8NetProxy.CreateInstanceFromFunctionTemplate(_NativeFunctionTemplateProxy, obj.ID, args.Length, _args)); // (note: setting '_NativeObject' also updates it's '_ManagedObject' field if necessary. obj.Initialize(true, args); } catch (Exception ex) { // ... something went wrong, so remove the new managed object ... _Engine._RemoveObjectWeakReference(obj.ID); throw ex; } finally { Utilities.FreeNativeMemory((IntPtr)_args); } return(obj); }
// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// Calls the underlying native function to create a new native object and return its handle. /// Use this method if you only need the native object and not a managed wrapper. /// </summary> /// <param name="args">Arguments to pass to the function to construct the new native instance.</param> /// <returns>A handle to the new object.</returns> public InternalHandle CreateNativeInstance(params InternalHandle[] args) // TODO: Parameter passing needs testing. { HandleProxy **_args = null; if (args.Length > 0) { _args = (HandleProxy **)Utilities.AllocPointerArray(args.Length); for (var i = 0; i < args.Length; i++) { _args[i] = args[i]; } } try { return((InternalHandle)V8NetProxy.CreateInstanceFromFunctionTemplate(_NativeFunctionTemplateProxy, -1, args.Length, _args)); } finally { Utilities.FreeNativeMemory((IntPtr)_args); } }
public static extern HandleProxy *CreateArray(NativeV8EngineProxy *engine, HandleProxy **items = null, Int32 length = 0);
public static unsafe extern HandleProxy *CreateFunctionInstance(NativeFunctionTemplateProxy *functionTemplateProxy, Int32 objID, Int32 argCount = 0, HandleProxy **args = null);
/// <summary> /// Calls a property with a given name on a specified object as a function and returns the result. /// If the function name is null, then the subject is assumed to be a function object. /// </summary> public static unsafe extern HandleProxy *Call(HandleProxy *subject, string functionName, HandleProxy *_this, Int32 argCount, HandleProxy **args);
// TODO: This is shared in both templates - consider putting elsewhere. internal static HandleProxy *_CallBack(Int32 managedObjectID, bool isConstructCall, HandleProxy *_this, HandleProxy **args, Int32 argCount, params JSFunction[] functions) { // ... get a handle to the native "this" object ... InternalHandle hThis = _this; V8Engine engine = hThis.Engine; // ... wrap the arguments ... InternalHandle[] _args = new InternalHandle[argCount]; int i; for (i = 0; i < argCount; i++) { _args[i] = args[i]; // (since these will be disposed immediately after, the "first" flag is not required [this also prevents it from getting passed on]) } // (note: the underlying native handles for '_this' and any arguments will be disposed automatically upon return, unless the user calls 'KeepAlive()' on them) InternalHandle result = null; // ... call all function types (multiple custom derived function types are allowed, but only one of each type) ... foreach (var callback in functions) { result = callback(engine, isConstructCall, hThis, _args); if (!result.IsEmpty) { break; } } var obj = result.Object; // ... make sure the user is not returning a 'V8ManagedObject' instance associated with the new object (the property interceptors will never work) ... if (isConstructCall && obj != null && obj is V8ManagedObject && obj.InternalHandle == hThis) { throw new InvalidOperationException("You've attempted to return the type '" + obj.GetType().Name + "' which is of type V8ManagedObject in a construction call (using 'new' in JavaScript) to wrap the new native object given to the constructor. The native V8 engine" + " only supports interceptor hooks for objects generated from ObjectTemplate instances. You will need to first derive/implement from V8NativeObject/IV8NativeObject" + " for your custom object(s), or rewrite your object to use V8NativeObject directly instead and use the 'SetAccessor()' handle method."); } return(result); }
// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// This is the main entry point from the native side for all calls to functions created from function templates. /// This method exists to give an instance based delegate reference for each function template instance. /// </summary> /// <param name="managedObjectID">The object ID of a managed object for this call.</param> /// <param name="isConstructCall">'true' if this is called because of the 'new' operator in JS.</param> /// <param name="_this">The instance context, if any.</param> /// <param name="args">Any arguments from the JS call.</param> /// <param name="argCount">Number of arguments given in the JS call.</param> /// <returns></returns> HandleProxy *_CallBack(Int32 managedObjectID, bool isConstructCall, HandleProxy *_this, HandleProxy **args, Int32 argCount) { lock (_FunctionsByType) { // ... get a list of callback functions to execute for this callback ... var functions = from f in (from t in _FunctionsByType.Keys.ToArray() // (need to convert this to an array in case the callbacks modify the dictionary!) select _Engine._GetExistingObject(_FunctionsByType[t])) where f != null && ((V8Function)f.Object).Callback != null select((V8Function)f.Object).Callback; return(_CallBack(managedObjectID, isConstructCall, _this, args, argCount, functions.ToArray())); } }
public static unsafe extern HandleProxy *CreateInstanceFromFunctionTemplate(NativeFunctionTemplateProxy *functionTemplateProxy, Int32 objID, Int32 argCount, HandleProxy **args);
internal static HandleProxy *_CallBack(Int32 managedObjectID, bool isConstructCall, HandleProxy *_this, HandleProxy **args, Int32 argCount, params JSFunction[] functions) { // ... get a handle to the native "this" object ... using (InternalHandle hThis = new InternalHandle(_this, false)) { V8Engine engine = hThis.Engine; // ... wrap the arguments ... InternalHandle[] _args = new InternalHandle[argCount]; int i; for (i = 0; i < argCount; i++) { _args[i]._Set(args[i], false); // (since these will be disposed immediately after, the "first" flag is not required [this also prevents it from getting passed on]) } InternalHandle result = null; try { // ... call all function types (multiple custom derived function types are allowed, but only one of each type) ... foreach (var callback in functions) { result = callback(engine, isConstructCall, hThis, _args); if (!result.IsEmpty) { break; } } } finally { for (i = 0; i < _args.Length; i++) { if (_args[i] != result) { _args[i].Dispose(); } } } if (isConstructCall && result.HasObject && result.Object is V8ManagedObject && result.Object.Handle._Handle == hThis) { throw new InvalidOperationException("You've attempted to return the type '" + result.Object.GetType().Name + "' which implements/extends IV8ManagedObject/V8ManagedObject in a construction call (using 'new' in JavaScript) to wrap the new native object." + " The native V8 engine only supports interceptor hooks for objects generated from ObjectTemplate instances. You will need to first derive/implement from V8NativeObject/IV8NativeObject" + " for construction calls, then wrap it around your object (or rewrite your object to use V8NativeObject directly instead and use the 'SetAccessor()' handle method)."); } return(result); } }
// -------------------------------------------------------------------------------------------------------------------- HandleProxy *_CallBack(Int32 managedObjectID, bool isConstructCall, HandleProxy *_this, HandleProxy **args, Int32 argCount) { var functions = from f in (from t in _FunctionsByType.Keys.ToArray() // (need to convert this to an array in case the callbacks modify the dictionary!) select _Engine._GetObjectWeakReference(_FunctionsByType[t])) where f != null && f.Object != null && ((V8Function)f.Object).Callback != null select((V8Function)f.Object).Callback; return(_CallBack(managedObjectID, isConstructCall, _this, args, argCount, functions.ToArray())); }