예제 #1
0
        public T CreateValue <T>(JavaScriptValueSafeHandle valueHandle)
            where T : JsValue
        {
            var targetType = typeof(T);

            return(CreateValue(targetType, valueHandle) as T);
        }
예제 #2
0
        private bool TryGetErrorProperty <T>(JavaScriptValueSafeHandle error, string propertyName, out T value)
        {
            JsErrorCode innerError;

            innerError = LibChakraCore.JsCreatePropertyId(propertyName, (ulong)propertyName.Length, out JavaScriptPropertyIdSafeHandle propertyHandle);
            innerError = LibChakraCore.JsHasProperty(error, propertyHandle, out bool hasProperty);

            if (hasProperty == true)
            {
                innerError = LibChakraCore.JsGetProperty(error, propertyHandle, out JavaScriptValueSafeHandle propertyValue);
                innerError = LibChakraCore.JsGetValueType(propertyValue, out JsValueType propertyType);
                switch (propertyType)
                {
                case JsValueType.Number:
                    innerError = LibChakraCore.JsNumberToDouble(propertyValue, out double doubleValue);
                    value      = (T)Convert.ChangeType(doubleValue, typeof(T));
                    return(true);

                case JsValueType.String:
                    var strValue = Helpers.GetStringUtf8(propertyValue, releaseHandle: true);
                    value = (T)Convert.ChangeType(strValue, typeof(T));
                    return(true);

                default:
                    value = default(T);
                    return(false);
                }
            }

            value = default(T);
            return(false);
        }
예제 #3
0
        public void BaristaObjectPoolTryGetRemovedHandlesAreNull()
        {
            var bop    = new BaristaObjectPool <JsValue, JavaScriptValueSafeHandle>();
            var handle = new JavaScriptValueSafeHandle();

            using (var rt = BaristaRuntimeFactory.CreateRuntime())
            {
                using (var ctx = rt.CreateContext())
                    using (ctx.Scope())
                    {
                        var value = ctx.CreateString("Test 123");
                        bop.TryAdd(value);
                        handle = value.Handle;
                        value.Dispose();
                        value = null;
                    }
                rt.CollectGarbage();
            }

            //m_provider = null;
            //m_serviceCollection.FreeBaristaCoreServices();
            //m_serviceCollection = null;

            //GC.Collect();
            //GC.WaitForPendingFinalizers();
            //GC.WaitForFullGCComplete();
            //GC.Collect();

            bop.RemoveHandle(handle);
            bop.TryGet(handle, out JsValue retrievedValue);
            Assert.Null(retrievedValue);
        }
예제 #4
0
        public BaristaModuleRecord(string name, JavaScriptValueSafeHandle moduleSpecifier, BaristaModuleRecord parentModule, IJavaScriptEngine engine, BaristaContext context, IBaristaModuleRecordFactory moduleRecordFactory, IBaristaModuleLoader moduleLoader, JavaScriptModuleRecord moduleRecord)
            : base(engine, moduleRecord)
        {
            m_name                = name ?? throw new ArgumentNullException(nameof(name));
            m_moduleSpecifier     = moduleSpecifier ?? throw new ArgumentNullException(nameof(moduleSpecifier));
            m_parentModule        = parentModule;
            m_context             = context ?? throw new ArgumentNullException(nameof(context));
            m_moduleRecordFactory = moduleRecordFactory ?? throw new ArgumentNullException(nameof(moduleRecordFactory));

            //Module loader is not required, but if not specified, imports will fail.
            m_moduleLoader = moduleLoader;

            //Associate functions that will handle module loading
            if (m_parentModule == null)
            {
                //Set the fetch module callback for the module.
                m_fetchImportedModuleCallbackHandle = InitFetchImportedModuleCallback(Handle);

                //Set the notify callback for the module.
                m_notifyCallbackHandle = InitNotifyModuleReadyCallback(Handle);
            }

            //Set the event that will be called prior to the engine collecting the context.
            JavaScriptObjectBeforeCollectCallback beforeCollectCallback = (IntPtr handle, IntPtr callbackState) =>
            {
                OnBeforeCollect(handle, callbackState);
            };

            m_beforeCollectCallbackDelegateHandle = GCHandle.Alloc(beforeCollectCallback);
            Engine.JsSetObjectBeforeCollectCallback(moduleRecord, IntPtr.Zero, beforeCollectCallback);
        }
