Example #1
0
 public override void Cleanup()
 {
     engine_.Dispose();
     engine_ = null;
     runtime_.Dispose();
     runtime_ = null;
 }
 public JavaScriptConverter(JavaScriptEngine engine)
 {
     engine_ = new WeakReference<JavaScriptEngine>(engine);
     api_ = engine.Api;
     projectionTypes_ = new Dictionary<Type, JavaScriptProjection>();
     eventMarshallers_ = new Dictionary<Type, Expression>();
 }
Example #3
0
        internal JavaScriptExecutionContext(JavaScriptEngine engine, JavaScriptEngine previousEngine)
        {
            Debug.Assert(engine != null);

            previousEngine_ = previousEngine;
            engine_         = engine;
        }
        internal JavaScriptExecutionContext(JavaScriptEngine engine, Action release)
        {
            Debug.Assert(engine != null);
            Debug.Assert(release != null);

            engine_ = engine;
            release_ = release;
        }
Example #5
0
        internal JavaScriptExecutionContext(JavaScriptEngine engine, Action release)
        {
            Debug.Assert(engine != null);
            Debug.Assert(release != null);

            engine_  = engine;
            release_ = release;
        }
        private void Dispose(bool disposing)
        {
            if (release_ != null)
                release_();

            if (disposing)
            {
                engine_ = null;
                release_ = null;
            }
        }
Example #7
0
        public override void Cleanup()
        {
            dataView_ = null;
            typedArray_ = null;
            buffer_ = null;

            engine_.Dispose();
            engine_ = null;
            runtime_.Dispose();
            runtime_ = null;
        }
Example #8
0
        public JavaScriptExecutionContext AcquireContext()
        {
            var c = currentEngine;

            if (c != this)
            {
                ClaimContextPrivate();
                currentEngine = this;
            }
            return(new JavaScriptExecutionContext(this, c));
        }
Example #9
0
        private IJavaScriptValue EchoForProjectedNamespace(JavaScriptEngine source, bool construct, IJavaScriptValue thisValue, IEnumerable<IJavaScriptValue> args)
        {
            string arg = args.First().ToString();
            arg = arg.Replace("{", "{{").Replace("}", "}}");
            Debug.WriteLine(string.Format(arg, (object[])args.Skip(1).ToArray()));

            if (arg == "toast promise done")
            {
                successSignal.SetResult(0);
            }
            return source.UndefinedValue;
        }
Example #10
0
        private IJavaScriptValue Echo(JavaScriptEngine source, bool construct, IJavaScriptValue thisValue, IEnumerable<IJavaScriptValue> args)
        {
            string arg = args.First().ToString();
            arg = arg.Replace("{", "{{").Replace("}", "}}");
            Log.Message(string.Format(arg, (object[])args.Skip(1).ToArray()));

            if (arg == "toast promise done")
            {
                Assert.Succeeded();
            }
            return source.UndefinedValue;
        }
Example #11
0
        private void Dispose(bool disposing)
        {
            if (release_ != null)
            {
                release_();
            }

            if (disposing)
            {
                engine_  = null;
                release_ = null;
            }
        }
Example #12
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);
        }
Example #13
0
        public override void Setup()
        {
            runtime_ = new JavaScriptRuntime(new JavaScriptRuntimeSettings());
            engine_ = runtime_.CreateEngine();

            var baseline = new ScriptSource("test://init.js", @"(function(global) {
            global.buffer = new ArrayBuffer(1024);
            global.typedArray = new Uint8ClampedArray(buffer);
            global.dataView = new DataView(buffer, 1);
            })(this);");
            engine_.Execute(baseline);
            buffer_ = (JavaScriptArrayBuffer)engine_.GetGlobalVariable("buffer");
            typedArray_ = (JavaScriptTypedArray)engine_.GetGlobalVariable("typedArray");
            dataView_ = (JavaScriptDataView)engine_.GetGlobalVariable("dataView");
        }
