Example #1
0
        /// <summary>
        /// Wraps a given object handle with a managed object, and optionally associates it with a template instance.
        /// <para>Note: Any other managed object associated with the given handle will cause an error.
        /// You should check '{Handle}.HasManagedObject', or use the "GetObject()" methods to make sure a managed object doesn't already exist.</para>
        /// <para>This was method exists to support the following cases: 1. The V8 context auto-generates the global object, and
        /// 2. V8 function objects are not generated from templates, but still need a managed wrapper.</para>
        /// <para>Note: </para>
        /// </summary>
        /// <typeparam name="T">The wrapper type to create (such as V8ManagedObject).</typeparam>
        /// <param name="v8Object">A handle to a native V8 object.</param>
        /// <param name="initialize">If true (default) then then 'IV8NativeObject.Initialize()' is called on the created object before returning.</param>
        internal T _CreateObject <T>(ITemplate template, InternalHandle v8Object, bool initialize = true, bool connectNativeObject = true)
            where T : V8NativeObject, new()
        {
            try
            {
                if (!v8Object.IsObjectType)
                {
                    throw new InvalidOperationException("An object handle type is required (such as a JavaScript object or function handle).");
                }

                // ... create the new managed JavaScript object, store it (to get the "ID"), and connect it to the native V8 object ...
                var obj = _CreateManagedObject <T>(template, v8Object.PassOn(), connectNativeObject);

                if (initialize)
                {
                    obj.Initialize(false, null);
                }

                return(obj);
            }
            finally
            {
                v8Object._DisposeIfFirst();
            }
        }
Example #2
0
        // --------------------------------------------------------------------------------------------------------------------

        /// <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 one function type 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;

            if (_FunctionsByType.TryGetValue(typeof(T), out funcID))
            {
                var weakRef = _Engine._GetObjectWeakReference(funcID);
                func = weakRef != null?weakRef.Reset() as V8Function : null;

                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.PassOn(), 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 = V8NetProxy.GetObjectPrototype(func._Handle);

            _FunctionsByType[typeof(T)] = func.ID; // (this exists to index functions by type)

            func.Initialize(false, null);

            return((T)func);
        }
Example #3
0
        // --------------------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Same as "GetObject()", but used internally for getting objects that are associated with templates (such as getting function prototype objects).
        /// </summary>
        internal T _GetObject <T>(ITemplate template, InternalHandle handle, bool createIfNotFound = true, bool initializeOnCreate = true, bool connectNativeObject = true)
            where T : V8NativeObject, new()
        {
            T obj = null;

            try
            {
                if (handle.IsEmpty)
                {
                    return(null);
                }

                if (handle.Engine != this)
                {
                    throw new InvalidOperationException("The specified handle was not generated from this V8Engine instance.");
                }

                var weakRef = _GetObjectWeakReference(handle.ObjectID); // (if out of bounds or invalid, this will simply return null)
                if (weakRef != null)
                {
                    obj = weakRef.Reset() as T;
                    if (obj != null && !typeof(T).IsAssignableFrom(obj.GetType()))
                    {
                        throw new InvalidCastException("The existing object of type '" + obj.GetType().Name + "' cannot be converted to type '" + typeof(T).Name + "'.");
                    }
                }

                if (obj == null && createIfNotFound)
                {
                    handle.ObjectID = -1; // (managed object doesn't exist [perhaps GC'd], so reset the ID)
                    obj             = _CreateObject <T>(template, handle.PassOn(), initializeOnCreate, connectNativeObject);
                }
            }
            finally
            {
                handle._DisposeIfFirst();
            }

            return(obj);
        }