예제 #5
0
        internal JavaScriptArray CreateArrayFromHandle(JavaScriptValueSafeHandle handle)
        {
            ClaimContext();

            JsValueType kind;

            Errors.ThrowIfIs(api_.JsGetValueType(handle, out kind));

            switch (kind)
            {
            case JsValueType.JsArray:
                return(new JavaScriptArray(handle, JavaScriptValueType.Array, this));

            case JsValueType.JsFunction:
            case JsValueType.JsObject:
            case JsValueType.JsError:
            case JsValueType.JsNull:
            case JsValueType.JsArrayBuffer:
            case JsValueType.JsTypedArray:
            case JsValueType.JsDataView:
            case JsValueType.JsBoolean:
            case JsValueType.JsNumber:
            case JsValueType.JsString:
            case JsValueType.JsUndefined:
            case JsValueType.JsSymbol:
            default:
                throw new ArgumentException();
            }
        }
예제 #6
0
        public static string GetStringUtf8(JavaScriptValueSafeHandle stringHandle, bool releaseHandle = false)
        {
            bool stringHandleWasCreated = false;

            if (stringHandle == null || stringHandle == JavaScriptValueSafeHandle.Invalid)
            {
                throw new ArgumentNullException(nameof(stringHandle));
            }

            //Don't use our helper error class in order to prevent recursive errors.
            JsErrorCode innerError;

            //Get the size
            innerError = LibChakraCore.JsCopyString(stringHandle, null, 0, out ulong size);

            if ((int)size > int.MaxValue)
            {
                throw new OutOfMemoryException("Exceeded maximum string length.");
            }

            byte[] result = new byte[(int)size];
            innerError = LibChakraCore.JsCopyString(stringHandle, result, (ulong)result.Length, out ulong written);

            var strResult = Encoding.UTF8.GetString(result, 0, result.Length);

            if (stringHandleWasCreated || releaseHandle)
            {
                stringHandle.Dispose();
            }

            return(strResult);
        }
예제 #7
0
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (m_fnScript != null)
                {
                    m_fnScript.Dispose();
                    m_fnScript = null;
                }

                if (m_sourceUrlHandle != null)
                {
                    m_sourceUrlHandle.Dispose();
                    m_sourceUrlHandle = null;
                }

                if (m_scriptHandle != null)
                {
                    m_scriptHandle.Dispose();
                    m_scriptHandle = null;
                }
            }

            Marshal.FreeHGlobal(m_ptrScript);
        }
예제 #8
0
 protected virtual void Dispose(bool disposing)
 {
     if (disposing)
     {
         if (handle_ != null)
         {
             handle_.Dispose();
             handle_ = null;
         }
     }
 }
예제 #9
0
        public JsIterator(IJavaScriptEngine engine, BaristaContext context, JavaScriptValueSafeHandle valueHandle, IEnumerator enumerator)
            : base(engine, context, valueHandle)
        {
            m_enumerator = enumerator ?? throw new ArgumentNullException(nameof(enumerator));

            var fnNext = context.CreateFunction(new Func <JsObject, JsObject>((thisObj) =>
            {
                return(Next());
            }));

            SetProperty("next", fnNext);
        }
