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); }
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); } }
public bool TryCreatePrototypeFunction(BaristaContext context, Type typeToConvert, out JsFunction ctor) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (typeToConvert == null) { throw new ArgumentNullException(nameof(typeToConvert)); } if (m_prototypes.ContainsKey(typeToConvert)) { ctor = m_prototypes[typeToConvert]; return(true); } var reflector = new ObjectReflector(typeToConvert); JsFunction superCtor = null; var baseType = reflector.GetBaseType(); if (baseType != null && !baseType.IsSameOrSubclass(typeof(JsValue)) && TryCreatePrototypeFunction(context, baseType, out JsFunction fnSuper)) { superCtor = fnSuper; } var objectName = BaristaObjectAttribute.GetBaristaObjectNameFromType(typeToConvert); //Get all the property descriptors for the specified type. var staticPropertyDescriptors = context.CreateObject(); var instancePropertyDescriptors = context.CreateObject(); //Get static and instance properties. ProjectProperties(context, staticPropertyDescriptors, reflector.GetProperties(false)); ProjectProperties(context, instancePropertyDescriptors, reflector.GetProperties(true)); //Get static and instance indexer properties. ProjectIndexerProperties(context, staticPropertyDescriptors, reflector.GetIndexerProperties(false)); ProjectIndexerProperties(context, instancePropertyDescriptors, reflector.GetIndexerProperties(true)); //Get static and instance methods. ProjectMethods(context, staticPropertyDescriptors, reflector, reflector.GetUniqueMethodsByName(false)); ProjectMethods(context, instancePropertyDescriptors, reflector, reflector.GetUniqueMethodsByName(true)); //Get static and instance events. ProjectEvents(context, staticPropertyDescriptors, reflector, reflector.GetEventTable(false)); ProjectEvents(context, instancePropertyDescriptors, reflector, reflector.GetEventTable(true)); //Get the [[iterator]] property. ProjectIEnumerable(context, instancePropertyDescriptors, reflector); JsFunction fnCtor; var publicConstructors = reflector.GetConstructors(); if (publicConstructors.Any()) { fnCtor = context.CreateFunction(new BaristaFunctionDelegate((calleeObj, isConstructCall, thisObj, args) => { if (thisObj == null) { var ex = context.CreateTypeError($"Failed to construct '{objectName}': 'this' must be specified."); context.CurrentScope.SetException(ex); return(context.Undefined); } if (superCtor != null) { superCtor.Call(thisObj); } context.Object.DefineProperties(thisObj, instancePropertyDescriptors); //If this isn't a construct call, don't attempt to set the bean if (!isConstructCall) { return(thisObj); } //Set our native object. JsExternalObject externalObject = null; //!!Special condition -- if there's exactly one argument, and if it matches the enclosing type, //don't invoke the type's constructor, rather, just wrap the object with the JsObject. if (args.Length == 1 && args[0].GetType() == typeToConvert) { externalObject = context.CreateExternalObject(args[0]); } else { try { var bestConstructor = reflector.GetConstructorBestMatch(args); if (bestConstructor == null) { var ex = context.CreateTypeError($"Failed to construct '{objectName}': Could not find a matching constructor for the provided arguments."); context.CurrentScope.SetException(ex); return(context.Undefined); } //Convert the args into the native args of the constructor. var constructorParams = bestConstructor.GetParameters(); var convertedArgs = ConvertArgsToParamTypes(context, args, constructorParams); var newObj = bestConstructor.Invoke(convertedArgs); externalObject = context.CreateExternalObject(newObj); } catch (Exception ex) { context.CurrentScope.SetException(context.CreateError(ex.Message)); return(context.Undefined); } } thisObj.SetBean(externalObject); return(thisObj); }), objectName); } else { fnCtor = context.CreateFunction(new BaristaFunctionDelegate((calleeObj, isConstructCall, thisObj, args) => { var ex = context.CreateTypeError($"Failed to construct '{objectName}': This object cannot be constructed."); context.CurrentScope.SetException(ex); return(context.Undefined); }), objectName); } //We've got everything we need. fnCtor.Prototype = context.Object.Create(superCtor == null ? context.Object.Prototype : superCtor.Prototype); context.Object.DefineProperties(fnCtor, staticPropertyDescriptors); m_prototypes.Add(typeToConvert, fnCtor); ctor = fnCtor; return(true); }