/// <summary>
        /// Creates a JavaScript value from an host object if the it does not already exist
        /// </summary>
        /// <param name="obj">Instance of host type</param>
        /// <returns>JavaScript value created from an host object</returns>
        public JsValue GetOrCreateScriptObject(object obj)
        {
            if (!_embeddedObjectStorageInitialized)
            {
                lock (_embeddedObjectStorageInitializationSynchronizer)
                {
                    if (!_embeddedObjectStorageInitialized)
                    {
                        _lazyEmbeddedObjects            = new ConcurrentDictionary <EmbeddedObjectKey, Lazy <EmbeddedObject> >();
                        _embeddedObjectFinalizeCallback = EmbeddedObjectFinalizeCallback;

                        _embeddedObjectStorageInitialized = true;
                    }
                }
            }

            var            embeddedObjectKey = new EmbeddedObjectKey(obj);
            EmbeddedObject embeddedObject    = _lazyEmbeddedObjects.GetOrAdd(
                embeddedObjectKey,
                key => new Lazy <EmbeddedObject>(() => CreateEmbeddedObjectOrFunction(obj))
                ).Value;

            return(embeddedObject.ScriptValue);
        }
        private void EmbeddedObjectFinalizeCallback(IntPtr ptr)
        {
            if (ptr == IntPtr.Zero)
            {
                return;
            }

            GCHandle objHandle           = GCHandle.FromIntPtr(ptr);
            object   obj                 = objHandle.Target;
            var      lazyEmbeddedObjects = _lazyEmbeddedObjects;

            if (obj != null && lazyEmbeddedObjects != null)
            {
                var embeddedObjectKey = new EmbeddedObjectKey(obj);
                Lazy <EmbeddedObject> lazyEmbeddedObject;

                if (lazyEmbeddedObjects.TryRemove(embeddedObjectKey, out lazyEmbeddedObject))
                {
                    lazyEmbeddedObject.Value?.Dispose();
                }
            }

            objHandle.Free();
        }