Example #14
0
 internal void ReleaseContextPrivate(JavaScriptEngine previous)
 {
     if (currentEngine != this)
     {
         throw new Exception("Incorrect JavaScriptExecutionContext disposal.");
     }
     if (previous != currentEngine)
     {
         Errors.ThrowIfIs(api_.JsReleaseCurrentContext());
         currentEngine = previous;
         if (previous != null)
         {
             previous.ClaimContextPrivate();
         }
     }
 }
        private void ProjectMethods(string owningTypeName, JavaScriptObject target, JavaScriptEngine engine, IEnumerable <MethodInfo> methods)
        {
            var methodsByName = methods.GroupBy(m => m.Name);

            foreach (var group in methodsByName)
            {
                var method = engine.CreateFunction((eng, ctor, thisObj, args) =>
                {
                    var @this = thisObj as JavaScriptObject;
                    if (@this == null)
                    {
                        eng.SetException(eng.CreateTypeError("Could not call method '" + group.Key + "' because there was an invalid 'this' context."));
                        return(eng.UndefinedValue);
                    }

                    var argsArray = args.ToArray();
                    var candidate = GetBestFitMethod(group, thisObj, argsArray);
                    if (candidate == null)
                    {
                        eng.SetException(eng.CreateReferenceError("Could not find suitable method or not enough arguments to invoke '" + group.Key + "'."));
                        return(eng.UndefinedValue);
                    }

                    List <object> argsToPass = new List <object>();
                    for (int i = 0; i < candidate.GetParameters().Length; i++)
                    {
                        argsToPass.Add(ToObject(argsArray[i]));
                    }

                    try
                    {
                        return(FromObject(candidate.Invoke(@this.ExternalObject, argsToPass.ToArray())));
                    }
                    catch (Exception ex)
                    {
                        eng.SetException(FromObject(ex));
                        return(eng.UndefinedValue);
                    }
                }, owningTypeName + "." + group.Key);
                //var propDescriptor = engine.CreateObject();
                //propDescriptor.SetPropertyByName("configurable", engine.TrueValue);
                //propDescriptor.SetPropertyByName("enumerable", engine.TrueValue);
                //propDescriptor.SetPropertyByName("value", method);
                //target.DefineProperty(group.Key, propDescriptor);
                target.SetPropertyByName(group.Key, method);
            }
        }
Example #16
0
 // used by InitializeProjectionForType
 private JavaScriptObject CreateObjectFor(JavaScriptEngine engine, JavaScriptProjection baseTypeProjection)
 {
     if (baseTypeProjection != null)
     {
         // todo: revisit to see if there is a better way to do this
         // Can probably get
         // ((engine.GlobalObject.GetPropertyByName("Object") as JavaScriptObject).GetPropertyByName("create") as JavaScriptFunction).Invoke(baseTypeProjection.Prototype)
         // but this is so much clearer
         dynamic          global = engine.GlobalObject;
         JavaScriptObject result = global.Object.create(baseTypeProjection.Prototype);
         return(result);
     }
     else
     {
         return(engine.CreateObject());
     }
 }
Example #17
0
        private IJavaScriptValue MessageDialog(JavaScriptEngine source, bool construct, IJavaScriptValue thisValue, IEnumerable<IJavaScriptValue> args)
        {
            if (!construct)
            {
                var undefined = source.UndefinedValue;
                source.SetException(source.CreateTypeError("Must call as a constructor."));
                return undefined;
            }

            var dlg = new MessageDialog(args.First().ToString());
            return source.Converter.FromWindowsRuntimeObject(dlg);
        }
