public static JsTypeFunction Define(string name, JsTypeFunction prototype) { JsTypeFunction typeFunction = null; // Create constructor function, which is a superconstructor that takes in the actual // constructor as the first argument, and the rest of the arguments are passed directly // to that constructor. These subconstructors are not Javascript constructors -- they // are not called via new, they exist for initialization only. typeFunction = Jsni.function(constructor => { if (constructor != null || !(Jsni.instanceof(Jsni.@this(), typeFunction))) { Jsni.invoke(Jsni.member(typeFunction, SpecialNames.StaticInitializer)); } if (constructor != null) { Jsni.apply(constructor, Jsni.@this(), Jsni.call(Jsni.reference("Array.prototype.slice"), Jsni.arguments(), 1.As < JsObject > ()).As <JsArray>()); } if (!Jsni.instanceof(Jsni.@this(), typeFunction)) { return(typeFunction); } else { return(Jsni.@this()); } }).As <JsTypeFunction>(); Jsni.memberset(typeFunction, "toString", Jsni.function(() => name.As <JsObject>())); Jsni.memberset(typeFunction, SpecialNames.TypeName, name.As <JsString>()); Jsni.memberset(typeFunction, "prototype", Jsni.@new(prototype)); return(typeFunction); }
public void Init(string fullName, int flags, JsTypeFunction thisType, JsTypeFunction baseType, JsTypeFunction[] interfaces, JsTypeFunction[] typeArguments, FieldInfo[] fields, MethodInfo[] methods, ConstructorInfo[] constructors, PropertyInfo[] properties, EventInfo[] events, JsTypeFunction elementType, JsTypeFunction unconstructedType) { FullName = fullName; typeFlags = (TypeFlags)flags; // this.typeAttributes = typeAttributes; this.thisType = thisType; this.baseType = baseType; this.interfaces = interfaces; this.typeArguments = typeArguments; this.fields = fields ?? new FieldInfo[0]; this.methods = methods ?? new MethodInfo[0]; this.properties = properties ?? new PropertyInfo[0]; this.constructors = constructors ?? new ConstructorInfo[0]; this.events = events ?? new EventInfo[0]; this.elementType = elementType; this.unconstructedType = unconstructedType; foreach (var field in this.fields) field.declaringType = this; foreach (var method in this.methods) method.declaringType = this; foreach (var property in this.properties) { property.declaringType = this; if (property.GetMethod != null) property.GetMethod.declaringType = this; if (property.SetMethod != null) property.SetMethod.declaringType = this; } foreach (var constructor in this.constructors) constructor.declaringType = this; }
public static object InternalToObject(JsTypeFunction enumType, object value) { var enumsByValue = enumsByTypeAndValue[enumType.TypeName]; Enum result = enumsByValue.GetOrDefault(value); if (result != null) { return(result); } else { // Otherwise it's an enum value that isn't represented by a declared member. In // this case, we need to box the value and then force it to be recognized as the // enum type. result = Jsni.@new(Jsni.reference("Number"), value.As <JsObject>()).As <Enum>(); foreach (var property in enumType.member("prototype")) { result.As <JsObject>()[property] = enumType.member("prototype")[property]; } foreach (var property in Jsni.type <Enum>().member("prototype")) { result.As <JsObject>()[property] = Jsni.type <Enum>().member("prototype")[property]; } result.___type = enumType; result.As <JsObject>().memberset("value", value.As <JsObject>()); enumsByValue[value] = result; return(result); } }
public static JsObject DefaultOf(JsTypeFunction type) { var typeName = type.TypeName; switch (typeName) { case "System.Boolean": return(false); case "System.Byte": case "System.SByte": case "System.Int16": case "System.Int32": case "System.Int64": case "System.UInt16": case "System.UInt32": case "System.UInt64": case "System.Single": case "System.Double": case "System.Decimal": return(0.As < JsNumber > ()); default: return(null); } }
internal static JsArray InitializeArray(JsArray array, JsTypeFunction elementType) { if (array.member("$isInitialized")) { return(array); } array.memberset("$isInitialized", true); var arrayType = MakeArrayType(elementType); // This is way faster than the foreach/for...in that was used below. So we'll just copy the methods we need manually. array["System$Collections$Generic$IEnumerable$1$GetEnumerator"] = arrayType.member("prototype")["System$Collections$Generic$IEnumerable$1$GetEnumerator"]; array["GetEnumerator"] = arrayType.member("prototype")["System$Collections$Generic$IEnumerable$1$GetEnumerator"]; array["GetType"] = arrayType.member("prototype")["GetType"]; array["$type"] = arrayType.member("prototype")["$type"]; array["System$Collections$Generic$IReadOnlyList$1$get_Item"] = arrayType.member("prototype")["System$Collections$Generic$IReadOnlyList$1$get_Item"]; // foreach (var property in arrayType.member("prototype")) // { // array[property] = arrayType.member("prototype")[property]; // } arrayType.member("prototype").member("$ctor").member("call").invoke(array); return(array); }
public static Type CreateTypeParameter(string fullName, JsTypeFunction baseType) { var type = new Type(fullName, new Attribute[0]); type.Init(fullName, (int)TypeFlags.GenericParameter, null, baseType, new JsTypeFunction[0], new JsTypeFunction[0], new FieldInfo[0], new MethodInfo[0], new ConstructorInfo[0], new PropertyInfo[0], new EventInfo[0], null, null); return type; }
public void Init(string fullName, int flags, JsTypeFunction thisType, JsTypeFunction baseType, JsTypeFunction[] interfaces, JsTypeFunction[] typeArguments, FieldInfo[] fields, MethodInfo[] methods, ConstructorInfo[] constructors, PropertyInfo[] properties, EventInfo[] events, JsTypeFunction elementType, JsTypeFunction unconstructedType) { FullName = fullName; typeFlags = (TypeFlags)flags; if ((typeFlags & TypeFlags.GenericType) != 0) isGenericType = true; if ((typeFlags & TypeFlags.ValueType) != 0) isValueType = true; if ((typeFlags & TypeFlags.Primitive) != 0) isPrimitive = true; if ((typeFlags & TypeFlags.Abstract) != 0) isAbstract = true; if ((typeFlags & TypeFlags.Interface) != 0) isInterface = true; if ((typeFlags & TypeFlags.Sealed) != 0) isSealed = true; if ((typeFlags & TypeFlags.Public) != 0) isPublic = true; if ((typeFlags & TypeFlags.Enum) != 0) isEnum = true; if ((typeFlags & TypeFlags.GenericTypeDefenition) != 0) isGenericTypeDefinition = true; if ((typeFlags & TypeFlags.GenericParameter) != 0) isGenericParameter = true; // this.typeAttributes = typeAttributes; this.thisType = thisType; this.baseType = baseType; this.interfaces = interfaces; this.typeArguments = typeArguments; this.fields = fields ?? new FieldInfo[0]; this.methods = methods ?? new MethodInfo[0]; this.properties = properties ?? new PropertyInfo[0]; this.constructors = constructors ?? new ConstructorInfo[0]; this.events = events ?? new EventInfo[0]; this.elementType = elementType; this.unconstructedType = unconstructedType; foreach (var field in this.fields) field.declaringType = this; foreach (var method in this.methods) method.declaringType = this; foreach (var property in this.properties) { property.declaringType = this; if (property.GetMethod != null) property.GetMethod.declaringType = this; if (property.SetMethod != null) property.SetMethod.declaringType = this; } foreach (var constructor in this.constructors) constructor.declaringType = this; }
internal static JsArray InitializeArray(JsArray array, JsTypeFunction elementType) { if (array.member("$isInitialized")) { return(array); } array.memberset("$isInitialized", true); var arrayType = MakeArrayType(elementType); // This is way faster than the foreach/for...in that was used below. So we'll just copy the methods we need manually. array["System$Collections$Generic$IEnumerable$1$GetEnumerator"] = arrayType.member("prototype")["System$Collections$Generic$IEnumerable$1$GetEnumerator"]; array["GetEnumerator"] = arrayType.member("prototype")["System$Collections$Generic$IEnumerable$1$GetEnumerator"]; array["GetType"] = arrayType.member("prototype")["GetType"]; array["$type"] = arrayType.member("prototype")["$type"]; array["System$Collections$Generic$IReadOnlyList$1$get_Item"] = arrayType.member("prototype")["System$Collections$Generic$IReadOnlyList$1$get_Item"]; /* * if (elementType.TypeName == "System.Int32") * { * array["System$Collections$IEnumerable$GetEnumerator"] = arrayType.member("prototype")["System$Collections$IEnumerable$GetEnumerator"]; * array["System$Collections$ICollection$get_Count"] = arrayType.member("prototype")["System$Collections$ICollection$get_Count"]; * array["System$Collections$Generic$IReadOnlyCollection$1$get_Count"] = arrayType.member("prototype")["System$Collections$Generic$IReadOnlyCollection$1$get_Count"]; * array["System$Collections$ICollection$get_SyncRoot"] = arrayType.member("prototype")["System$Collections$ICollection$get_SyncRoot"]; * array["System$Collections$ICollection$get_IsSynchronized"] = arrayType.member("prototype")["System$Collections$ICollection$get_IsSynchronized"]; * array["System$Collections$ICollection$CopyTo"] = arrayType.member("prototype")["System$Collections$ICollection$CopyTo"]; * array["System$Collections$IList$get_IsReadOnly"] = arrayType.member("prototype")["System$Collections$IList$get_IsReadOnly"]; * array["System$Collections$IList$get_IsFixedSize"] = arrayType.member("prototype")["System$Collections$IList$get_IsFixedSize"]; * array["System$Collections$IList$Add"] = arrayType.member("prototype")["System$Collections$IList$Add"]; * array["System$Collections$IList$Contains"] = arrayType.member("prototype")["System$Collections$IList$Contains"]; * array["System$Collections$IList$Clear"] = arrayType.member("prototype")["System$Collections$IList$Clear"]; * array["System$Collections$IList$Insert"] = arrayType.member("prototype")["System$Collections$IList$Insert"]; * array["System$Collections$IList$Remove"] = arrayType.member("prototype")["System$Collections$IList$Remove"]; * array["System$Collections$IList$RemoveAt"] = arrayType.member("prototype")["System$Collections$IList$RemoveAt"]; * array["GetValue"] = arrayType.member("prototype")["GetValue"]; * array["GetEnumerator"] = arrayType.member("prototype")["GetEnumerator"]; * array["get_Count"] = arrayType.member("prototype")["get_Count"]; * array["get_SyncRoot"] = arrayType.member("prototype")["get_SyncRoot"]; * array["get_IsSynchronized"] = arrayType.member("prototype")["get_IsSynchronized"]; * array["Copy"] = arrayType.member("prototype")["Copy"]; * array["Copy$2"] = arrayType.member("prototype")["Copy$2"]; * array["ConstrainedCopy"] = arrayType.member("prototype")["ConstrainedCopy"]; * array["Copy$1"] = arrayType.member("prototype")["Copy$1"]; * array["Copy$3"] = arrayType.member("prototype")["Copy$3"]; * } */ // foreach (var property in arrayType.member("prototype")) // { // array[property] = arrayType.member("prototype")[property]; // } arrayType.member("prototype").member("$ctor").member("call").invoke(array); return(array); }
public static JsTypeFunction DefineTypeParameter(string name, JsTypeFunction prototype) { var result = Define(name, prototype); result.memberset(SpecialNames.CreateType, Jsni.function(() => { var type = Type.CreateTypeParameter(name, prototype); result.Type = type; return(result); })); return(result); }
public static JsFunction DefineStaticConstructor(JsTypeFunction enclosingType, JsFunction implementation) { return(Jsni.procedure(() => { if (enclosingType.IsStaticInitialized) { return; } enclosingType.IsStaticInitialized = true; implementation.invoke(); })); }
public static JsFunction CreateConstructor(JsTypeFunction enclosingType, JsFunction implementation) { implementation.memberset(SpecialNames.TypeField, enclosingType); implementation.memberset(SpecialNames.New, Jsni.function(() => { /* * if (!enclosingType.IsPrototypeInitialized) * { * enclosingType.IsPrototypeInitialized = true; * enclosingType.prototype = Jsni.@new(enclosingType.PrototypeFactory.invoke()); * } */ return(Jsni.@new(enclosingType, implementation, Jsni.arguments())); })); return(implementation); }
internal static JsArray InitializeArray(JsArray array, JsTypeFunction elementType) { if (array.member("$isInitialized")) { return(array); } array.memberset("$isInitialized", true); var arrayType = MakeArrayType(elementType); foreach (var property in arrayType.member("prototype")) { array[property] = arrayType.member("prototype")[property]; } arrayType.member("prototype").member("$ctor").member("call").invoke(array); return(array); }
public static JsFunction CreateDelegate(JsObject thisExpression, JsTypeFunction delegateType, JsFunction lambda, string delegateKey = null) { if (delegateKey != null) { if (thisExpression[delegateKey]) { return(thisExpression[delegateKey].As <JsFunction>()); } } else { if (lambda.member("$delegate") != null) { return(lambda.member("$delegate").As <JsFunction>()); } } JsFunction delegateFunc = null; delegateFunc = Jsni.function(() => { return(lambda.apply(delegateFunc.As <Delegate>().Target.As <JsObject>(), Jsni.arguments().As <JsArray>())); }); delegateFunc.prototype = Jsni.@new(delegateType); Jsni.type <object>().TypeInitializer.invoke(delegateFunc, delegateFunc); Jsni.type <Delegate>().TypeInitializer.invoke(delegateFunc, delegateFunc); Jsni.type <MulticastDelegate>().TypeInitializer.invoke(delegateFunc, delegateFunc); delegateType.TypeInitializer.invoke(delegateFunc, delegateFunc); Jsni.invoke(Jsni.member(Jsni.member(Jsni.type <MulticastDelegate>().prototype, "$ctor"), "call"), delegateFunc, thisExpression, new[] { delegateFunc }.As <JsArray>()); Jsni.memberset(delegateFunc, SpecialNames.TypeField, delegateType); if (delegateKey != null) { thisExpression[delegateKey] = delegateFunc; } else { lambda.memberset("$delegate", delegateFunc); } return(delegateFunc); }
internal static JsTypeFunction MakeGenericTypeFactory(JsTypeFunction unconstructedType, JsArray typeArgs) { var cache = Jsni.member(unconstructedType, SpecialNames.TypeCache); if (cache == null) { cache = new JsObject(); unconstructedType.memberset(SpecialNames.TypeCache, cache); } var keyArray = Jsni.call <JsArray>(x => x.slice(0), typeArgs, 0.As < JsNumber > ()).As <JsArray>(); var keyParts = new JsArray(); for (var i = 0; i < keyArray.length; i++) { keyParts[i] = keyArray[i].member(SpecialNames.TypeName); } var keyString = keyParts.join(", "); var result = cache[keyString]; if (result == null) { var lastIndexOfDollar = unconstructedType.TypeName.LastIndexOf('`'); var newTypeName = unconstructedType.TypeName.Substring(0, lastIndexOfDollar) + "<" + keyString + ">"; var prototype = unconstructedType.BaseType; if (prototype.member("$")) { prototype = prototype.member("$").apply(null, typeArgs).As <JsTypeFunction>(); } var generic = Define(newTypeName, prototype); generic.memberset(SpecialNames.UnconstructedType, unconstructedType); // unconstructedType.$TypeInitializer.apply(this, [generic, generic.prototype].concat(Array.prototype.slice.call(arguments, 0))); Jsni.apply( Jsni.member(unconstructedType, SpecialNames.TypeInitializer), unconstructedType, Jsni.invoke( Jsni.member(Jsni.array(generic, generic.prototype), "concat"), keyArray ).As <JsArray>()); generic.TypeInitializer = Jsni.procedure((t, p) => { p.___type = generic; t.As <JsTypeFunction>().BaseType = unconstructedType; t.As <JsTypeFunction>().GetTypeFromType = Jsni.function(() => Type._GetTypeFromTypeFunc(Jsni.@this().As <JsTypeFunction>()).As <JsObject>()); t.As <JsTypeFunction>().TypeName = newTypeName; t.As <JsTypeFunction>().CreateTypeField = Jsni.function(() => { var unconstructedTypeType = Type._GetTypeFromTypeFunc(unconstructedType); var type = new Type(newTypeName, new Attribute[0]); generic.Type = type; type.thisType = generic; var typeParameters = unconstructedTypeType.typeArguments; var typeArguments = InitializeArray(typeArgs, Jsni.type <JsTypeFunction>()).As <JsTypeFunction[]>(); Func <Type, JsTypeFunction> reifyGenerics = null; reifyGenerics = theType => { if (theType == null) { return(null); } if (theType.IsArray) { var elementType = theType.GetElementType(); var arrayType = MakeArrayType(reifyGenerics(elementType)); return(arrayType); } if (theType.IsGenericParameter) { for (int i = 0; i < typeArguments.Length; i++) { var typeParameter = typeParameters[i]; var typeArgument = typeArguments[i]; if (typeParameter.TypeName == theType.FullName) { return(typeArgument); } } } else if (theType.IsGenericTypeDefinition) { return(MakeGenericTypeFactory(theType.thisType, theType.GenericTypeArguments.Select(x => reifyGenerics(x)).ToArray().As <JsArray>())); } else if (theType.IsGenericType) { JsTypeFunction[] newTypeArguments = null; for (var i = 0; i < theType.typeArguments.Length; i++) { var theTypeArgument = theType.typeArguments[i]; for (var j = 0; j < typeParameters.Length; j++) { var typeParameter = typeParameters[j]; var typeArgument = typeArguments[j]; if (theTypeArgument == typeParameter) { if (newTypeArguments == null) { newTypeArguments = new JsTypeFunction[theType.typeArguments.Length]; for (var k = 0; k < theType.typeArguments.Length; k++) { newTypeArguments[k] = theType.typeArguments[k]; } } newTypeArguments[i] = typeArgument; } } } if (newTypeArguments != null) { return(MakeGenericTypeFactory(theType.unconstructedType, newTypeArguments.As <JsArray>())); } else { return(theType.thisType); } } return(theType.thisType); }; var newInterfaces = unconstructedTypeType.interfaces.ToArray(); for (var i = 0; i < newInterfaces.Length; i++) { var intf = newInterfaces[i]; intf = reifyGenerics(Type._GetTypeFromTypeFunc(intf)); newInterfaces[i] = intf; } var newConstructors = unconstructedTypeType.constructors.ToArray(); for (var i = 0; i < newConstructors.Length; i++) { var constructor = newConstructors[i]; var parameters = constructor.GetParameters(); for (var j = 0; j < parameters.Length; j++) { var parameter = parameters[j]; var parameterType = reifyGenerics(parameter.ParameterType); parameter = new ParameterInfo(parameter.Name, parameterType, j, parameter.Attributes, parameter.DefaultValue, parameter.attributes); parameters[j] = parameter; } newConstructors[i] = new ConstructorInfo(constructor.Name, generic.prototype[constructor.Name].As <JsFunction>(), parameters, constructor.Attributes, constructor.attributes); } var newProperties = unconstructedTypeType.properties.ToArray(); for (var i = 0; i < newProperties.Length; i++) { var property = newProperties[i]; var propertyTypeType = property.PropertyType; var propertyType = reifyGenerics(propertyTypeType); newProperties[i] = new PropertyInfo(property.Name, propertyType, property.GetGetMethod(), property.GetSetMethod(), property.GetIndexParameters(), property.attributes); } var newMethods = unconstructedTypeType.methods.ToArray(); for (var i = 0; i < newMethods.Length; i++) { var method = newMethods[i]; var returnTypeType = method.ReturnType; var returnType = reifyGenerics(returnTypeType); var parameters = method.GetParameters(); for (var j = 0; j < parameters.Length; j++) { var parameter = parameters[j]; var parameterType = reifyGenerics(parameter.ParameterType); parameter = new ParameterInfo(parameter.Name, parameterType, j, parameter.Attributes, parameter.DefaultValue, parameter.attributes); parameters[j] = parameter; } method = new MethodInfo(method.Name, method.jsMethod, parameters, returnType, method.Attributes, method.attributes); newMethods[i] = method; } type.Init( newTypeName, unconstructedTypeType.typeAttributes, generic, unconstructedType.BaseType, newInterfaces, typeArguments, unconstructedTypeType.fields, newMethods, newConstructors, newProperties, unconstructedTypeType.events, false, unconstructedTypeType.IsAbstract, unconstructedTypeType.IsInterface, false, true, false, unconstructedTypeType.IsEnum, null, unconstructedType); return(type.As <JsObject>()); }); }, SpecialNames.TypeInitializerTypeFunction, SpecialNames.TypeInitializerPrototype); Jsni.call(generic.TypeInitializer, Jsni.@this(), generic, generic.prototype); result = generic; cache[keyString] = result; } return(result.As <JsTypeFunction>()); }
public static JsTypeFunction DefineTypeParameter(JsFunction assembly, string name, JsTypeFunction prototype) { var result = Define(assembly, null, name, false, Jsni.array(), prototype, Jsni.procedure(() => {})); result.memberset(SpecialNames.IsTypeParameter, true); result.memberset(SpecialNames.CreateType, Jsni.function(() => { var type = Type.CreateTypeParameter(name, prototype); result.Type = type; type.thisType = result; return(result); })); return(result); }
internal static JsTypeFunction MakeArrayType(JsTypeFunction elementType) { if (elementType.ArrayType == null) { var baseType = MakeGenericTypeFactory(Jsni.type(typeof(GenericArray <>)), Jsni.array(elementType)); var arrayType = Jsni.procedure(() => {}).As <JsTypeFunction>(); arrayType.prototype = Jsni.@new(baseType); Jsni.apply( Jsni.type <Object>().TypeInitializer, Jsni.@this(), Jsni.array(arrayType, arrayType.prototype)); Jsni.apply( Jsni.type <Array>().TypeInitializer, Jsni.@this(), Jsni.invoke( Jsni.member(Jsni.array(arrayType, arrayType.prototype), "concat"), elementType ).As <JsArray>()); arrayType.TypeInitializer = Jsni.procedure((t, p) => { p.___type = arrayType; t.As <JsTypeFunction>().TypeName = elementType.TypeName + "[]"; t.As <JsTypeFunction>().BaseType = baseType; t.As <JsTypeFunction>().ElementType = elementType; t.As <JsTypeFunction>().GetTypeFromType = Jsni.function(() => Type._GetTypeFromTypeFunc(Jsni.@this().As <JsTypeFunction>()).As <JsObject>()); t.As <JsTypeFunction>().CreateTypeField = Jsni.function(() => { var lastIndex = elementType.TypeName.LastIndexOf('.'); if (lastIndex == -1) { lastIndex = 0; } else { lastIndex++; } var type = new Type(elementType.TypeName.Substring(lastIndex) + "[]", new Attribute[0]); arrayType.Type = type; type.Init( elementType.TypeName + "[]", TypeAttributes.Public, elementType, Jsni.type <Array>(), typeof(Array).interfaces.Concat(new[] { SpecialFunctions.MakeGenericTypeFactory(Jsni.type(typeof(IEnumerable <>)), Jsni.array(elementType)) }).ToArray(), new JsTypeFunction[0], new FieldInfo[0], new MethodInfo[0], new ConstructorInfo[0], new PropertyInfo[0], new EventInfo[0], false, false, false, false, elementType, null); return(type.As <JsObject>()); }); }, SpecialNames.TypeInitializerTypeFunction, SpecialNames.TypeInitializerPrototype); Jsni.call(arrayType.TypeInitializer, Jsni.@this(), arrayType, arrayType.prototype); var result = arrayType; elementType.ArrayType = result; } return(elementType.ArrayType); }
internal static JsTypeFunction MakeGenericTypeFactory(JsTypeFunction unconstructedType, JsArray typeArgs) { var cache = Jsni.member(unconstructedType, SpecialNames.TypeCache); if (cache == null) { cache = new JsObject(); unconstructedType.memberset(SpecialNames.TypeCache, cache); } var keyArray = Jsni.call <JsArray>(x => x.slice(0), typeArgs, 0.As < JsNumber > ()).As <JsArray>(); var keyParts = new JsArray(); for (var i = 0; i < keyArray.length; i++) { keyParts[i] = keyArray[i].member(SpecialNames.TypeName); } var keyString = keyParts.join(", "); var result = cache[keyString]; if (result == null) { var lastIndexOfDollar = unconstructedType.TypeName.LastIndexOf('`'); var newTypeName = unconstructedType.TypeName.Substring(0, lastIndexOfDollar) + "<" + keyString + ">"; var prototype = unconstructedType.BaseType; if (prototype.member("$")) { prototype = prototype.member("$").apply(null, typeArgs).As <JsTypeFunction>(); } var generic = Define(newTypeName, prototype); generic.memberset(SpecialNames.UnconstructedType, unconstructedType); // unconstructedType.$TypeInitializer.apply(this, [generic, generic.prototype].concat(Array.prototype.slice.call(arguments, 0))); Jsni.apply( Jsni.member(unconstructedType, SpecialNames.TypeInitializer), unconstructedType, Jsni.invoke( Jsni.member(Jsni.array(generic, generic.prototype), "concat"), keyArray ).As <JsArray>()); generic.TypeInitializer = Jsni.procedure((t, p) => { p.___type = generic; t.As <JsTypeFunction>().BaseType = unconstructedType; t.As <JsTypeFunction>().GetTypeFromType = Jsni.function(() => Type._GetTypeFromTypeFunc(Jsni.@this().As <JsTypeFunction>()).As <JsObject>()); t.As <JsTypeFunction>().CreateTypeField = Jsni.function(() => { var unconstructedTypeType = Type._GetTypeFromTypeFunc(unconstructedType); var type = new Type(newTypeName, new Attribute[0]); generic.Type = type; type.Init( newTypeName, unconstructedTypeType.typeAttributes, generic, unconstructedType.BaseType, unconstructedTypeType.interfaces, InitializeArray(typeArgs, Jsni.type <JsTypeFunction>()).As <JsTypeFunction[]>(), unconstructedTypeType.fields, unconstructedTypeType.methods, unconstructedTypeType.constructors, unconstructedTypeType.properties, unconstructedTypeType.events, false, false, true, false, null, unconstructedType); return(type.As <JsObject>()); }); }, SpecialNames.TypeInitializerTypeFunction, SpecialNames.TypeInitializerPrototype); Jsni.call(generic.TypeInitializer, Jsni.@this(), generic, generic.prototype); result = generic; cache[keyString] = result; } return(result.As <JsTypeFunction>()); }
public FieldInfo(string name, JsTypeFunction fieldType, FieldAttributes fieldAttributes, object constantValue, Attribute[] attributes) : base(name, attributes) { this.fieldType = fieldType; this.fieldAttributes = fieldAttributes; this.constantValue = constantValue; }
public static JsFunction CreateDelegate(JsObject thisExpression, JsFunction lambda, JsTypeFunction delegateType = null, string delegateKey = null) { delegateType = delegateType ?? Jsni.reference("System.Delegate").As <JsTypeFunction>(); JsFunction delegateFunc = null; delegateFunc = Jsni.function(() => { return(lambda.apply(delegateFunc.As <Delegate>().Target.As <JsObject>(), Jsni.arguments().As <JsArray>())); }); delegateFunc.prototype = Jsni.@new(delegateType); delegateFunc.memberset("get_Target", Jsni.function(() => thisExpression)); delegateFunc.memberset("GetType", Jsni.function(() => delegateType.GetTypeFromType.invoke())); Jsni.memberset(delegateFunc, SpecialNames.TypeField, delegateType); Jsni.memberset(delegateFunc, "Invoke", delegateFunc); Jsni.memberset(delegateFunc, "DynamicInvoke", Jsni.function(args => delegateFunc.apply(delegateFunc, args.As <JsArray>()))); Jsni.memberset(delegateFunc, "GetHashCode", Jsni.function(() => lambda.toString().GetHashCode().As <JsObject>())); Jsni.memberset(delegateFunc, "lambda", lambda); Jsni.memberset(delegateFunc, "Equals", Jsni.function(x => x != null && lambda == x.member("lambda"))); return(delegateFunc); }
internal static JsTypeFunction MakeGenericTypeFactory(JsTypeFunction unconstructedType, JsArray typeArgs) { var cache = Jsni.member(unconstructedType, SpecialNames.TypeCache); JsObject result = null; if (typeArgs.length > 0) { if (cache == null) { cache = new JsObject(); unconstructedType.memberset(SpecialNames.TypeCache, cache); } JsObject currentCache = cache; for (var i = 0; i < typeArgs.length - 1; i++) { var nextCache = currentCache[typeArgs[i].member(SpecialNames.TypeName)]; if (nextCache == null) { nextCache = new JsObject(); currentCache[typeArgs[i].member(SpecialNames.TypeName)] = nextCache; } currentCache = nextCache; } cache = currentCache; result = cache[typeArgs[typeArgs.length - 1].member(SpecialNames.TypeName)]; } else { result = cache; } // JsObject keyString; // First two if statements are optimizations for performance reasons to avoid heap allocation when possible. /* * if (typeArgs.length == 0) * keyString = ""; * else if (typeArgs.length == 1) * keyString = typeArgs[0].member(SpecialNames.TypeName); * else * { * var keyArray = Jsni.call<JsArray>(x => x.slice(0), typeArgs, 0.As<JsNumber>()).As<JsArray>(); * var keyParts = new JsArray(); * for (var i = 0; i < keyArray.length; i++) * { * keyParts[i] = keyArray[i].member(SpecialNames.TypeName); * } * keyString = keyParts.join(", "); * } * * var result = cache[keyString]; */ if (result == null) { var keyArray = Jsni.call <JsArray>(x => x.slice(0), typeArgs, 0.As < JsNumber > ()).As <JsArray>(); var keyParts = new JsArray(); for (var i = 0; i < keyArray.length; i++) { keyParts[i] = keyArray[i].member(SpecialNames.TypeName); } var keyString = keyParts.join(", "); var lastIndexOfDollar = unconstructedType.TypeName.LastIndexOf('`'); if (lastIndexOfDollar == -1) { lastIndexOfDollar = unconstructedType.TypeName.Length; } var newTypeName = unconstructedType.TypeName.Substring(0, lastIndexOfDollar) + "<" + keyString + ">"; var prototype = unconstructedType.BaseType; if (prototype.member("$")) { var baseArgs = unconstructedType.BaseTypeArgs.slice(0); for (var i = 0; i < baseArgs.length; i++) { var baseArg = (JsTypeFunction)baseArgs[i]; if (baseArg.IsTypeParameter) { for (var j = 0; j < unconstructedType.TypeArgs.length; j++) { var typeArg = unconstructedType.TypeArgs[j]; if (typeArg == baseArg) { baseArgs[i] = typeArgs[j]; } } } } prototype = prototype.member("$").apply(null, baseArgs).As <JsTypeFunction>(); } var typeInitializer = Jsni.procedure((_t, p) => { var t = _t.As <JsTypeFunction>(); p.___type = t; t.As <JsTypeFunction>().BaseType = unconstructedType; t.As <JsTypeFunction>().GetTypeFromType = Jsni.function(() => Type._GetTypeFromTypeFunc(Jsni.@this().As <JsTypeFunction>()).As <JsObject>()); t.As <JsTypeFunction>().TypeName = newTypeName; t.As <JsTypeFunction>().CreateTypeField = Jsni.function(() => { var unconstructedTypeType = Type._GetTypeFromTypeFunc(unconstructedType); var type = new Type(newTypeName, new Attribute[0]); t.Type = type; type.thisType = t; var typeParameters = unconstructedTypeType.typeArguments; var typeArguments = InitializeArray(typeArgs, Jsni.type <JsTypeFunction>()).As <JsTypeFunction[]>(); Func <Type, JsTypeFunction> reifyGenerics = null; reifyGenerics = theType => { if (theType == null) { return(null); } if (theType.IsArray) { var elementType = theType.GetElementType(); var arrayType = MakeArrayType(reifyGenerics(elementType)); return(arrayType); } if (theType.IsGenericParameter) { for (int i = 0; i < typeArguments.Length; i++) { var typeParameter = typeParameters[i]; var typeArgument = typeArguments[i]; if (typeParameter.TypeName == theType.FullName) { return(typeArgument); } } } else if (theType.IsGenericTypeDefinition) { return(MakeGenericTypeFactory(theType.thisType, theType.GenericTypeArguments.Select(x => reifyGenerics(x)).ToArray().As <JsArray>())); } else if (theType.IsGenericType) { JsTypeFunction[] newTypeArguments = null; for (var i = 0; i < theType.typeArguments.Length; i++) { var theTypeArgument = theType.typeArguments[i]; for (var j = 0; j < typeParameters.Length; j++) { var typeParameter = typeParameters[j]; var typeArgument = typeArguments[j]; if (theTypeArgument == typeParameter) { if (newTypeArguments == null) { newTypeArguments = new JsTypeFunction[theType.typeArguments.Length]; for (var k = 0; k < theType.typeArguments.Length; k++) { newTypeArguments[k] = theType.typeArguments[k]; } } newTypeArguments[i] = typeArgument; } } } if (newTypeArguments != null) { return(MakeGenericTypeFactory(theType.unconstructedType, newTypeArguments.As <JsArray>())); } else { return(theType.thisType); } } return(theType.thisType); }; var newInterfaces = unconstructedTypeType.interfaces.ToArray(); for (var i = 0; i < newInterfaces.Length; i++) { var intf = newInterfaces[i]; intf = reifyGenerics(Type._GetTypeFromTypeFunc(intf)); newInterfaces[i] = intf; } var newConstructors = unconstructedTypeType.constructors.ToArray(); for (var i = 0; i < newConstructors.Length; i++) { var constructor = newConstructors[i]; var parameters = constructor.GetParameters(); for (var j = 0; j < parameters.Length; j++) { var parameter = parameters[j]; var parameterType = reifyGenerics(parameter.ParameterType); parameter = new ParameterInfo(parameter.Name, parameterType, j, parameter.Attributes, parameter.DefaultValue, parameter.attributes); parameters[j] = parameter; } newConstructors[i] = new ConstructorInfo(constructor.Name, t.prototype[constructor.Name].As <JsFunction>(), parameters, constructor.Attributes, constructor.attributes); } var newProperties = unconstructedTypeType.properties.ToArray(); for (var i = 0; i < newProperties.Length; i++) { var property = newProperties[i]; var propertyTypeType = property.PropertyType; var propertyType = reifyGenerics(propertyTypeType); newProperties[i] = new PropertyInfo(property.Name, propertyType, property.GetGetMethod(), property.GetSetMethod(), property.GetIndexParameters(), property.attributes); } var newMethods = unconstructedTypeType.methods.ToArray(); for (var i = 0; i < newMethods.Length; i++) { var method = newMethods[i]; var returnTypeType = method.ReturnType; var returnType = reifyGenerics(returnTypeType); var parameters = method.GetParameters(); for (var j = 0; j < parameters.Length; j++) { var parameter = parameters[j]; var parameterType = reifyGenerics(parameter.ParameterType); parameter = new ParameterInfo(parameter.Name, parameterType, j, parameter.Attributes, parameter.DefaultValue, parameter.attributes); parameters[j] = parameter; } method = new MethodInfo(method.Name, method.jsMethod, parameters, returnType, method.Attributes, method.attributes); newMethods[i] = method; } type.Init( newTypeName, (int)((unconstructedTypeType.typeFlags | TypeFlags.GenericType) & ~TypeFlags.GenericTypeDefenition), t, prototype, newInterfaces, typeArguments, unconstructedTypeType.fields, newMethods, newConstructors, newProperties, unconstructedTypeType.events, null, unconstructedType); return(type.As <JsObject>()); }); }, SpecialNames.TypeInitializerTypeFunction, SpecialNames.TypeInitializerPrototype); var generic = Define(unconstructedType.GetAssembly, unconstructedType.EnclosingType, newTypeName, true, Jsni.array(), prototype, typeInitializer); generic.memberset(SpecialNames.UnconstructedType, unconstructedType); // unconstructedType.$TypeInitializer.apply(this, [generic, generic.prototype].concat(Array.prototype.slice.call(arguments, 0))); unconstructedType.member(SpecialNames.TypeInitializer).apply( unconstructedType, Jsni.array(generic, generic.prototype).member("concat").invoke(keyArray).As <JsArray>() ); Jsni.call(generic.TypeInitializer, Jsni.@this(), generic, generic.prototype); result = generic; if (typeArgs.length == 0) { unconstructedType.memberset(SpecialNames.TypeCache, result); } else { cache[typeArgs[typeArgs.length - 1].member(SpecialNames.TypeName)] = result; } } return(result.As <JsTypeFunction>()); }
public static JsTypeFunction Define(JsFunction assembly, JsTypeFunction enclosingType, string name, bool isGenericType, JsArray typeParameters, JsObject prototype, JsFunction typeInitializer) { JsTypeFunction typeFunction = null; var isTypeInitialized = false; // Create constructor function, which is a superconstructor that takes in the actual // constructor as the first argument, and the rest of the arguments are passed directly // to that constructor. These subconstructors are not Javascript constructors -- they // are not called via new, they exist for initialization only. typeFunction = Jsni.function((constructor, args) => { if (constructor != null || !(Jsni.instanceof(Jsni.@this(), typeFunction))) { if (!isGenericType || typeFunction.UnconstructedType != null) { typeFunction.member(SpecialNames.StaticInitializer).invoke(); } } if (constructor != null) { constructor.apply(Jsni.@this(), args.As <JsArray>()); } if (!Jsni.instanceof(Jsni.@this(), typeFunction)) { return(typeFunction); } else { return(Jsni.@this()); } }).As <JsTypeFunction>(); typeFunction.GetAssembly = assembly; assembly.member(SpecialNames.AssemblyTypesArray).member("push").invoke(typeFunction); typeFunction.memberset("toString", Jsni.function(() => name.As <JsObject>())); typeFunction.EnclosingType = enclosingType; typeFunction.TypeName = name; typeFunction.prototype = Jsni.@new(prototype); typeFunction.IsPrototypeInitialized = false; typeFunction.TypeInitializer = Jsni.procedure((_t, p) => { var t = _t.As <JsTypeFunction>(); if (isGenericType) { var unconstructedType = t.UnconstructedType ?? t; t.GenericTypeFunction = Jsni.function(() => { return(Jsni.reference(SpecialNames.MakeGenericTypeConstructor).As <JsFunction>().call(unconstructedType, unconstructedType, Jsni.arguments()).As <JsFunction>().invoke()); }); } t.GetTypeFromType = Jsni.function(() => { return(Type._GetTypeFromTypeFunc(Jsni.@this().As <JsTypeFunction>()).As <JsObject>()); }); p.memberset(SpecialNames.TypeName, t.member(SpecialNames.TypeName)); p.___type = t; t.BaseType = prototype.As <JsTypeFunction>(); typeInitializer.apply(Jsni.@this(), Jsni.arguments().As <JsArray>()); }); typeFunction.CallTypeInitializer = Jsni.procedure(() => { typeFunction.TypeInitializer.apply(enclosingType, Jsni.array(typeFunction, typeFunction.prototype).concat(typeParameters)); }); return(typeFunction); }
public static JsFunction DefineTypeFunction(JsTypeFunction type, JsFunction template) { return(template); }
/// <summary> /// Initializes a new instance of the <see cref="T:System.Reflection.MethodInfo"/> class. /// </summary> public MethodInfo(string name, JsFunction jsMethod, ParameterInfo[] parameters, JsTypeFunction returnType, MethodAttributes methodAttributes, Attribute[] attributes) : base(name, parameters, methodAttributes, attributes) { this.jsMethod = jsMethod; this.returnType = returnType; }
public static object InternalToObject(JsTypeFunction enumType, object value) { var enumsByValue = enumsByTypeAndValue[enumType.TypeName]; Enum result = enumsByValue.GetOrDefault(value); if (result != null) { return result; } else { // Otherwise it's an enum value that isn't represented by a declared member. In // this case, we need to box the value and then force it to be recognized as the // enum type. result = Jsni.@new(Jsni.reference("Number"), value.As<JsObject>()).As<Enum>(); foreach (var property in enumType.member("prototype")) { result.As<JsObject>()[property] = enumType.member("prototype")[property]; } foreach (var property in Jsni.type<Enum>().member("prototype")) { result.As<JsObject>()[property] = Jsni.type<Enum>().member("prototype")[property]; } result.___type = enumType; result.As<JsObject>().memberset("value", value.As<JsObject>()); enumsByValue[value] = result; return result; } }
public static Type _GetTypeFromTypeFunc(JsTypeFunction typeFunction) { if (typeFunction.member("$CreateType") == null) return null; if (typeFunction.Type == null) typeFunction.CreateType(); return typeFunction.Type; }