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