Example #18
0
 public async Task Setup()
 {
     await DispatchContainer.GlobalDispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
     {
         runtime_ = new JavaScriptRuntime();
         engine_ = runtime_.CreateEngine();
     });
 }
        private void ProjectEvents(string owningTypeName, JavaScriptObject target, JavaScriptEngine engine, IEnumerable<EventInfo> events, JavaScriptProjection baseTypeProjection, bool instance)
        {
            var eventsArray = events.ToArray();
            var eventsLookup = eventsArray.ToDictionary(ei => ei.Name.ToLower());
            // General approach here
            // if there is a base thing, invoke that
            // for each event, register a delegate that marshals it back to JavaScript
            var add = engine.CreateFunction((eng, ctor, thisObj, args) =>
            {
                bool callBase = instance && (baseTypeProjection?.HasInstanceEvents ?? false);
                var @this = thisObj as JavaScriptObject;
                if (@this == null)
                    return eng.UndefinedValue;

                if (callBase)
                {
                    var baseObj = baseTypeProjection.Prototype;
                    var baseFn = baseObj.GetPropertyByName("addEventListener") as JavaScriptFunction;
                    if (baseFn != null)
                    {
                        baseFn.Call(@this, args);
                    }
                }

                var argsArray = args.ToArray();
                if (argsArray.Length < 2)
                    return eng.UndefinedValue;

                string eventName = argsArray[0].ToString();
                JavaScriptFunction callbackFunction = argsArray[1] as JavaScriptFunction;
                if (callbackFunction == null)
                    return eng.UndefinedValue;

                EventInfo curEvent;
                if (!eventsLookup.TryGetValue(eventName, out curEvent))
                    return eng.UndefinedValue;

                MethodInfo targetMethod = curEvent.EventHandlerType.GetMethod("Invoke");

                var paramsExpr = targetMethod.GetParameters().Select(p => Expression.Parameter(p.ParameterType, p.Name)).ToArray();
                int cookie = EventMarshaler.RegisterDelegate(callbackFunction, SynchronizationContext.Current);

                var marshaler = Expression.Lambda(curEvent.EventHandlerType, Expression.Block(
                    Expression.Call(
                        typeof(EventMarshaler).GetMethod(nameof(EventMarshaler.InvokeJavaScriptCallback)), 
                        Expression.Constant(cookie), 
                        Expression.NewArrayInit(typeof(string), targetMethod.GetParameters().Select(p => Expression.Constant(p.Name))),
                        Expression.NewArrayInit(typeof(object), paramsExpr))
                ), paramsExpr);

                curEvent.AddMethod.Invoke(@this.ExternalObject, new object[] { marshaler.Compile() });

                return eng.UndefinedValue;
            }, owningTypeName + ".addEventListener");
            target.SetPropertyByName("addEventListener", add);
        }
Example #20
0
 private IJavaScriptValue Success(JavaScriptEngine source, bool construct, IJavaScriptValue thisValue, IEnumerable<IJavaScriptValue> args)
 {
     successSignal.SetResult(0);
     return source.UndefinedValue;
 }
Example #21
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;
        }
Example #22
0
 public JavaScriptConverter(JavaScriptEngine engine)
 {
     engine_ = new WeakReference <JavaScriptEngine>(engine);
     api_    = engine.Api;
 }
Example #23
0
 public void Setup()
 {
     var settings = new JavaScriptRuntimeSettings();
     runtime_ = new JavaScriptRuntime(settings);
     engine_ = runtime_.CreateEngine();
 }
Example #24
0
        internal JavaScriptSymbol(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine):
            base(handle, type, engine)
        {

        }
Example #25
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);
        }
Example #26
0
        internal JavaScriptFunction(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine):
            base(handle, type, engine)
        {

        }
 internal JavaScriptTypedArray(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine) :
     base(handle, type, engine)
 {
     arrayType_ = new Lazy <JavaScriptTypedArrayType>(GetArrayType);
 }
 public override void Setup()
 {
     var settings = new JavaScriptRuntimeSettings() { EnableIdleProcessing = true, };
     runtime_ = new JavaScriptRuntime(settings);
     engine_ = runtime_.CreateEngine();
 }
Example #29
0
 private IJavaScriptValue Echo(JavaScriptEngine source, bool construct, IJavaScriptValue thisValue, IEnumerable<IJavaScriptValue> args)
 {
     Log.Message(string.Format(args.First().ToString(), (object[])args.Skip(1).ToArray()));
     return source.UndefinedValue;
 }
 internal JavaScriptArrayBuffer(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine) :
     base(handle, type, engine)
 {
     len_ = new Lazy <uint>(GetLength);
 }