예제 #10
0
        /// <summary>
        /// Returns a delegate that attempts to convert supplied arguments into a BaristaDelegate and returns the result.
        /// </summary>
        /// <param name="functionDelegate"></param>
        /// <returns></returns>
        private JavaScriptNativeFunction CreateNativeFunctionForDelegate(BaristaFunctionDelegate functionDelegate)
        {
            JavaScriptNativeFunction fnDelegate = (IntPtr callee, bool isConstructCall, IntPtr[] arguments, ushort argumentCount, IntPtr callbackData) =>
            {
                //Convert each argument into a native object.
                var calleeObj = CreateValue(new JavaScriptValueSafeHandle(callee)) as JsObject;

                var      nativeArgs = new object[argumentCount - 1];
                JsObject thisObj    = null;
                for (int i = 0; i < argumentCount; i++)
                {
                    var currentArgument = arguments[i];
                    var argValueHandle  = new JavaScriptValueSafeHandle(currentArgument);
                    var jsValue         = CreateValue(argValueHandle);
                    if (i == 0)
                    {
                        thisObj = jsValue as JsObject;
                    }
                    else
                    {
                        if (Context.Converter.TryToObject(Context, jsValue, out object obj))
                        {
                            nativeArgs[i - 1] = obj;
                        }
                        else
                        {
                            throw new InvalidOperationException($"Unable to covert argument {i} into a value.");
                        }
                    }
                }

                try
                {
                    var nativeResult = functionDelegate.DynamicInvoke(calleeObj, isConstructCall, thisObj, nativeArgs);
                    if (Context.Converter.TryFromObject(Context, nativeResult, out JsValue valueResult))
                    {
                        return(valueResult.Handle.DangerousGetHandle());
                    }
                    else
                    {
                        return(Context.Undefined.Handle.DangerousGetHandle());
                    }
                }
                catch (TargetInvocationException exceptionResult)
                {
                    var jsError = CreateError(exceptionResult.InnerException);
                    m_engine.JsSetException(jsError.Handle);
                    return(Context.Undefined.Handle.DangerousGetHandle());
                }
            };

            return(fnDelegate);
        }
예제 #11
0
        internal JavaScriptValue CreateValueFromHandle(JavaScriptValueSafeHandle handle)
        {
            Debug.Assert(!(handle.IsClosed || handle.IsInvalid));

            JsValueType kind;

            Errors.ThrowIfIs(api_.JsGetValueType(handle, out kind));

            JavaScriptValue result = null;

            switch (kind)
            {
            case JsValueType.JsArray:
                result = new JavaScriptArray(handle, JavaScriptValueType.Array, this);
                break;

            case JsValueType.JsFunction:
                result = new JavaScriptFunction(handle, JavaScriptValueType.Function, this);
                break;

            case JsValueType.JsObject:
            case JsValueType.JsNull:
            case JsValueType.JsError:
                result = new JavaScriptObject(handle, JavaScriptValueType.Object, this);
                break;

            case JsValueType.JsSymbol:
                result = new JavaScriptSymbol(handle, JavaScriptValueType.Symbol, this);
                break;

            case JsValueType.JsArrayBuffer:
                result = new JavaScriptArrayBuffer(handle, JavaScriptValueType.ArrayBuffer, this);
                break;

            case JsValueType.JsTypedArray:
                result = new JavaScriptTypedArray(handle, JavaScriptValueType.TypedArray, this);
                break;

            case JsValueType.JsDataView:
                result = new JavaScriptDataView(handle, JavaScriptValueType.DataView, this);
                break;

            case JsValueType.JsBoolean:
            case JsValueType.JsNumber:
            case JsValueType.JsString:
            case JsValueType.JsUndefined:
            default:
                result = new JavaScriptValue(handle, kind.ToApiValueType(), this);
                break;
            }

            return(result);
        }
예제 #12
0
        private void PromiseContinuationCallback(IntPtr taskHandle, IntPtr callbackState)
        {
            if (m_promiseTaskQueue == null)
            {
                return;
            }
            var task = new JavaScriptValueSafeHandle(taskHandle);

            //Ensure that the object doesn't get disposed as we're processing items in the queue.
            m_context.Engine.JsAddRef(task);
            var promise = m_context.CreateValue <JsFunction>(task);

            m_promiseTaskQueue.Enqueue(promise);
        }
예제 #13
0
        public JsSymbol CreateSymbol(string description)
        {
            JavaScriptValueSafeHandle descriptionHandle = JavaScriptValueSafeHandle.Invalid;

            if (description != null)
            {
                var descriptionValue = CreateString(description);
                descriptionHandle = descriptionValue.Handle;
            }

            var symbolHandle = m_engine.JsCreateSymbol(descriptionHandle);

            return(CreateValue <JsSymbol>(symbolHandle));
        }
예제 #14
0
        public ScriptSource(IJavaScriptEngine engine, string script, string sourceUrl = "[eval source]")
        {
            if (engine == null)
            {
                throw new ArgumentNullException(nameof(engine));
            }
            m_script = script ?? throw new ArgumentNullException(nameof(script));

            m_ptrScript       = Marshal.StringToHGlobalAnsi(script);
            m_scriptHandle    = engine.JsCreateExternalArrayBuffer(m_ptrScript, (uint)script.Length, null, IntPtr.Zero);
            m_sourceUrlHandle = engine.JsCreateString(sourceUrl, (ulong)sourceUrl.Length);
            m_sourceContext   = JavaScriptSourceContext.GetNextSourceContext();

            m_fnScript = engine.JsParse(m_scriptHandle, m_sourceContext, m_sourceUrlHandle, JavaScriptParseScriptAttributes.None);
        }
