private JsExpression CompileImportedTypeCheckCode(IType type, ref JsExpression @this, IRuntimeContext context, bool isTypeIs) { var def = type.GetDefinition(); if (def == null) { return(null); } var ia = AttributeReader.ReadAttribute <ImportedAttribute>(def); if (ia == null || string.IsNullOrEmpty(ia.TypeCheckCode)) { return(null); } // Can ignore errors here because they are caught by the metadata importer var method = MetadataUtils.CreateTypeCheckMethod(type, _compilation); var tokens = InlineCodeMethodCompiler.Tokenize(method, ia.TypeCheckCode, _ => {}); int thisCount = tokens.Count(t => t.Type == InlineCodeToken.TokenType.This); if (!isTypeIs || thisCount > 0) { @this = context.EnsureCanBeEvaluatedMultipleTimes(@this, new JsExpression[0]); } return(JsExpression.LogicalAnd( ReferenceNotEquals(@this, JsExpression.Null, context), InlineCodeMethodCompiler.CompileExpressionInlineCodeMethodInvocation(method, tokens, @this, EmptyList <JsExpression> .Instance, n => { var t = ReflectionHelper.ParseReflectionName(n).Resolve(_compilation); return t.Kind == TypeKind.Unknown ? JsExpression.Null : InstantiateType(t, context); }, t => InstantiateTypeForUseAsTypeArgumentInInlineCode(t, context), _ => {}))); }
public JsExpression InitializeField(JsExpression jsThis, string scriptName, IMember member, JsExpression initialValue, IRuntimeContext context) { var cia = _attributeStore.AttributesFor(member).GetAttribute <CustomInitializationAttribute>(); if (cia != null) { if (string.IsNullOrEmpty(cia.Code)) { return(null); } var method = MetadataUtils.CreateDummyMethodForFieldInitialization(member, _compilation); // Can ignore errors because they are caught by the metadata importer var tokens = InlineCodeMethodCompiler.Tokenize(method, cia.Code, _ => {}); initialValue = InlineCodeMethodCompiler.CompileExpressionInlineCodeMethodInvocation(method, tokens, jsThis, new[] { initialValue }, n => { var t = ReflectionHelper.ParseReflectionName(n).Resolve(_compilation); return(t.Kind == TypeKind.Unknown ? JsExpression.Null : InstantiateType(t, context)); }, t => InstantiateTypeForUseAsTypeArgumentInInlineCode(t, context), _ => {}); } return(JsExpression.Assign(JsExpression.Member(jsThis, scriptName), initialValue)); }
private void AddClassMembers(JsClass c, string typevarName, List <JsStatement> stmts) { if (c.NamedConstructors.Count > 0) { stmts.AddRange(c.NamedConstructors.Select(m => (JsStatement)JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), m.Name), m.Definition))); } var defaultConstructor = Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition).GetConstructors().SingleOrDefault(x => x.Parameters.Count == 0 && x.IsPublic); bool hasCreateInstance = false; if (defaultConstructor != null) { var sem = _metadataImporter.GetConstructorSemantics(defaultConstructor); if (sem.Type != ConstructorScriptSemantics.ImplType.UnnamedConstructor && sem.Type != ConstructorScriptSemantics.ImplType.NotUsableFromScript) { var createInstance = MetadataUtils.CompileConstructorInvocation(defaultConstructor, null, c.CSharpTypeDefinition, null, EmptyList <ResolveResult> .Instance, _compilation, _metadataImporter, _namer, _runtimeLibrary, _errorReporter, null, null); stmts.Add(JsExpression.Assign( JsExpression.Member(JsExpression.Identifier(typevarName), "createInstance"), JsExpression.FunctionDefinition(new string[0], JsStatement.Block(createInstance.AdditionalStatements.Concat(new[] { JsStatement.Return(createInstance.Expression) }))))); hasCreateInstance = true; } } if (c.CSharpTypeDefinition.Kind == TypeKind.Struct) { stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "getDefaultValue"), hasCreateInstance ? JsExpression.Member(JsExpression.Identifier(typevarName), "createInstance") : JsExpression.FunctionDefinition(EmptyList <string> .Instance, JsStatement.Return(JsExpression.New(JsExpression.Identifier(typevarName)))))); if (_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Type == TypeScriptSemantics.ImplType.MutableValueType) { stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "$clone"), GenerateStructCloneMethod(c.CSharpTypeDefinition, typevarName, hasCreateInstance))); } } stmts.AddRange(c.StaticMethods.Select(m => (JsStatement)JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), m.Name), RewriteMethod(m)))); if (MetadataUtils.IsSerializable(c.CSharpTypeDefinition, _attributeStore)) { string typeCheckCode = MetadataUtils.GetSerializableTypeCheckCode(c.CSharpTypeDefinition, _attributeStore); if (!string.IsNullOrEmpty(typeCheckCode)) { var oldReg = _errorReporter.Region; _errorReporter.Region = c.CSharpTypeDefinition.Attributes.Single(a => a.AttributeType.FullName == typeof(SerializableAttribute).FullName).Region; var method = MetadataUtils.CreateTypeCheckMethod(Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition), _compilation); var errors = new List <string>(); var tokens = InlineCodeMethodCompiler.Tokenize(method, typeCheckCode, errors.Add); if (errors.Count == 0) { var context = new DefaultRuntimeContext(c.CSharpTypeDefinition, _metadataImporter, _errorReporter, _namer); var result = InlineCodeMethodCompiler.CompileExpressionInlineCodeMethodInvocation(method, tokens, JsExpression.Identifier("obj"), new JsExpression[0], n => { var type = ReflectionHelper.ParseReflectionName(n).Resolve(_compilation); if (type.Kind == TypeKind.Unknown) { errors.Add("Unknown type '" + n + "' specified in inline implementation"); return(JsExpression.Null); } return(_runtimeLibrary.InstantiateType(type, context)); }, t => _runtimeLibrary.InstantiateTypeForUseAsTypeArgumentInInlineCode(t, context), errors.Add); stmts.Add(JsExpression.Assign( JsExpression.Member(JsExpression.Identifier(typevarName), "isInstanceOfType"), JsExpression.FunctionDefinition(new[] { "obj" }, JsStatement.Return(result)))); foreach (var e in errors) { _errorReporter.Message(Messages._7157, c.CSharpTypeDefinition.FullName, e); } } _errorReporter.Region = oldReg; } else { stmts.Add(JsExpression.Assign( JsExpression.Member(JsExpression.Identifier(typevarName), "isInstanceOfType"), JsExpression.FunctionDefinition(new string[0], JsStatement.Return(JsExpression.True)))); } } if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) { var args = new List <JsExpression> { JsExpression.Identifier(typevarName), new JsTypeReferenceExpression(c.CSharpTypeDefinition), JsExpression.ArrayLiteral(c.CSharpTypeDefinition.TypeParameters.Select(tp => JsExpression.Identifier(_namer.GetTypeParameterName(tp)))), CreateInstanceMembers(c, typevarName), }; if (c.CSharpTypeDefinition.Kind != TypeKind.Interface) { args.Add(JsExpression.FunctionDefinition(new string[0], JsStatement.Return(GetBaseClass(c.CSharpTypeDefinition) ?? JsExpression.Null))); } args.Add(JsExpression.FunctionDefinition(new string[0], JsStatement.Return(JsExpression.ArrayLiteral(GetImplementedInterfaces(c.CSharpTypeDefinition))))); stmts.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? RegisterGenericInterfaceInstance : RegisterGenericClassInstance), args)); if (c.CSharpTypeDefinition.Kind == TypeKind.Class && c.NamedConstructors.Count > 0) { stmts.Add(AssignNamedConstructorPrototypes(c, JsExpression.Identifier(typevarName))); } if (c.CSharpTypeDefinition.Kind == TypeKind.Struct) { stmts.Add(JsExpression.Assign(JsExpression.Member(JsExpression.Identifier(typevarName), "__class"), JsExpression.False)); } var metadata = GetMetadataDescriptor(c.CSharpTypeDefinition, true); if (metadata != null) { stmts.Add(JsExpression.Invocation(JsExpression.Member(_systemScript, SetMetadata), JsExpression.Identifier(typevarName), metadata)); } } }