Example #31
0
        private IJavaScriptValue EchoForNoNamespace(JavaScriptEngine source, bool construct, IJavaScriptValue thisValue, IEnumerable<IJavaScriptValue> args)
        {
            string arg = args.First().ToString();

            Assert.AreEqual("callback completed", arg);
            successSignal.SetResult(0);
            return source.UndefinedValue;
        }
Example #32
0
 internal JavaScriptFunction(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine) :
     base(handle, type, engine)
 {
 }
Example #33
0
 public void Dispose()
 {
     engine_.ReleaseContextPrivate(previousEngine_);
     engine_ = null;
 }
Example #34
0
        internal JavaScriptDataView(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine) :
            base(handle, type, engine)
        {

        }
        private void ProjectMethods(string owningTypeName, JavaScriptObject target, JavaScriptEngine engine, IEnumerable<MethodInfo> methods)
        {
            var methodsByName = methods.GroupBy(m => m.Name);
            foreach (var group in methodsByName)
            {
                var method = engine.CreateFunction((eng, ctor, thisObj, args) =>
                {
                    var @this = thisObj as JavaScriptObject;
                    if (@this == null)
                    {
                        eng.SetException(eng.CreateTypeError("Could not call method '" + group.Key + "' because there was an invalid 'this' context."));
                        return eng.UndefinedValue;
                    }

                    var argsArray = args.ToArray();
                    var candidate = GetBestFitMethod(group, thisObj, argsArray);
                    if (candidate == null)
                    {
                        eng.SetException(eng.CreateReferenceError("Could not find suitable method or not enough arguments to invoke '" + group.Key + "'."));
                        return eng.UndefinedValue;
                    }

                    List<object> argsToPass = new List<object>();
                    for (int i = 0; i < candidate.GetParameters().Length; i++)
                    {
                        argsToPass.Add(ToObject(argsArray[i]));
                    }

                    try
                    {
                        return FromObject(candidate.Invoke(@this.ExternalObject, argsToPass.ToArray()));
                    }
                    catch (Exception ex)
                    {
                        eng.SetException(FromObject(ex));
                        return eng.UndefinedValue;
                    }
                }, owningTypeName + "." + group.Key);
                //var propDescriptor = engine.CreateObject();
                //propDescriptor.SetPropertyByName("configurable", engine.TrueValue);
                //propDescriptor.SetPropertyByName("enumerable", engine.TrueValue);
                //propDescriptor.SetPropertyByName("value", method);
                //target.DefineProperty(group.Key, propDescriptor);
                target.SetPropertyByName(group.Key, method);
            }
        }
 public override void Setup()
 {
     var settings = new JavaScriptRuntimeSettings() { AllowScriptInterrupt = true, };
     runtime_ = new JavaScriptRuntime(settings);
     engine_ = runtime_.CreateEngine();
 }
Example #37
0
 internal JavaScriptDataView(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine) :
     base(handle, type, engine)
 {
 }
 internal JavaScriptTypedArray(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine):
     base(handle, type, engine)
 {
     arrayType_ = new Lazy<JavaScriptTypedArrayType>(GetArrayType);
 }
