示例#1
0
        private JsExpression GetCastTarget(IType type, IRuntimeContext context)
        {
            if (type.Kind == TypeKind.Enum)
            {
                return(CreateTypeReferenceExpression(type.GetDefinition().EnumUnderlyingType.GetDefinition()));
            }

            var def = type.GetDefinition();

            if (def != null)
            {
                if (MetadataUtils.IsSerializable(def) && string.IsNullOrEmpty(MetadataUtils.GetSerializableTypeCheckCode(def)))
                {
                    return(null);
                }
                if (!MetadataUtils.DoesTypeObeyTypeSystem(def))
                {
                    return(null);
                }
            }

            return(GetScriptType(type, TypeContext.GetScriptType, context));
        }
        public JsExpression TryDowncast(JsExpression expression, IType sourceType, IType targetType, IRuntimeContext context)
        {
            JsExpression jsTarget = CompileImportedTypeCheckCode(targetType, ref expression, context, false);

            if (jsTarget == null)
            {
                var def = targetType.GetDefinition();
                if (def != null && (!MetadataUtils.DoesTypeObeyTypeSystem(def) || (MetadataUtils.IsSerializable(def) && string.IsNullOrEmpty(MetadataUtils.GetSerializableTypeCheckCode(def)))))
                {
                    _errorReporter.Message(Messages._7702, targetType.FullName);
                    return(JsExpression.Null);
                }

                jsTarget = GetCastTarget(sourceType, targetType, context);
            }

            if (jsTarget == null || IsSystemObjectReference(jsTarget))
            {
                return(expression);
            }

            return(JsExpression.Invocation(JsExpression.Member(CreateTypeReferenceExpression(_systemScript), "safeCast"), expression, jsTarget));
        }
        public JsExpression TypeIs(JsExpression expression, IType sourceType, IType targetType, IRuntimeContext context)
        {
            var importedCheck = CompileImportedTypeCheckCode(targetType, ref expression, context, true);

            if (importedCheck != null)
            {
                return(importedCheck);
            }

            var def = targetType.GetDefinition();

            if (def != null && (!MetadataUtils.DoesTypeObeyTypeSystem(def) || (MetadataUtils.IsSerializable(def) && string.IsNullOrEmpty(MetadataUtils.GetSerializableTypeCheckCode(def)))))
            {
                _errorReporter.Message(Messages._7701, targetType.FullName);
                return(JsExpression.Null);
            }

            var jsTarget = GetCastTarget(sourceType, targetType, context);

            if (jsTarget == null || IsSystemObjectReference(jsTarget))
            {
                return(ReferenceNotEquals(expression, JsExpression.Null, context));
            }
            return(JsExpression.Invocation(JsExpression.Member(CreateTypeReferenceExpression(_systemScript), "isInstanceOfType"), expression, jsTarget));
        }
示例#4
0
        private void AddClassMembers(JsClass c, JsExpression typeRef, List <JsStatement> stmts)
        {
            if (c.InstanceMethods.Count > 0)
            {
                stmts.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, Prototype), JsExpression.ObjectLiteral(c.InstanceMethods.Select(m => new JsObjectLiteralProperty(m.Name, m.Definition != null ? RewriteMethod(m) : JsExpression.Null))))));
            }

            if (c.NamedConstructors.Count > 0)
            {
                stmts.AddRange(c.NamedConstructors.Select(m => new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, m.Name), m.Definition))));
                stmts.Add(new JsExpressionStatement(c.NamedConstructors.Reverse().Aggregate((JsExpression)JsExpression.Member(typeRef, Prototype), (right, ctor) => JsExpression.Assign(JsExpression.Member(JsExpression.Member(typeRef, ctor.Name), Prototype), right))));                     // This generates a statement like {C}.ctor1.prototype = {C}.ctor2.prototype = {C}.prototoype
            }

            var defaultConstructor = Saltarelle.Compiler.Utils.SelfParameterize(c.CSharpTypeDefinition).GetConstructors().SingleOrDefault(x => x.Parameters.Count == 0 && x.IsPublic);

            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(new JsExpressionStatement(
                                  JsExpression.Assign(
                                      JsExpression.Member(typeRef, "createInstance"),
                                      JsExpression.FunctionDefinition(new string[0], new JsBlockStatement(createInstance.AdditionalStatements.Concat(new[] { new JsReturnStatement(createInstance.Expression) }))))));
                }
            }

            stmts.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, m.Name), RewriteMethod(m)))));

            if (MetadataUtils.IsSerializable(c.CSharpTypeDefinition))
            {
                string typeCheckCode = MetadataUtils.GetSerializableTypeCheckCode(c.CSharpTypeDefinition);
                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.CompileInlineCodeMethodInvocation(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(new JsExpressionStatement(
                                      JsExpression.Assign(
                                          JsExpression.Member(typeRef, "isInstanceOfType"),
                                          JsExpression.FunctionDefinition(new[] { "obj" }, new JsReturnStatement(result)))));

                        foreach (var e in errors)
                        {
                            _errorReporter.Message(Messages._7157, c.CSharpTypeDefinition.FullName, e);
                        }
                    }
                    _errorReporter.Region = oldReg;
                }
            }

            if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter))
            {
                var args = new List <JsExpression> {
                    typeRef, new JsTypeReferenceExpression(c.CSharpTypeDefinition), JsExpression.ArrayLiteral(c.CSharpTypeDefinition.TypeParameters.Select(tp => JsExpression.Identifier(_namer.GetTypeParameterName(tp))))
                };
                if (c.CSharpTypeDefinition.Kind == TypeKind.Class)
                {
                    args.Add(JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(GetBaseClass(c.CSharpTypeDefinition) ?? JsExpression.Null)));
                }
                args.Add(JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(JsExpression.ArrayLiteral(GetImplementedInterfaces(c.CSharpTypeDefinition)))));
                var metadata = GetMetadataDescriptor(c.CSharpTypeDefinition, true);
                if (metadata != null)
                {
                    args.Add(metadata);
                }
                stmts.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Class ? RegisterGenericClassInstance : RegisterGenericInterfaceInstance), args)));
            }
        }
示例#5
0
        private JsExpression GetCastTarget(IType type, IRuntimeContext context)
        {
            var def = type.GetDefinition();

            if (type.Kind == TypeKind.Enum)
            {
                var underlying = MetadataUtils.IsNamedValues(def, _attributeStore) ? _compilation.FindType(KnownTypeCode.String) : def.EnumUnderlyingType;
                return(CreateTypeReferenceExpression(underlying.GetDefinition()));
            }

            if (def != null)
            {
                if (MetadataUtils.IsSerializable(def, _attributeStore) && string.IsNullOrEmpty(MetadataUtils.GetSerializableTypeCheckCode(def, _attributeStore)))
                {
                    return(null);
                }
                if (!MetadataUtils.DoesTypeObeyTypeSystem(def, _attributeStore))
                {
                    return(null);
                }
            }

            return(GetScriptType(type, TypeContext.GetScriptType, context));
        }
        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));
                }
            }
        }