예제 #15
0
        internal JavaScriptValue(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine)
        {
            Debug.Assert(handle != null);
            Debug.Assert(engine != null);
            Debug.Assert(Enum.IsDefined(typeof(JavaScriptValueType), type));
            handle.SetEngine(engine);
            api_ = engine.Api;

            uint count;

            Errors.ThrowIfIs(api_.JsAddRef(handle.DangerousGetHandle(), out count));

            handle_ = handle;
            type_   = type;
            engine_ = new WeakReference <JavaScriptEngine>(engine);
        }
예제 #16
0
        internal JavaScriptValue(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine)
        {
            Debug.Assert(handle != null);
            Debug.Assert(engine != null);
            Debug.Assert(type >= 0 && type <= JavaScriptValueType.DataView);
            handle.SetEngine(engine);
            api_ = engine.Api;

            uint count;

            Errors.ThrowIfIs(api_.JsAddRef(handle.DangerousGetHandle(), out count));

            handle_ = handle;
            type_   = type;
            engine_ = engine.engineWeakReference;
        }
예제 #17
0
        internal JavaScriptObject CreateObjectFromHandle(JavaScriptValueSafeHandle handle)
        {
            JsValueType kind;

            Errors.ThrowIfIs(api_.JsGetValueType(handle, out kind));

            JavaScriptObject result = null;

            switch (kind)
            {
            case JsValueType.JsArray:
                result = new JavaScriptArray(handle, JavaScriptValueType.Array, this);
                break;

            case JsValueType.JsFunction:
                result = new JavaScriptFunction(handle, JavaScriptValueType.Function, this);
                break;

            case JsValueType.JsObject:
            case JsValueType.JsError:
            case JsValueType.JsNull:
                result = new JavaScriptObject(handle, JavaScriptValueType.Object, this);
                break;

            case JsValueType.JsArrayBuffer:
                result = new JavaScriptArrayBuffer(handle, JavaScriptValueType.ArrayBuffer, this);
                break;

            case JsValueType.JsTypedArray:
                result = new JavaScriptTypedArray(handle, JavaScriptValueType.TypedArray, this);
                break;

            case JsValueType.JsDataView:
                result = new JavaScriptDataView(handle, JavaScriptValueType.DataView, this);
                break;

            case JsValueType.JsBoolean:
            case JsValueType.JsNumber:
            case JsValueType.JsString:
            case JsValueType.JsUndefined:
            case JsValueType.JsSymbol:
            default:
                throw new ArgumentException();
            }

            return(result);
        }
예제 #18
0
        /// <summary>
        /// Creates a module that returns the specified value.
        /// </summary>
        /// <param name="valueSafeHandle"></param>
        /// <param name="referencingModuleRecord"></param>
        /// <param name="specifierHandle"></param>
        /// <param name="dependentModuleRecord"></param>
        /// <returns></returns>
        private bool CreateSingleValueModule(BaristaModuleRecord moduleRecord, JavaScriptValueSafeHandle specifier, JsValue defaultExportedValue)
        {
            var globalId                = Guid.NewGuid();
            var exportSymbol            = Context.Symbol.For($"$DEFAULTEXPORT_{globalId.ToString()}");
            var exposeNativeValueScript = $@"
const defaultExport = global[Symbol.for('$DEFAULTEXPORT_{globalId.ToString()}')];
export default defaultExport;
";

            Context.Object.DefineProperty(Context.GlobalObject, exportSymbol, new JsPropertyDescriptor()
            {
                Configurable = false, Enumerable = false, Writable = false, Value = defaultExportedValue
            });

            moduleRecord.ParseModuleSource(exposeNativeValueScript);
            return(false);
        }