Example #39
0
        private void ProjectEvents(string owningTypeName, JavaScriptObject target, JavaScriptEngine engine, IEnumerable <EventInfo> events, JavaScriptProjection baseTypeProjection, bool instance)
        {
            var eventsArray  = events.ToArray();
            var eventsLookup = eventsArray.ToDictionary(ei => ei.Name.ToLower());
            // General approach here
            // if there is a base thing, invoke that
            // for each event, register a delegate that marshals it back to JavaScript
            var add = engine.CreateFunction((eng, ctor, thisObj, args) =>
            {
                bool callBase = instance && (baseTypeProjection?.HasInstanceEvents ?? false);
                var @this     = thisObj as JavaScriptObject;
                if (@this == null)
                {
                    return(eng.UndefinedValue);
                }

                if (callBase)
                {
                    var baseObj = baseTypeProjection.Prototype;
                    var baseFn  = baseObj.GetPropertyByName("addEventListener") as JavaScriptFunction;
                    if (baseFn != null)
                    {
                        baseFn.Call(@this, args);
                    }
                }

                var argsArray = args.ToArray();
                if (argsArray.Length < 2)
                {
                    return(eng.UndefinedValue);
                }

                string eventName = argsArray[0].ToString();
                JavaScriptFunction callbackFunction = argsArray[1] as JavaScriptFunction;
                if (callbackFunction == null)
                {
                    return(eng.UndefinedValue);
                }

                EventInfo curEvent;
                if (!eventsLookup.TryGetValue(eventName, out curEvent))
                {
                    return(eng.UndefinedValue);
                }

                MethodInfo targetMethod = curEvent.EventHandlerType.GetMethod("Invoke");

                var paramsExpr = targetMethod.GetParameters().Select(p => Expression.Parameter(p.ParameterType, p.Name)).ToArray();
                int cookie     = EventMarshaler.RegisterDelegate(callbackFunction, SynchronizationContext.Current);

                var marshaler = Expression.Lambda(curEvent.EventHandlerType, Expression.Block(
                                                      Expression.Call(
                                                          typeof(EventMarshaler).GetMethod(nameof(EventMarshaler.InvokeJavaScriptCallback)),
                                                          Expression.Constant(cookie),
                                                          Expression.NewArrayInit(typeof(string), targetMethod.GetParameters().Select(p => Expression.Constant(p.Name))),
                                                          Expression.NewArrayInit(typeof(object), paramsExpr))
                                                      ), paramsExpr);

                curEvent.AddMethod.Invoke(@this.ExternalObject, new object[] { marshaler.Compile() });

                return(eng.UndefinedValue);
            }, owningTypeName + ".addEventListener");

            target.SetPropertyByName("addEventListener", add);
        }
 // used by InitializeProjectionForType
 private JavaScriptObject CreateObjectFor(JavaScriptEngine engine, JavaScriptProjection baseTypeProjection)
 {
     if (baseTypeProjection != null)
     {
         // todo: revisit to see if there is a better way to do this
         // Can probably get 
         // ((engine.GlobalObject.GetPropertyByName("Object") as JavaScriptObject).GetPropertyByName("create") as JavaScriptFunction).Invoke(baseTypeProjection.Prototype) 
         // but this is so much clearer
         dynamic global = engine.GlobalObject;
         JavaScriptObject result = global.Object.create(baseTypeProjection.Prototype);
         return result;
     }
     else
     {
         return engine.CreateObject();
     }
 }
Example #41
0
 internal JavaScriptSymbol(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine) :
     base(handle, type, engine)
 {
 }
        private void ProjectProperties(string owningTypeName, JavaScriptObject target, JavaScriptEngine engine, IEnumerable<PropertyInfo> properties)
        {
            foreach (var prop in properties)
            {
                if (prop.GetIndexParameters().Length > 0)
                    throw new NotSupportedException("Index properties not supported for projecting CLR to JavaScript objects.");

                JavaScriptFunction jsGet = null, jsSet = null;
                if (prop.GetMethod != null)
                {
                    jsGet = engine.CreateFunction((eng, ctor, thisObj, args) =>
                    {
                        var @this = thisObj as JavaScriptObject;
                        if (@this == null)
                        {
                            eng.SetException(eng.CreateTypeError("Could not retrieve property '" + prop.Name + "' because there was an invalid 'this' context."));
                            return eng.UndefinedValue;
                        }

                        try
                        {
                            return FromObject(prop.GetValue(@this.ExternalObject));
                        }
                        catch (Exception ex)
                        {
                            eng.SetException(FromObject(ex));
                            return eng.UndefinedValue;
                        }
                    }, owningTypeName + "." + prop.Name + ".get");
                }
                if (prop.SetMethod != null)
                {
                    jsSet = engine.CreateFunction((eng, ctor, thisObj, args) =>
                    {
                        var @this = thisObj as JavaScriptObject;
                        if (@this == null)
                        {
                            eng.SetException(eng.CreateTypeError("Could not retrieve property '" + prop.Name + "' because there was an invalid 'this' context."));
                            return eng.UndefinedValue;
                        }

                        try
                        {
                            var val = ToObject(args.First());
                            if (prop.PropertyType == typeof(int))
                            {
                                val = (int)(double)val;
                            }
                            prop.SetValue(@this.ExternalObject, val);
                            return eng.UndefinedValue;
                        }
                        catch (Exception ex)
                        {
                            eng.SetException(FromObject(ex));
                            return eng.UndefinedValue;
                        }
                    }, owningTypeName + "." + prop.Name + ".set");
                }

                var descriptor = engine.CreateObject();
                if (jsGet != null)
                    descriptor.SetPropertyByName("get", jsGet);
                if (jsSet != null)
                    descriptor.SetPropertyByName("set", jsSet);
                descriptor.SetPropertyByName("enumerable", engine.TrueValue);
                target.DefineProperty(prop.Name, descriptor);
            }
        }
