internal void _Initialize(V8Engine v8EngineProxy, bool registerPropertyInterceptors = true) { _Initialize(v8EngineProxy, (NativeObjectTemplateProxy *)V8NetProxy.CreateObjectTemplateProxy(v8EngineProxy._NativeV8EngineProxy), // (create a corresponding native object) registerPropertyInterceptors ); }
internal void _Initialize(V8Engine v8EngineProxy, NativeFunctionTemplateProxy *nativeFunctionTemplateProxy) { if (v8EngineProxy == null) { throw new ArgumentNullException("v8EngineProxy"); } if (nativeFunctionTemplateProxy == null) { throw new ArgumentNullException("nativeFunctionTemplateProxy"); } _Engine = v8EngineProxy; _NativeFunctionTemplateProxy = nativeFunctionTemplateProxy; InstanceTemplate = new ObjectTemplate(); InstanceTemplate.Parent = this; InstanceTemplate._Initialize(_Engine, V8NetProxy.GetFunctionInstanceTemplateProxy(_NativeFunctionTemplateProxy), false); PrototypeTemplate = new ObjectTemplate(); PrototypeTemplate.Parent = this; PrototypeTemplate._Initialize(_Engine, V8NetProxy.GetFunctionPrototypeTemplateProxy(_NativeFunctionTemplateProxy), false); OnInitialized(); }
/// <summary> /// Creates a new CLR object which will be tracked by a new V8 native object. /// </summary> /// <param name="initialize">If true (default) then then 'IV8NativeObject.Initialize()' is called on the created wrapper before returning.</param> /// <typeparam name="T">A custom 'V8NativeObject' type, or just use 'V8NativeObject' as a default.</typeparam> public T CreateObject <T>(bool initialize = true) where T : V8NativeObject, new() { // ... create the new managed JavaScript object and store it (to get the "ID")... var obj = _CreateManagedObject <T>(null, null); try { // ... create a new native object and associated it with the new managed object ID ... obj._Handle._Set(V8NetProxy.CreateObject(_NativeV8EngineProxy, obj.ID)); /* The V8 object will have an associated internal field set to the index of the created managed object above for quick lookup. This index is used * to locate the associated managed object when a call-back occurs. The lookup is a fast O(1) operation using the custom 'IndexedObjectList' manager. */ } catch (Exception ex) { // ... something went wrong, so remove the new managed object ... _RemoveObjectWeakReference(obj.ID); throw ex; } if (initialize) { obj.Initialize(false, null); } return((T)obj); }
///// <summary> ///// Called when this handle has no more managed references, and the native garbage collector wants to collect this instance. ///// <para>Note: Handle disposal process only completes when there are no more managed references to the associated managed object as well.</para> ///// </summary> //??internal bool _OnNativeGCRequested() //{ // // ... the native V8 engine is requesting garbage collection ... // var dispose = _IsDisposeReady; // if (dispose && _ManagedObjectInfo != null) // lock (_Engine._Objects) // { // _Engine._Objects.Remove(_ManagedObjectInfo._ID); // } // return dispose; //} ///// <summary> ///// If this is true, then the native handle was made weak, and this handle instance is pending disposal. ///// </summary> //??internal bool _NativeHandleIsWeak; //??internal void _MakeWeakNativeHandle() //{ // if (!_NativeHandleIsWeak) // { // V8NetProxy.MakeWeakHandle(_HandleProxy); // _NativeHandleIsWeak = true; // } //} //??internal void _MakeStrongNativeHandle() //{ // if (_NativeHandleIsWeak) // { // V8NetProxy.MakeStrongHandle(_HandleProxy); // _NativeHandleIsWeak = false; // } //} /// <summary> /// Completes the disposal of the native handle. /// <para>Note: A disposed native handle is simply cached for reuse, and always points back to the same managed handle.</para> /// </summary> internal void _ForceDisposal() { if (!_IsWeakManagedObject) { throw new InvalidOperationException("A managed object is still associated with this handle"); } lock (this) { if (!IsDisposed) { //??if (_NativeHandleIsWeak) // _MakeStrongNativeHandle(); // (prevent any GC callback just in case) V8NetProxy.DisposeHandleProxy(_HandleProxy); // (note: '_HandleProxy' is NOT set to null here because the connection has to be maintained for cache purposes) GC.RemoveMemoryPressure((sizeof(HandleProxy) + sizeof(ValueProxy))); } if (_ManagedObjectInfo != null) { _ManagedObjectInfo.Dispose(); _ManagedObjectInfo = null; ManagedObjectID = -1; } } }
/// <summary> /// Calls the native V8 proxy library to create an error string for use within the V8 JavaScript environment. /// <para>Note: The error flag exists in the associated proxy object only. If the handle is passed along to another operation, only the string message will get passed.</para> /// </summary> public InternalHandle CreateError(string message, JSValueType errorType) { if (errorType >= 0) { throw new InvalidOperationException("Invalid error type."); } return(V8NetProxy.CreateError(_NativeV8EngineProxy, message, errorType)); }
/// <summary> /// Creates a new native V8 object only. /// </summary> /// <param name="objectID">You can associate arbitrary NEGATIVE numbers with objects to use for tracking purposes. The numbers have to be less than or /// equal to -2. Values greater or equal to 0 are used for internal tracking of V8NativeObject instances. -1 is a default value that is set automatically /// when new objects are created (which simply means "no ID is set").</param> public InternalHandle CreateObject(Int32 objectID = -2) { if (objectID > -2) { throw new InvalidOperationException("Object IDs must be <= -2."); } return(V8NetProxy.CreateObject(_NativeV8EngineProxy, objectID)); }
//~Context() { V8NetProxy.DeleteContext(_NativeContext); _NativeContext = null; } public void Dispose() { if (_NativeContext != null) { V8NetProxy.DeleteContext(_NativeContext); } _NativeContext = null; }
NativeFunctionCallback _ProxyCallback; // (need to keep a reference) /// <summary> /// Registers an invoke handler on the underlying native ObjectTemplate instance, which allows objects to be called like /// a function. /// <para>A proxy delegate is used and stored locally to prevent it from being reclaimed by the /// GC. If you call this method again, the old proxy delegate will be replaced with a new one and registered again on /// the native side. </para> /// </summary> /// <param name="callback"> A callback that gets invoked when the object is used like a function. </param> public void SetCallAsFunctionHandler(JSFunction callback) { _ProxyCallback = (managedObjectID, isConstructCall, _this, args, argCount) => { return(FunctionTemplate._CallBack(managedObjectID, isConstructCall, _this, args, argCount, callback)); }; V8NetProxy.SetCallAsFunctionHandler(_NativeObjectTemplateProxy, _ProxyCallback); }
// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// Registers an invoke handler on the underlying native ObjectTemplate instance, which allows the object to be called like a method. /// </summary> /// <param name="callback">A callback that gets invoked </param> public void RegisterInvokeHandler(JSFunction callback) { V8NetProxy.RegisterInvokeHandler(_NativeObjectTemplateProxy, (managedObjectID, isConstructCall, _this, args, argCount) => { return(FunctionTemplate._CallBack(managedObjectID, isConstructCall, _this, args, argCount, callback)); }); _Engine._StoreAccessor <JSFunction>(_NativeObjectTemplateProxy->ObjectID, "$__InvokeHandler", callback); }
// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// Calls the V8 'Set()' function on the underlying native function template to set properties that will exist on all function objects created from this template. /// </summary> public void SetProperty(string name, InternalHandle value, V8PropertyAttributes attributes = V8PropertyAttributes.Undefined) { if (name.IsNullOrWhiteSpace()) { throw new ArgumentNullException("name (cannot be null, empty, or only whitespace)"); } V8NetProxy.SetFunctionTemplateProperty(_NativeFunctionTemplateProxy, name, value, attributes); }
/// <summary> /// Registers an invoke handler on the underlying native ObjectTemplate instance, which allows the object to be called /// like a function. /// </summary> /// <param name="callback">A callback that gets invoked when the object is used like a function.</param> public void SetCallAsFunctionHandler(JSFunction callback) { ManagedJSFunctionCallback proxyCallback = (managedObjectID, isConstructCall, _this, args, argCount) => { return(FunctionTemplate._CallBack(managedObjectID, isConstructCall, _this, args, argCount, callback)); }; V8NetProxy.SetCallAsFunctionHandler(_NativeObjectTemplateProxy, proxyCallback); _Engine._StoreAccessor(_NativeObjectTemplateProxy->ObjectID, "$__InvokeHandler", proxyCallback); }
/// <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> /// Calls the V8 'SetAccessor()' function on the underlying native object to create a property that is controlled by /// "getter" and "setter" callbacks. /// <para>WARNING: If you try to set managed accessors on a native-ONLY object (as in, this handle does not yet have a /// managed-side object associated with it) then /// <see cref="V8Engine.CreateObject(InternalHandle, bool)"/> will be called to create a wrapper object so the /// accessor delegates will not get garbage collected, causing errors. You can optionally take control of this yourself /// and call one of the 'CreateObject()' methods on <see cref="V8Engine"/>.</para> /// </summary> /// <param name="name"> The property name. </param> /// <param name="getter"> /// The property getter delegate that returns a value when the property is accessed within JavaScript. /// </param> /// <param name="setter"> /// The property setter delegate that sets AND returns a value when the property is accessed within JavaScript. /// </param> /// <param name="attributes"> (Optional) The attributes to assign to the property. </param> /// <param name="access"> (Optional) The access security on the property. </param> /// <seealso cref="M:V8.Net.IV8Object.SetAccessor(string,GetterAccessor,SetterAccessor,V8PropertyAttributes,V8AccessControl)"/> public virtual void SetAccessor(string name, GetterAccessor getter, SetterAccessor setter, V8PropertyAttributes attributes = V8PropertyAttributes.None, V8AccessControl access = V8AccessControl.Default) { attributes = _CreateAccessorProxies(Engine, name, getter, setter, attributes, access, ref _Getter, ref _Setter); Getter = getter; Setter = setter; V8NetProxy.SetObjectAccessor(this, ID, name, _Getter, _Setter, access, attributes); }
// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// Returns the specified V8Function object type associated with this function template. /// There can only ever be one native V8 function object per native V8 function template in a single native V8 JavaScript context; /// however, V8.NET (the managed side) does allow multiple function types per template. In this case, a single call triggers all derived types at once. /// The first callback to return a value terminates the cycle and any following callbacks are ignored. /// <para>WARNING: The returned function object will be garbage collected if you don't store the reference anywhere. If this happens, then calling /// the function object in JavaScript will return "undefined".</para> /// </summary> /// <typeparam name="T">A type that implements IV8Function, or derives from V8Function.</typeparam> /// <param name="callback">When a new instance of type 'T' is created, it's 'Callback' property will overwritten by this value (replacing anything that may be set when it was created). /// It is expect to provide a callback method when using the default 'V8Function' object, but if you have a custom derivation you can set this to 'null'.</param> public T GetFunctionObject <T>(JSFunction callback = null) where T : V8Function, new() { if (_Engine == null) { throw new InvalidOperationException("You must create object templates by calling one of the 'V8Engine.CreateFunctionTemplate()' overloads."); } if (_NativeFunctionTemplateProxy == null) { throw new InvalidOperationException("This managed function template is not initialized."); } int funcID; V8Function func; lock (_FunctionsByType) { if (_FunctionsByType.TryGetValue(typeof(T), out funcID)) { func = _Engine._GetExistingObject(funcID) as V8Function; if (func != null) { return((T)func); } } } // ... get the v8 "Function" object ... InternalHandle hNativeFunc = V8NetProxy.GetFunction(_NativeFunctionTemplateProxy); // ... create a managed wrapper for the V8 "Function" object (note: functions inherit the native V8 "Object" type) ... func = _Engine._GetObject <T>(this, hNativeFunc, true, false); // (note: this will "connect" the native object [hNativeFunc] to a new managed V8Function wrapper, and set the prototype!) if (callback != null) { func.Callback = callback; } // ... get the function's prototype object, wrap it, and give it to the new function object ... // (note: this is a special case, because the function object auto generates the prototype object natively using an existing object template) func._Prototype.Set(V8NetProxy.GetObjectPrototype(func._Handle)); lock (_FunctionsByType) { _FunctionsByType[typeof(T)] = func.ID; // (this exists to index functions by type) } func.Initialize(false, null); return((T)func); }
public override void Dispose() // (note: This can cause issues if removed while the native object exists [because of the callbacks].) { if (_NativeObjectTemplateProxy != null && CanDispose) { _Engine._ClearAccessors(_NativeObjectTemplateProxy->ObjectID); V8NetProxy.DeleteObjectTemplateProxy(_NativeObjectTemplateProxy); // (delete the corresponding native object as well; WARNING: This is done on the GC thread!) _NativeObjectTemplateProxy = null; } }
/// <summary> /// Calls the V8 'SetAccessor()' function on the underlying native 'v8::ObjectTenplate' instance to create a property that is controlled by "getter" and "setter" callbacks. /// <para>Note: This is template related, which means all objects created from this template will be affected by these special properties.</para> /// </summary> public void SetAccessor(string name, GetterAccessor getter, SetterAccessor setter, V8PropertyAttributes attributes = V8PropertyAttributes.None, V8AccessControl access = V8AccessControl.Default) { attributes = V8NativeObject._CreateAccessorProxies(Engine, name, getter, setter, attributes, access, ref _Getter, ref _Setter); Getter = getter; Setter = setter; V8NetProxy.SetObjectTemplateAccessor(_NativeObjectTemplateProxy, -1, name, _Getter, _Setter, access, attributes); }
/// <summary> /// Unregisters handlers that intercept access to properties on ALL objects created by this template. See <see cref="RegisterNamedPropertyInterceptors()"/> and <see cref="RegisterIndexedPropertyInterceptors()"/>. /// </summary> public void UnregisterPropertyInterceptors() { if (NamedPropertyInterceptorsRegistered) { V8NetProxy.UnregisterNamedPropertyHandlers(_NativeObjectTemplateProxy); V8NetProxy.UnregisterIndexedPropertyHandlers(_NativeObjectTemplateProxy); NamedPropertyInterceptorsRegistered = false; } }
internal void _Initialize(V8Engine v8EngineProxy, string className) { ClassName = className; _Initialize(v8EngineProxy, (NativeFunctionTemplateProxy *)V8NetProxy.CreateFunctionTemplateProxy( v8EngineProxy._NativeV8EngineProxy, ClassName, _SetDelegate <NativeFunctionCallback>(_CallBack)) // (create a corresponding native object) ); }
public void Dispose() // TODO: !!! This will cause issues if removed while the native object exists. !!! { if (_NativeObjectTemplateProxy != null) { _Engine._ClearAccessors(_NativeObjectTemplateProxy->ObjectID); V8NetProxy.DeleteObjectTemplateProxy(_NativeObjectTemplateProxy); // (delete the corresponding native object as well; WARNING: This is done on the GC thread!) _NativeObjectTemplateProxy = null; } ((IFinalizable)this).CanFinalize = true; }
/// <summary> /// Compiles JavaScript on the V8 engine and returns the result. /// Since V8 JIT-compiles script every time, repeated tasks can take advantage of re-executing pre-compiled scripts for a speed boost. /// </summary> /// <param name="script">The script to run.</param> /// <param name="sourceName">A string that identifies the source of the script (handy for debug purposes).</param> /// <param name="throwExceptionOnError">If true, and the return value represents an error, an exception is thrown (default is 'false').</param> /// <returns>A handle to the compiled script.</returns> public Handle Compile(string script, string sourceName = "V8.NET", bool throwExceptionOnError = false) { Handle result = V8NetProxy.V8Compile(_NativeV8EngineProxy, script, sourceName); // (note: speed is not an issue when executing whole scripts, so the result is returned in a handle object instead of a value [safer]) if (throwExceptionOnError) { result.ThrowOnError(); } return(result); }
public override void Dispose() { if (_NativeFunctionTemplateProxy != null && CanDispose) { V8NetProxy.DeleteFunctionTemplateProxy(_NativeFunctionTemplateProxy); // (delete the corresponding native object as well; WARNING: This is done on the GC thread!) _NativeFunctionTemplateProxy = null; PrototypeTemplate.Parent = null; InstanceTemplate.Parent = null; PrototypeTemplate = null; InstanceTemplate = null; } }
/// <summary> /// Registers handlers that intercept access to properties on ALL objects created by this template. The native V8 engine only supports this on 'ObjectTemplate's. /// </summary> public void RegisterIndexedPropertyInterceptors() { if (!IndexedPropertyInterceptorsRegistered) { V8NetProxy.RegisterIndexedPropertyHandlers(_NativeObjectTemplateProxy, _SetDelegate <ManagedIndexedPropertyGetter>(_IndexedPropertyGetter), _SetDelegate <ManagedIndexedPropertySetter>(_IndexedPropertySetter), _SetDelegate <ManagedIndexedPropertyQuery>(_IndexedPropertyQuery), _SetDelegate <ManagedIndexedPropertyDeleter>(_IndexedPropertyDeleter), _SetDelegate <ManagedIndexedPropertyEnumerator>(_IndexedPropertyEnumerator)); IndexedPropertyInterceptorsRegistered = true; } }
protected override bool _Finalize(bool finalizer) // (note: This can cause issues if removed while the native object exists [because of the callbacks].) { if (_NativeObjectTemplateProxy != null) { if (V8NetProxy.DeleteObjectTemplateProxy(_NativeObjectTemplateProxy)) // (delete the corresponding native object as well; WARNING: This may be done on the GC thread!) { _NativeObjectTemplateProxy = null; } else { return(false); // (bounced, a script might be in progress; try again later) } } return(true); }
public void Dispose() { if (_NativeFunctionTemplateProxy != null) { V8NetProxy.DeleteFunctionTemplateProxy(_NativeFunctionTemplateProxy); // (delete the corresponding native object as well; WARNING: This is done on the GC thread!) _NativeFunctionTemplateProxy = null; PrototypeTemplate.Parent = null; InstanceTemplate.Parent = null; PrototypeTemplate = null; InstanceTemplate = null; } ((IFinalizable)this).CanFinalize = true; }
// -------------------------------------------------------------------------------------------------------------------- /// <summary> /// Calls the V8 'Set()' function on the underlying native object template to set properties that will exist on all objects created from this template. /// </summary> public void SetProperty(string name, InternalHandle value, V8PropertyAttributes attributes = V8PropertyAttributes.None) { try { if (name.IsNullOrWhiteSpace()) { throw new ArgumentNullException("name (cannot be null, empty, or only whitespace)"); } V8NetProxy.SetObjectTemplateProperty(_NativeObjectTemplateProxy, name, value, attributes); } finally { value._DisposeIfFirst(); } }
/// <summary> /// Executes JavaScript on the V8 engine and returns the result. /// </summary> /// <param name="script">The script to run.</param> /// <param name="sourceName">A string that identifies the source of the script (handy for debug purposes).</param> /// <param name="throwExceptionOnError">If true, and the return value represents an error, an exception is thrown (default is 'false').</param> public Handle Execute(Handle script, bool throwExceptionOnError = false) { if (script.ValueType != JSValueType.Script) { throw new InvalidOperationException("The handle must represent pre-compiled JavaScript."); } Handle result = V8NetProxy.V8ExecuteCompiledScript(_NativeV8EngineProxy, script); // (note: speed is not an issue when executing whole scripts, so the result is returned in a handle object instead of a value [safer]) if (throwExceptionOnError) { result.ThrowOnError(); } return(result); }
public void Dispose() { if (_NativeV8EngineProxy != null) { _TerminateWorker(); // (will return only when it has successfully terminated) // ... clear all handles of object IDs for disposal ... HandleProxy *hProxy; for (var i = 0; i < _HandleProxies.Length; i++) { hProxy = _HandleProxies[i]; if (hProxy != null && !hProxy->IsDisposed) { hProxy->_ObjectID = -2; // (note: this must be <= -2, otherwise the ID auto updates -1 to -2 to flag the ID as already processed) } } // ... allow all objects to be finalized by the GC ... ObservableWeakReference <V8NativeObject> weakRef; for (var i = 0; i < _Objects.Count; i++) { if ((weakRef = _Objects[i]) != null && weakRef.Object != null) { weakRef.Object._ID = null; weakRef.Object.Template = null; weakRef.Object._Handle = ObjectHandle.Empty; } } // ... destroy the native engine ... if (_NativeV8EngineProxy != null) { _Engines[_NativeV8EngineProxy->ID] = null; // (notifies any lingering handles that this engine is now gone) V8NetProxy.DestroyV8EngineProxy(_NativeV8EngineProxy); _NativeV8EngineProxy = null; } } }
/// <summary> /// Calls the native V8 proxy library to create the value instance for use within the V8 JavaScript environment. /// <para>This overload provides a *quick way* to construct an array of strings. /// One big memory block is created to marshal the given strings at one time, which is many times faster than having to create an array of individual native strings.</para> /// </summary> public InternalHandle CreateValue(IEnumerable <string> items) { if (items == null) { return(V8NetProxy.CreateArray(_NativeV8EngineProxy, null, 0)); } var itemsEnum = items.GetEnumerator(); int strBufSize = 0; // (size needed for the string chars portion of the memory block) int itemsCount = 0; while (itemsEnum.MoveNext()) { // get length of all strings together strBufSize += itemsEnum.Current.Length + 1; // (+1 for null char) itemsCount++; } itemsEnum.Reset(); int strPtrBufSize = Marshal.SizeOf(typeof(IntPtr)) * itemsCount; // start buffer size with size needed for all string pointers. char **oneBigStringBlock = (char **)Utilities.AllocNativeMemory(strPtrBufSize + Marshal.SystemDefaultCharSize * strBufSize); char **ptrWritePtr = oneBigStringBlock; char * strWritePtr = (char *)(((byte *)oneBigStringBlock) + strPtrBufSize); int itemLength; while (itemsEnum.MoveNext()) { itemLength = itemsEnum.Current.Length; Marshal.Copy(itemsEnum.Current.ToCharArray(), 0, (IntPtr)strWritePtr, itemLength); Marshal.WriteInt16((IntPtr)(strWritePtr + itemLength), 0); Marshal.WriteIntPtr((IntPtr)ptrWritePtr++, (IntPtr)strWritePtr); strWritePtr += itemLength + 1; } InternalHandle handle = V8NetProxy.CreateStringArray(_NativeV8EngineProxy, oneBigStringBlock, itemsCount); Utilities.FreeNativeMemory((IntPtr)oneBigStringBlock); return(handle); }
// -------------------------------------------------------------------------------------------------------------------- /// <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); } }