Пример #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();
            }
        }
Пример #2
0
        // --------------------------------------------------------------------------------------------------------------------

        /// <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)
        {
            try
            {
                if (name.IsNullOrWhiteSpace())
                {
                    throw new ArgumentNullException("name (cannot be null, empty, or only whitespace)");
                }

                V8NetProxy.SetFunctionTemplateProperty(_NativeFunctionTemplateProxy, name, value, attributes);
            }
            finally
            {
                value._DisposeIfFirst();
            }
        }
Пример #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);
        }
Пример #4
0
        // --------------------------------------------------------------------------------------------------------------------

        /// <summary>
        /// Creates an uninitialized managed object ONLY (does not attempt to associate it with a JavaScript object, regardless of the supplied handle).
        /// <para>Warning: The managed wrapper is not yet initialized.  When returning the new managed object to the user, make sure to call
        /// '_ObjectInfo.Initialize()' first. Note however that new objects should only be initialized AFTER setup is completed so the users
        /// (developers) can write initialization code on completed objects (see source as example for 'FunctionTemplate.GetFunctionObject()').</para>
        /// </summary>
        /// <typeparam name="T">The wrapper type to create (such as V8ManagedObject).</typeparam>
        /// <param name="template">The managed template reference that owns the native object, if applicable.</param>
        /// <param name="handle">The handle to the native V8 object.</param>
        /// <param name="connectNativeObject">If true (the default), then a native function is called to associate the native V8 object with the new managed object.
        /// Set this to false if native V8 objects will be associated manually for special cases.  This parameter is ignored if no handle is given (hNObj == null).</param>
        internal T _CreateManagedObject <T>(ITemplate template, InternalHandle handle, bool connectNativeObject = true)
            where T : V8NativeObject, new()
        {
            T newObject;

            try
            {
                if (typeof(V8ManagedObject).IsAssignableFrom(typeof(T)) && template == null)
                {
                    throw new InvalidOperationException("You've attempted to create the type '" + typeof(T).Name + "' which implements IV8ManagedObject without a template (ObjectTemplate). The native V8 engine only supports interceptor hooks for objects generated from object templates.  At the very least, you can derive from 'V8NativeObject' and use the 'SetAccessor()' method.");
                }

                if (!handle.IsUndefined)
                {
                    if (!handle.IsObjectType)
                    {
                        throw new InvalidOperationException("The specified handle does not represent an native V8 object.");
                    }
                    else
                    if (connectNativeObject && handle.HasObject)
                    {
                        throw new InvalidOperationException("Cannot create a managed object for this handle when one already exists. Existing objects will not be returned by 'Create???' methods to prevent initializing more than once.");
                    }
                }

                newObject          = new T();
                newObject._Engine  = this;
                newObject.Template = template;
                newObject.Handle   = handle;

                using (_ObjectsLocker.WriteLock()) // (need a lock because of the worker thread)
                {
                    newObject.ID = _Objects.Add(new ObservableWeakReference <V8NativeObject>(newObject));
                }

                if (!handle.IsUndefined)
                {
                    if (connectNativeObject)
                    {
                        try
                        {
                            void *templateProxy = (template is ObjectTemplate) ? (void *)((ObjectTemplate)template)._NativeObjectTemplateProxy :
                                                  (template is FunctionTemplate) ? (void *)((FunctionTemplate)template)._NativeFunctionTemplateProxy : null;

                            V8NetProxy.ConnectObject(handle, newObject.ID, templateProxy);

                            /* 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(newObject.ID);
                            handle.ObjectID = -1; // (existing ID no longer valid)
                            throw ex;
                        }
                    }
                }
            }
            finally
            {
                handle._DisposeIfFirst();
            }

            return(newObject);
        }