Example #43
0
 public async Task Cleanup()
 {
     await DispatchContainer.GlobalDispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
     {
         engine_.Dispose();
         engine_ = null;
         runtime_.Dispose();
         runtime_ = null;
     });
 }
Example #44
0
 public override void Setup()
 {
     runtime_ = new JavaScriptRuntime();
     engine_ = runtime_.CreateEngine();
 }
Example #45
0
        public static void CheckForScriptExceptionOrThrow(JsErrorCode errorCode, JavaScriptEngine engine)
        {
            if (errorCode == JsErrorCode.JsErrorScriptException)
            {
                engine.OnRuntimeExceptionRaised();
                return;
            }

            if (errorCode != JsErrorCode.JsNoError)
                ThrowFor(errorCode);
        }
Example #46
0
 static JavaScriptValue Echo(JavaScriptEngine engine, bool construct, JavaScriptValue thisValue, IEnumerable<JavaScriptValue> arguments)
 {
     Console.WriteLine(arguments.First().ToString(), (object[])arguments.Skip(1).ToArray());
     return engine.UndefinedValue;
 }
Example #47
0
        private void ProjectMethods(string owningTypeName, JavaScriptObject target, JavaScriptEngine engine, IEnumerable <MethodInfo> methods)
        {
            var methodsByName = methods.GroupBy(m => m.Name);

            foreach (var group in methodsByName)
            {
                var groupKey        = group.Key;
                var groupCandidates = group.ToList();
                var method          = engine.CreateFunction((eng, ctor, thisObj, args) =>
                {
                    var @this = thisObj as JavaScriptObject;
                    if (@this == null)
                    {
                        if (thisObj.Type == JavaScriptValueType.Undefined)
                        {
                            var global = engine.GlobalObject.Prototype;
                            thisObj    = @this = global;
                        }
                        else
                        {
                            eng.SetException(eng.CreateTypeError("Could not call method '" + groupKey + "' because there was an invalid 'this' context."));
                            return(eng.UndefinedValue);
                        }
                    }

                    var argsArray = args.ToArray();
                    var candidate = GetBestFitMethod(groupCandidates, thisObj, argsArray);
                    if (candidate == null)
                    {
                        eng.SetException(eng.CreateReferenceError("Could not find suitable method or not enough arguments to invoke '" + groupKey + "'."));
                        return(eng.UndefinedValue);
                    }

                    if (!parameterCache.TryGetValue(candidate, out var parameters))
                    {
                        parameters = candidate.GetParameters();
                        parameterCache[candidate] = parameters;
                    }


                    var parameterCount = parameters.Length;
                    var argsToPass     = engine.BorrowArrayOfObjects(parameterCount);
                    for (int i = 0; i < parameterCount && i < argsArray.Length; i++)
                    {
                        var val           = ToObject(argsArray[i]);
                        var parameterType = parameters[i].ParameterType;
                        if (val != null && parameterType == typeof(string) && !(val is string))
                        {
                            val = argsArray[i].ToString();
                        }
                        if (val is Double d && parameterType != typeof(Double))
                        {
                            val = Convert.ChangeType(val, parameterType);
                        }
                        argsToPass[i] = val;
                    }

                    var t      = @this;
                    object obj = null;
                    while (obj == null && t.IsTruthy && t.Prototype != null)
                    {
                        obj = t.ExternalObject;
                        if (obj == null)
                        {
                            t = t.Prototype;
                        }
                    }

                    try
                    {
                        var result = FromObject(candidate.Invoke(obj, argsToPass));
                        engine.ReleaseArrayOfObjects(argsToPass);
                        return(result);
                    }
                    catch (Exception ex)
                    {
                        eng.SetException(FromObject(ex), ex);
                        return(eng.UndefinedValue);
                    }
                }, owningTypeName + "." + groupKey);
                //var propDescriptor = engine.CreateObject();
                //propDescriptor.SetPropertyByName("configurable", engine.TrueValue);
                //propDescriptor.SetPropertyByName("enumerable", engine.TrueValue);
                //propDescriptor.SetPropertyByName("value", method);
                //target.DefineProperty(group.Key, propDescriptor);
                target.SetPropertyByName(groupKey, method);
            }
        }
 internal JavaScriptArrayBuffer(JavaScriptValueSafeHandle handle, JavaScriptValueType type, JavaScriptEngine engine):
     base(handle, type, engine)
 {
     len_ = new Lazy<uint>(GetLength);
 }
