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