public Task <JsValue> Json() { if (TryCheckBodyUsed()) { return(Task.FromResult <JsValue>(m_context.Undefined)); } var result = m_context.JSON.Parse(m_context.CreateString(m_response.Content)); m_bodyUsed = true; return(Task.FromResult(result)); }
public BaristaModuleRecord CreateBaristaModuleRecord(BaristaContext context, string moduleName, BaristaModuleRecord parentModule = null, bool setAsHost = false, IBaristaModuleLoader moduleLoader = null) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var moduleNameValue = context.CreateString(moduleName); return(CreateBaristaModuleRecordInternal(context, moduleName, moduleNameValue.Handle, parentModule, setAsHost, moduleLoader)); }
private void ProjectProperties(BaristaContext context, JsObject targetObject, IEnumerable <PropertyInfo> properties) { foreach (var prop in properties) { var propertyAttribute = BaristaPropertyAttribute.GetAttribute(prop); var propertyName = propertyAttribute.Name; var propertyDescriptor = context.CreateObject(); if (propertyAttribute.Configurable) { propertyDescriptor.SetProperty("configurable", context.True); } if (propertyAttribute.Enumerable) { propertyDescriptor.SetProperty("enumerable", context.True); } if (prop.GetMethod != null) { var jsGet = context.CreateFunction(new BaristaFunctionDelegate((calleeObj, isConstructCall, thisObj, args) => { return(GetPropertyValue(context, prop, propertyName, thisObj)); })); propertyDescriptor.SetProperty("get", jsGet); } if (prop.SetMethod != null) { var jsSet = context.CreateFunction(new BaristaFunctionDelegate((calleeObj, isConstructCall, thisObj, args) => { return(SetPropertyValue(context, prop, propertyName, thisObj, args)); })); propertyDescriptor.SetProperty("set", jsSet); } targetObject.SetProperty(context.CreateString(propertyName), propertyDescriptor); } }
private void ProjectEvents(BaristaContext context, JsObject targetObject, ObjectReflector reflector, IDictionary <string, EventInfo> eventsTable) { if (eventsTable.Count == 0) { return; } var fnAddEventListener = context.CreateFunction(new Func <JsObject, string, JsFunction, JsValue>((thisObj, eventName, fnCallback) => { if (String.IsNullOrWhiteSpace(eventName)) { context.CurrentScope.SetException(context.CreateTypeError($"The name of the event listener to register must be specified.")); return(context.Undefined); } object targetObj = null; if (thisObj == null) { context.CurrentScope.SetException(context.CreateTypeError($"Could not register event listener '{eventName}': Invalid 'this' context.")); return(context.Undefined); } if (thisObj.TryGetBean(out JsExternalObject xoObj)) { targetObj = xoObj.Target; } if (!eventsTable.TryGetValue(eventName, out EventInfo targetEvent)) { return(context.False); } Action <object[]> invokeListener = (args) => { //TODO: Object conversion. fnCallback.Call(thisObj, null); }; var targetEventMethod = targetEvent.EventHandlerType.GetMethod("Invoke"); var targetEventParameters = targetEventMethod.GetParameters().Select(p => Expression.Parameter(p.ParameterType, p.Name)).ToArray(); var exprInvokeListener = Expression.Lambda(targetEvent.EventHandlerType, Expression.Block( Expression.Call( Expression.Constant(invokeListener.Target), invokeListener.Method, Expression.NewArrayInit(typeof(object), targetEventParameters)) ), targetEventParameters); var invokeListenerDelegate = exprInvokeListener.Compile(); IDictionary <string, IList <Tuple <JsFunction, Delegate> > > eventListeners; if (thisObj.HasProperty(BaristaEventListenersPropertyName)) { var xoListeners = thisObj.GetProperty <JsExternalObject>(BaristaEventListenersPropertyName); eventListeners = xoListeners.Target as IDictionary <string, IList <Tuple <JsFunction, Delegate> > >; } else { eventListeners = new Dictionary <string, IList <Tuple <JsFunction, Delegate> > >(); //Set the listeners as a non-configurable, non-enumerable, non-writable property var xoListeners = context.CreateExternalObject(eventListeners); var baristaEventListenersPropertyDescriptor = context.CreateObject(); baristaEventListenersPropertyDescriptor.SetProperty("value", xoListeners); context.Object.DefineProperty(thisObj, context.CreateString(BaristaEventListenersPropertyName), baristaEventListenersPropertyDescriptor); } if (eventListeners != null) { if (eventListeners.ContainsKey(eventName)) { eventListeners[eventName].Add(new Tuple <JsFunction, Delegate>(fnCallback, invokeListenerDelegate)); } else { eventListeners.Add(eventName, new List <Tuple <JsFunction, Delegate> >() { new Tuple <JsFunction, Delegate>(fnCallback, invokeListenerDelegate) }); } } targetEvent.AddMethod.Invoke(targetObj, new object[] { invokeListenerDelegate }); return(context.True); }), "addEventListener"); var fnRemoveEventListener = context.CreateFunction(new Func <JsObject, string, JsFunction, JsValue>((thisObj, eventName, eventListener) => { if (String.IsNullOrWhiteSpace(eventName)) { context.CurrentScope.SetException(context.CreateTypeError($"The name of the event listener to remove must be specified.")); return(context.Undefined); } if (eventListener == null) { context.CurrentScope.SetException(context.CreateTypeError($"The event listener to remove must be specified.")); return(context.Undefined); } object targetObj = null; if (thisObj == null) { context.CurrentScope.SetException(context.CreateTypeError($"Could not unregister event listener '{eventName}': Invalid 'this' context.")); return(context.Undefined); } if (thisObj.TryGetBean(out JsExternalObject xoObj)) { targetObj = xoObj.Target; } if (!eventsTable.TryGetValue(eventName, out EventInfo targetEvent)) { return(context.False); } //Get the event listeners. IDictionary <string, IList <Tuple <JsFunction, Delegate> > > eventListeners = null; if (thisObj.HasProperty(BaristaEventListenersPropertyName)) { var xoListeners = thisObj.GetProperty <JsExternalObject>(BaristaEventListenersPropertyName); eventListeners = xoListeners.Target as IDictionary <string, IList <Tuple <JsFunction, Delegate> > >; } if (eventListeners == null) { return(context.False); } var hasRemoved = false; if (eventListeners.ContainsKey(eventName)) { var listeners = eventListeners[eventName]; var toRemove = new List <Tuple <JsFunction, Delegate> >(); foreach (var listener in listeners) { if (listener.Item1 == eventListener) { targetEvent.RemoveMethod.Invoke(targetObj, new object[] { listener.Item2 }); toRemove.Add(listener); hasRemoved = true; } } eventListeners[eventName] = listeners.Where(l => toRemove.Any(tl => tl == l)).ToList(); } return(hasRemoved ? context.True : context.False); }), "removeEventListener"); var fnRemoveAllEventListeners = context.CreateFunction(new Func <JsObject, string, JsValue>((thisObj, eventName) => { if (String.IsNullOrWhiteSpace(eventName)) { context.CurrentScope.SetException(context.CreateTypeError($"The name of the event listener to remove must be specified.")); return(context.Undefined); } object targetObj = null; if (thisObj == null) { context.CurrentScope.SetException(context.CreateTypeError($"Could not unregister event listener '{eventName}': Invalid 'this' context.")); return(context.Undefined); } if (thisObj.TryGetBean(out JsExternalObject xoObj)) { targetObj = xoObj.Target; } if (!eventsTable.TryGetValue(eventName, out EventInfo targetEvent)) { return(context.False); } //Get the event listeners. IDictionary <string, IList <Tuple <JsFunction, Delegate> > > eventListeners = null; if (thisObj.HasProperty(BaristaEventListenersPropertyName)) { var xoListeners = thisObj.GetProperty <JsExternalObject>(BaristaEventListenersPropertyName); eventListeners = xoListeners.Target as IDictionary <string, IList <Tuple <JsFunction, Delegate> > >; } if (eventListeners == null) { return(context.False); } if (eventListeners.ContainsKey(eventName)) { foreach (var listener in eventListeners[eventName]) { targetEvent.RemoveMethod.Invoke(targetObj, new object[] { listener.Item2 }); } eventListeners.Remove(eventName); } return(context.True); }), "removeAllEventListeners"); var addEventListenerFunctionDescriptor = context.CreateObject(); addEventListenerFunctionDescriptor.SetProperty("enumerable", context.True); addEventListenerFunctionDescriptor.SetProperty("value", fnAddEventListener); targetObject.SetProperty(context.CreateString("addEventListener"), addEventListenerFunctionDescriptor); var removeEventListenerFunctionDescriptor = context.CreateObject(); removeEventListenerFunctionDescriptor.SetProperty("enumerable", context.True); removeEventListenerFunctionDescriptor.SetProperty("value", fnRemoveEventListener); targetObject.SetProperty(context.CreateString("removeEventListener"), removeEventListenerFunctionDescriptor); var removeAllEventListenersFunctionDescriptor = context.CreateObject(); removeAllEventListenersFunctionDescriptor.SetProperty("enumerable", context.True); removeAllEventListenersFunctionDescriptor.SetProperty("value", fnRemoveAllEventListeners); targetObject.SetProperty(context.CreateString("removeAllEventListeners"), removeAllEventListenersFunctionDescriptor); }
private void ProjectMethods(BaristaContext context, JsObject targetObject, ObjectReflector reflector, IDictionary <string, IList <MethodInfo> > methods) { foreach (var method in methods) { var methodName = method.Key; var methodInfos = method.Value; var fn = context.CreateFunction(new BaristaFunctionDelegate((calleeObj, isConstructCall, thisObj, args) => { object targetObj = null; if (thisObj == null) { context.CurrentScope.SetException(context.CreateTypeError($"Could not call function '{methodName}': Invalid 'this' context.")); return(context.Undefined); } if (thisObj.TryGetBean(out JsExternalObject xoObj)) { targetObj = xoObj.Target; } try { var bestMethod = reflector.GetMethodBestMatch(methodInfos, args); if (bestMethod == null) { var ex = context.CreateTypeError($"Failed to call function '{methodName}': Could not find a matching function for the provided arguments."); context.CurrentScope.SetException(ex); return(context.Undefined); } //Convert the args into the native args of the method. var methodParams = bestMethod.GetParameters(); var convertedArgs = ConvertArgsToParamTypes(context, args, methodParams); var result = bestMethod.Invoke(targetObj, convertedArgs); if (context.Converter.TryFromObject(context, result, out JsValue resultValue)) { return(resultValue); } else { context.CurrentScope.SetException(context.CreateTypeError($"The call to '{methodName}' was successful, but the result could not be converted into a JavaScript object.")); return(context.Undefined); } } catch (Exception ex) { context.CurrentScope.SetException(context.CreateError(ex.Message)); return(context.Undefined); } })); var functionDescriptor = context.CreateObject(); if (methodInfos.All(mi => BaristaPropertyAttribute.GetAttribute(mi).Configurable)) { functionDescriptor.SetProperty("configurable", context.True); } if (methodInfos.All(mi => BaristaPropertyAttribute.GetAttribute(mi).Enumerable)) { functionDescriptor.SetProperty("enumerable", context.True); } if (methodInfos.All(mi => BaristaPropertyAttribute.GetAttribute(mi).Writable)) { functionDescriptor.SetProperty("writable", context.True); } functionDescriptor.SetProperty("value", fn); targetObject.SetProperty(context.CreateString(methodName), functionDescriptor); } }