// -------------------------------------------------------------------------------------------------------------------- /// <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); }