예제 #19
0
        public static string GetStringUtf8(this IJavaScriptEngine jsrt, JavaScriptValueSafeHandle stringHandle, bool autoConvert = false)
        {
            bool stringHandleWasCreated = false;

            if (stringHandle == null || stringHandle == JavaScriptValueSafeHandle.Invalid)
            {
                throw new ArgumentNullException(nameof(stringHandle));
            }

            //If Auto Convert is specified, ensure that the type is a string, otherwise convert it.
            if (autoConvert)
            {
                var handleValueType = jsrt.JsGetValueType(stringHandle);

                if (handleValueType != JsValueType.String)
                {
                    var convertedToStringHandle = jsrt.JsConvertValueToString(stringHandle);

                    stringHandle           = convertedToStringHandle;
                    stringHandleWasCreated = true;
                }
            }

            //Get the size
            var size = jsrt.JsCopyString(stringHandle, null, 0);

            if ((int)size > int.MaxValue)
            {
                throw new OutOfMemoryException("Exceeded maximum string length.");
            }

            byte[] result  = new byte[(int)size];
            var    written = jsrt.JsCopyString(stringHandle, result, (ulong)result.Length);

            var strResult = Encoding.UTF8.GetString(result, 0, result.Length);

            if (stringHandleWasCreated)
            {
                stringHandle.Dispose();
            }

            return(strResult);
        }
예제 #20
0
        internal JavaScriptValue CreateValueFromHandle(JavaScriptValueSafeHandle handle)
        {
            ClaimContext();

            JsValueType kind;

            Errors.ThrowIfIs(api_.JsGetValueType(handle, out kind));

            switch (kind)
            {
            case JsValueType.JsArray:
                return(new JavaScriptArray(handle, JavaScriptValueType.Array, this));

            case JsValueType.JsFunction:
                return(new JavaScriptFunction(handle, JavaScriptValueType.Function, this));

            case JsValueType.JsObject:
            case JsValueType.JsNull:
            case JsValueType.JsError:
                return(new JavaScriptObject(handle, JavaScriptValueType.Object, this));

            case JsValueType.JsSymbol:
                return(new JavaScriptSymbol(handle, JavaScriptValueType.Symbol, this));

            case JsValueType.JsArrayBuffer:
                return(new JavaScriptArrayBuffer(handle, JavaScriptValueType.ArrayBuffer, this));

            case JsValueType.JsTypedArray:
                return(new JavaScriptTypedArray(handle, JavaScriptValueType.TypedArray, this));

            case JsValueType.JsDataView:
                return(new JavaScriptDataView(handle, JavaScriptValueType.DataView, this));

            case JsValueType.JsBoolean:
            case JsValueType.JsNumber:
            case JsValueType.JsString:
            case JsValueType.JsUndefined:
            default:
                return(new JavaScriptValue(handle, kind.ToApiValueType(), this));
            }
        }
        public BaristaModuleRecord CreateBaristaModuleRecord(BaristaContext context, JavaScriptValueSafeHandle specifier, BaristaModuleRecord parentModule = null, bool setAsHost = false, IBaristaModuleLoader moduleLoader = null)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (specifier == null || specifier.IsClosed || specifier.IsInvalid)
            {
                throw new ArgumentNullException(nameof(specifier));
            }

            var moduleNameValue = context.CreateValue <JsString>(specifier);

            if (moduleNameValue == null)
            {
                throw new InvalidOperationException("Specifier is expected to be a string value.");
            }

            return(CreateBaristaModuleRecordInternal(context, moduleNameValue.ToString(), specifier, parentModule, setAsHost, moduleLoader));
        }
예제 #22
0
 public JsValue CreateValue(Type targetType, JavaScriptValueSafeHandle valueHandle)
 {
     return(ValueFactory.CreateValue(targetType, valueHandle));
 }