Example #49
0
        private void ProjectProperties(string owningTypeName, JavaScriptObject target, JavaScriptEngine engine, IEnumerable <PropertyInfo> properties)
        {
            foreach (var prop in properties)
            {
                if (prop.GetIndexParameters().Length > 0)
                {
                    throw new NotSupportedException("Index properties not supported for projecting CLR to JavaScript objects.");
                }

                JavaScriptFunction jsGet = null, jsSet = null;
                if (prop.GetMethod != null)
                {
                    jsGet = engine.CreateFunction((eng, ctor, thisObj, args) =>
                    {
                        var @this = thisObj as JavaScriptObject;
                        if (@this == null)
                        {
                            eng.SetException(eng.CreateTypeError("Could not retrieve property '" + prop.Name + "' because there was an invalid 'this' context."));
                            return(eng.UndefinedValue);
                        }


                        object external = null;
                        if (!prop.GetMethod.IsStatic)
                        {
                            external = @this.ExternalObject;
                            if (external == null)
                            {
                                external = @this.Prototype.ExternalObject;
                            }
                            if (external == null)
                            {
                                throw new Exception("this object not found for method invocation. Perhaps it has been garbage collected.");
                            }
                        }
                        try
                        {
                            return(FromObject(prop.GetValue(external)));
                        }
                        catch (Exception ex)
                        {
                            eng.SetException(FromObject(ex), ex);
                            return(eng.UndefinedValue);
                        }
                    }, owningTypeName + "." + prop.Name + ".get");
                }
                if (prop.SetMethod != null)
                {
                    jsSet = engine.CreateFunction((eng, ctor, thisObj, args) =>
                    {
                        var @this = thisObj as JavaScriptObject;
                        if (@this == null)
                        {
                            eng.SetException(eng.CreateTypeError("Could not retrieve property '" + prop.Name + "' because there was an invalid 'this' context."));
                            return(eng.UndefinedValue);
                        }

                        try
                        {
                            var val = ToObject(args.First());
                            if (prop.PropertyType == typeof(int))
                            {
                                val = (int)(double)val;
                            }
                            var obj = @this.ExternalObject;
                            if (obj == null && @this.Prototype.ExternalObject == engine.GlobalObject.Prototype.ExternalObject)
                            {
                                obj = @this.Prototype.ExternalObject;
                            }
                            prop.SetValue(obj, val);
                            return(eng.UndefinedValue);
                        }
                        catch (Exception ex)
                        {
                            eng.SetException(FromObject(ex), ex);
                            return(eng.UndefinedValue);
                        }
                    }, owningTypeName + "." + prop.Name + ".set");
                }

                var descriptor = engine.CreateObject();
                if (jsGet != null)
                {
                    descriptor.SetPropertyByName("get", jsGet);
                }
                if (jsSet != null)
                {
                    descriptor.SetPropertyByName("set", jsSet);
                }
                descriptor.SetPropertyByName("enumerable", engine.TrueValue);
                target.DefineProperty(prop.Name, descriptor);
            }
        }