예제 #23
0
        public JsValue CreateValue(Type targetType, JavaScriptValueSafeHandle valueHandle)
        {
            if (targetType == null)
            {
                throw new ArgumentNullException(nameof(targetType));
            }

            if (targetType.IsSubclassOf(typeof(JsValue)) == false)
            {
                throw new ArgumentOutOfRangeException(nameof(targetType));
            }

            if (valueHandle == JavaScriptValueSafeHandle.Invalid)
            {
                return(null);
            }

            return(m_valuePool.GetOrAdd(valueHandle, () =>
            {
                JsValue result;

                if (typeof(JsObject).IsSameOrSubclass(targetType))
                {
                    result = Activator.CreateInstance(targetType, new object[] { m_engine, Context, valueHandle }) as JsValue;
                }
                else if (typeof(JsExternalObject).IsSameOrSubclass(targetType))
                {
                    //TODO: This isn't exactly true, we should set the ExternalData to the GCHandle.
                    //Then we can new JsExternalObject(m_engine, Context, valueHandle, Engine.GetExternalData(valueHandle));
                    throw new InvalidOperationException("External Objects must first be created by ...");
                }
                else if (typeof(JsBoolean) == targetType)
                {
                    result = new JsBoolean(m_engine, Context, valueHandle);
                }
                else if (typeof(JsNumber) == targetType)
                {
                    result = new JsNumber(m_engine, Context, valueHandle);
                }
                else if (typeof(JsString) == targetType)
                {
                    result = new JsString(m_engine, Context, valueHandle);
                }
                else if (typeof(JsSymbol) == targetType)
                {
                    result = new JsSymbol(m_engine, Context, valueHandle);
                }
                else if (typeof(JsUndefined) == targetType)
                {
                    result = new JsUndefined(m_engine, Context, valueHandle);
                }
                else if (typeof(JsNull) == targetType)
                {
                    result = new JsNull(m_engine, Context, valueHandle);
                }
                else
                {
                    throw new InvalidOperationException($"Type {targetType} must subclass JsValue");
                }

                if (result == null)
                {
                    throw new ArgumentOutOfRangeException(nameof(targetType), $"Unable to create an object of type {targetType}.");
                }

                result.BeforeCollect += JsValueBeforeCollectCallback;
                return result;
            }));
        }
예제 #24
0
 public JsString(IJavaScriptEngine engine, BaristaContext context, JavaScriptValueSafeHandle valueHandle)
     : base(engine, context, valueHandle)
 {
 }
예제 #25
0
        public static void SetGlobalVariable(this IJavaScriptEngine jsrt, string name, JavaScriptValueSafeHandle value)
        {
            var globalObjectHandle = jsrt.JsGetGlobalObject();
            var propertyIdHandle   = default(JavaScriptPropertyIdSafeHandle);

            try
            {
                propertyIdHandle = jsrt.JsCreatePropertyId(name, (ulong)name.Length);
                jsrt.JsSetProperty(globalObjectHandle, propertyIdHandle, value, true);
            }
            finally
            {
                if (propertyIdHandle != default(JavaScriptPropertyIdSafeHandle))
                {
                    propertyIdHandle.Dispose();
                }
                globalObjectHandle.Dispose();
            }
        }
예제 #26
0
 public JsPromiseConstructor(IJavaScriptEngine engine, BaristaContext context, JavaScriptValueSafeHandle valueHandle)
     : base(engine, context, valueHandle)
 {
 }
예제 #27
0
        /// <summary>
        /// Returns a delegate that will attempt to coerce supplied arguments into the specified delegate and return the result.
        /// </summary>
        /// <param name="func"></param>
        /// <returns></returns>
        private JavaScriptNativeFunction CreateNativeFunctionForDelegate(Delegate func)
        {
            //This is crazy fun.
            var funcParams = func.Method.GetParameters();
            JavaScriptNativeFunction fnDelegate = (IntPtr callee, bool isConstructCall, IntPtr[] arguments, ushort argumentCount, IntPtr callbackData) =>
            {
                //Make sure that we have argument values for each parameter.
                var nativeArgs = new object[funcParams.Length];
                for (int i = 0; i < funcParams.Length; i++)
                {
                    var targetParameterType = funcParams[i].ParameterType;

                    var currentArgument = arguments.ElementAtOrDefault(i);
                    if (currentArgument == default(IntPtr))
                    {
                        //If the argument wasn't specified, use the default value for the target parameter.
                        nativeArgs[i] = targetParameterType.GetDefaultValue();
                    }
                    else
                    {
                        //As the argument has been specified, convert the JsValue back to an Object using
                        //the conversion strategy associated with the context.

                        var argValueHandle = new JavaScriptValueSafeHandle(currentArgument);
                        var jsValue        = CreateValue(argValueHandle);
                        //Keep the first argument as the this JsObject.
                        if (i == 0)
                        {
                            nativeArgs[i] = jsValue as JsObject;
                        }
                        //If the target type is the same as the value type (The delegate expects a JsValue) don't convert.
                        else if (targetParameterType.IsSameOrSubclass(jsValue.GetType()))
                        {
                            nativeArgs[i] = jsValue;
                        }
                        else if (Context.Converter.TryToObject(Context, jsValue, out object obj))
                        {
                            try
                            {
                                nativeArgs[i] = Convert.ChangeType(obj, targetParameterType);
                            }
                            catch (Exception)
                            {
                                //Something went wrong, use the default value.
                                nativeArgs[i] = targetParameterType.GetDefaultValue();
                            }
                        }
                        else
                        {
                            //If we couldn't convert the type, use the default value.
                            nativeArgs[i] = targetParameterType.GetDefaultValue();
                        }
                    }
                }

                try
                {
                    var nativeResult = func.DynamicInvoke(nativeArgs);
                    if (Context.Converter.TryFromObject(Context, nativeResult, out JsValue valueResult))
                    {
                        return(valueResult.Handle.DangerousGetHandle());
                    }
                    else
                    {
                        return(Context.Undefined.Handle.DangerousGetHandle());
                    }
                }
                catch (TargetInvocationException exceptionResult)
                {
                    var jsError = CreateError(exceptionResult.InnerException);
                    m_engine.JsSetException(jsError.Handle);
                    return(Context.Undefined.Handle.DangerousGetHandle());
                }
            };

            return(fnDelegate);
        }
예제 #28
0
 public T CreateValue <T>(JavaScriptValueSafeHandle valueHandle) where T : JsValue
 {
     return(ValueFactory.CreateValue <T>(valueHandle));
 }
예제 #29
0
        /// <summary>
        /// Returns a new JavaScriptValue for the specified handle querying for the handle's value type.
        /// </summary>
        /// <remarks>
        /// Use the valueType parameter carefully. If the resulting type does not match the handle type unexpected issues may occur.
        /// </remarks>
        /// <returns>The JavaScript Value that represents the handle</returns>
        public JsValue CreateValue(JavaScriptValueSafeHandle valueHandle, JsValueType?valueType = null)
        {
            if (valueHandle == JavaScriptValueSafeHandle.Invalid)
            {
                return(null);
            }

            return(m_valuePool.GetOrAdd(valueHandle, () =>
            {
                if (valueType.HasValue == false)
                {
                    valueType = m_engine.JsGetValueType(valueHandle);
                }

                JsValue result;
                switch (valueType.Value)
                {
                case JsValueType.Array:
                    result = new JsArray(m_engine, Context, valueHandle);
                    break;

                case JsValueType.ArrayBuffer:
                    result = new JsArrayBuffer(m_engine, Context, valueHandle);
                    break;

                case JsValueType.Boolean:
                    result = new JsBoolean(m_engine, Context, valueHandle);
                    break;

                case JsValueType.DataView:
                    result = new JsDataView(m_engine, Context, valueHandle);
                    break;

                case JsValueType.Error:
                    result = new JsError(m_engine, Context, valueHandle);
                    break;

                case JsValueType.Function:
                    result = new JsFunction(m_engine, Context, valueHandle);
                    break;

                case JsValueType.Null:
                    result = new JsNull(m_engine, Context, valueHandle);
                    break;

                case JsValueType.Number:
                    result = new JsNumber(m_engine, Context, valueHandle);
                    break;

                case JsValueType.Object:
                    result = new JsObject(m_engine, Context, valueHandle);
                    break;

                case JsValueType.String:
                    result = new JsString(m_engine, Context, valueHandle);
                    break;

                case JsValueType.Symbol:
                    result = new JsSymbol(m_engine, Context, valueHandle);
                    break;

                case JsValueType.TypedArray:
                    result = new JsTypedArray(m_engine, Context, valueHandle);
                    break;

                case JsValueType.Undefined:
                    result = new JsUndefined(m_engine, Context, valueHandle);
                    break;

                default:
                    throw new NotImplementedException($"Error Creating JavaScript Value: The JavaScript Value Type '{valueType}' is unknown, invalid, or has not been implemented.");
                }

                result.BeforeCollect += JsValueBeforeCollectCallback;

                return result;
            }));
        }
예제 #30
0
 public JsValue CreateValue(JavaScriptValueSafeHandle valueHandle, JsValueType?valueType = null)
 {
     return(ValueFactory.CreateValue(valueHandle, valueType));
 }