From d476c0dc6a29b1c3457d22cca995f5d7c3c8c86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Tue, 2 Nov 2021 23:18:48 +0100 Subject: [PATCH 01/10] javascript back converter --- src/Esprima/Utils/ToJavascriptConverter.cs | 1220 ++++++++++++++++++++ test/Esprima.Tests/JavascriptTest.cs | 425 +++++++ 2 files changed, 1645 insertions(+) create mode 100644 src/Esprima/Utils/ToJavascriptConverter.cs create mode 100644 test/Esprima.Tests/JavascriptTest.cs diff --git a/src/Esprima/Utils/ToJavascriptConverter.cs b/src/Esprima/Utils/ToJavascriptConverter.cs new file mode 100644 index 00000000..5a90e9b3 --- /dev/null +++ b/src/Esprima/Utils/ToJavascriptConverter.cs @@ -0,0 +1,1220 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; +using Esprima.Ast; + +namespace Esprima.Utils +{ + public class ToJavascriptConverter + { + public static string ToJavascript(Node node) + { + var visitor = new ToJavascriptConverter(); + visitor.Visit(node); + return visitor.ToString(); + } + + protected StringBuilder _sb = new StringBuilder(); + protected int _indentionLevel = 0; + protected bool beautify = false; + protected int _indentionSize = 4; + protected char _indentionChar = ' '; + + private static readonly ConditionalWeakTable EnumMap = new ConditionalWeakTable(); + + private string GetEnumValue(string name, T value) where T : Enum + { + var map = (Dictionary) + EnumMap.GetValue(value.GetType(), + t => t.GetRuntimeFields() + .Where(f => f.IsStatic) + .ToDictionary(f => (T) f.GetValue(null), + f => f.GetCustomAttribute() is EnumMemberAttribute a + ? a.Value : f.Name.ToLowerInvariant())); + return map[value]; + } + + private readonly List _parentStack = new List(); + protected IReadOnlyList ParentStack => _parentStack; + + /// + /// Returns parent node at specified position. + /// + /// Zero index value returns current node; one corresponds to direct + /// parent of current node. + protected Node? TryGetParentAt(int offset) + { + if (_parentStack.Count < offset + 1) + { + return null; + } + + return _parentStack[_parentStack.Count - 1 - offset]; + } + + public virtual void Visit(Node node) + { + _parentStack.Add(node); + + switch (node.Type) + { + case Nodes.AssignmentExpression: + VisitAssignmentExpression(node.As()); + break; + case Nodes.ArrayExpression: + VisitArrayExpression(node.As()); + break; + case Nodes.BlockStatement: + VisitBlockStatement(node.As()); + break; + case Nodes.BinaryExpression: + VisitBinaryExpression(node.As()); + break; + case Nodes.BreakStatement: + VisitBreakStatement(node.As()); + break; + case Nodes.CallExpression: + VisitCallExpression(node.As()); + break; + case Nodes.CatchClause: + VisitCatchClause(node.As()); + break; + case Nodes.ConditionalExpression: + VisitConditionalExpression(node.As()); + break; + case Nodes.ContinueStatement: + VisitContinueStatement(node.As()); + break; + case Nodes.DoWhileStatement: + VisitDoWhileStatement(node.As()); + break; + case Nodes.DebuggerStatement: + VisitDebuggerStatement(node.As()); + break; + case Nodes.EmptyStatement: + VisitEmptyStatement(node.As()); + break; + case Nodes.ExpressionStatement: + VisitExpressionStatement(node.As()); + break; + case Nodes.ForStatement: + VisitForStatement(node.As()); + break; + case Nodes.ForInStatement: + VisitForInStatement(node.As()); + break; + case Nodes.FunctionDeclaration: + VisitFunctionDeclaration(node.As()); + break; + case Nodes.FunctionExpression: + VisitFunctionExpression(node.As()); + break; + case Nodes.Identifier: + VisitIdentifier(node.As()); + break; + case Nodes.IfStatement: + VisitIfStatement(node.As()); + break; + case Nodes.Import: + VisitImport(node.As()); + break; + case Nodes.Literal: + VisitLiteral(node.As()); + break; + case Nodes.LabeledStatement: + VisitLabeledStatement(node.As()); + break; + case Nodes.LogicalExpression: + VisitBinaryExpression(node.As()); + break; + case Nodes.MemberExpression: + VisitMemberExpression(node.As()); + break; + case Nodes.NewExpression: + VisitNewExpression(node.As()); + break; + case Nodes.ObjectExpression: + VisitObjectExpression(node.As()); + break; + case Nodes.Program: + VisitProgram(node.As()); + break; + case Nodes.Property: + VisitProperty(node.As()); + break; + case Nodes.PropertyDefinition: + VisitPropertyDefinition(node.As()); + break; + case Nodes.RestElement: + VisitRestElement(node.As()); + break; + case Nodes.ReturnStatement: + VisitReturnStatement(node.As()); + break; + case Nodes.SequenceExpression: + VisitSequenceExpression(node.As()); + break; + case Nodes.SwitchStatement: + VisitSwitchStatement(node.As()); + break; + case Nodes.SwitchCase: + VisitSwitchCase(node.As()); + break; + case Nodes.TemplateElement: + VisitTemplateElement(node.As()); + break; + case Nodes.TemplateLiteral: + VisitTemplateLiteral(node.As()); + break; + case Nodes.ThisExpression: + VisitThisExpression(node.As()); + break; + case Nodes.ThrowStatement: + VisitThrowStatement(node.As()); + break; + case Nodes.TryStatement: + VisitTryStatement(node.As()); + break; + case Nodes.UnaryExpression: + VisitUnaryExpression(node.As()); + break; + case Nodes.UpdateExpression: + VisitUpdateExpression(node.As()); + break; + case Nodes.VariableDeclaration: + VisitVariableDeclaration(node.As()); + break; + case Nodes.VariableDeclarator: + VisitVariableDeclarator(node.As()); + break; + case Nodes.WhileStatement: + VisitWhileStatement(node.As()); + break; + case Nodes.WithStatement: + VisitWithStatement(node.As()); + break; + case Nodes.ArrayPattern: + VisitArrayPattern(node.As()); + break; + case Nodes.AssignmentPattern: + VisitAssignmentPattern(node.As()); + break; + case Nodes.SpreadElement: + VisitSpreadElement(node.As()); + break; + case Nodes.ObjectPattern: + VisitObjectPattern(node.As()); + break; + case Nodes.ArrowParameterPlaceHolder: + VisitArrowParameterPlaceHolder(node.As()); + break; + case Nodes.MetaProperty: + VisitMetaProperty(node.As()); + break; + case Nodes.Super: + VisitSuper(node.As()); + break; + case Nodes.TaggedTemplateExpression: + VisitTaggedTemplateExpression(node.As()); + break; + case Nodes.YieldExpression: + VisitYieldExpression(node.As()); + break; + case Nodes.ArrowFunctionExpression: + VisitArrowFunctionExpression(node.As()); + break; + case Nodes.AwaitExpression: + VisitAwaitExpression(node.As()); + break; + case Nodes.ClassBody: + VisitClassBody(node.As()); + break; + case Nodes.ClassDeclaration: + VisitClassDeclaration(node.As()); + break; + case Nodes.ForOfStatement: + VisitForOfStatement(node.As()); + break; + case Nodes.MethodDefinition: + VisitMethodDefinition(node.As()); + break; + case Nodes.ImportSpecifier: + VisitImportSpecifier(node.As()); + break; + case Nodes.ImportDefaultSpecifier: + VisitImportDefaultSpecifier(node.As()); + break; + case Nodes.ImportNamespaceSpecifier: + VisitImportNamespaceSpecifier(node.As()); + break; + case Nodes.ImportDeclaration: + VisitImportDeclaration(node.As()); + break; + case Nodes.ExportSpecifier: + VisitExportSpecifier(node.As()); + break; + case Nodes.ExportNamedDeclaration: + VisitExportNamedDeclaration(node.As()); + break; + case Nodes.ExportAllDeclaration: + VisitExportAllDeclaration(node.As()); + break; + case Nodes.ExportDefaultDeclaration: + VisitExportDefaultDeclaration(node.As()); + break; + case Nodes.ClassExpression: + VisitClassExpression(node.As()); + break; + case Nodes.ChainExpression: + VisitChainExpression(node.As()); + break; + default: + VisitUnknownNode(node); + break; + } + _parentStack.RemoveAt(_parentStack.Count - 1); + } + + protected virtual void VisitProgram(Program program) + { + VisitNodeList(program.Body, appendAtEnd: ";"); + } + + protected virtual void VisitUnknownNode(Node node) + { + throw new NotImplementedException($"AST visitor doesn't support nodes of type {node.Type}, you can override VisitUnknownNode to handle this case."); + } + + protected virtual void VisitChainExpression(ChainExpression chainExpression) + { + Visit(chainExpression.Expression); + } + + protected virtual void VisitCatchClause(CatchClause catchClause) + { + _sb.Append("("); + if (catchClause.Param is not null) + Visit(catchClause.Param); + _sb.Append(")"); + Visit(catchClause.Body); + } + + protected virtual void VisitFunctionDeclaration(FunctionDeclaration functionDeclaration) + { + if (functionDeclaration.Async) + _sb.Append("async "); + _sb.Append("function"); + if (functionDeclaration.Generator) + _sb.Append("*"); + if (functionDeclaration.Id != null) + { + _sb.Append(" "); + Visit(functionDeclaration.Id); + } + _sb.Append("("); + VisitNodeList(functionDeclaration.Params, appendSeperatorString: ","); + _sb.Append(")"); + Visit(functionDeclaration.Body); + } + + protected virtual void VisitWithStatement(WithStatement withStatement) + { + _sb.Append("with("); + Visit(withStatement.Object); + _sb.Append(")"); + Visit(withStatement.Body); + } + + protected virtual void VisitWhileStatement(WhileStatement whileStatement) + { + _sb.Append("while("); + Visit(whileStatement.Test); + _sb.Append(")"); + Visit(whileStatement.Body); + } + + protected virtual void VisitVariableDeclaration(VariableDeclaration variableDeclaration) + { + _sb.Append(variableDeclaration.Kind.ToString().ToLower() + " "); + VisitNodeList(variableDeclaration.Declarations, appendSeperatorString: ","); + } + + protected virtual void VisitTryStatement(TryStatement tryStatement) + { + _sb.Append("try "); + Visit(tryStatement.Block); + if (tryStatement.Handler != null) + { + _sb.Append(" catch"); + Visit(tryStatement.Handler); + } + if (tryStatement.Finalizer != null) + { + _sb.Append(" finally"); + Visit(tryStatement.Finalizer); + } + } + + protected virtual void VisitThrowStatement(ThrowStatement throwStatement) + { + _sb.Append("throw "); + Visit(throwStatement.Argument); + _sb.Append(";"); + } + + protected virtual void VisitSwitchStatement(SwitchStatement switchStatement) + { + WriteStartLineToSb("switch("); + Visit(switchStatement.Discriminant); + _sb.Append("){"); + VisitNodeList(switchStatement.Cases); + _sb.Append("}"); + } + + protected virtual void VisitSwitchCase(SwitchCase switchCase) + { + if (switchCase.Test != null) + { + //todo, remove space after case, if testcase is a string starting with " or ' + WriteStartLineToSb("case "); + Visit(switchCase.Test); + } + else + WriteStartLineToSb("default"); + WriteStartLineToSb(":"); + + VisitNodeList(switchCase.Consequent, appendAtEnd: ";"); + } + + protected virtual void VisitReturnStatement(ReturnStatement returnStatement) + { + _sb.Append("return"); + if (returnStatement.Argument != null) + { + _sb.Append(" "); + Visit(returnStatement.Argument); + } + _sb.Append(";"); + } + + protected virtual void VisitLabeledStatement(LabeledStatement labeledStatement) + { + Visit(labeledStatement.Label); + _sb.Append(":"); + Visit(labeledStatement.Body); + } + + protected virtual void VisitIfStatement(IfStatement ifStatement) + { + WriteStartLineToSb("if("); + Visit(ifStatement.Test); + WriteEndLineToSb(")"); + Visit(ifStatement.Consequent); + if (NodeNeedsSemicolon(ifStatement.Consequent)) + _sb.Append(";"); + if (ifStatement.Alternate != null) + { + _sb.Append(" else "); + Visit(ifStatement.Alternate); + if (NodeNeedsSemicolon(ifStatement.Alternate)) + _sb.Append(";"); + } + } + + protected virtual void VisitEmptyStatement(EmptyStatement emptyStatement) + { + _sb.Append(";"); + } + + protected virtual void VisitDebuggerStatement(DebuggerStatement debuggerStatement) + { + _sb.Append("debugger"); + } + + protected virtual void VisitExpressionStatement(ExpressionStatement expressionStatement) + { + if (expressionStatement.Expression is CallExpression callExpression && !(callExpression.Callee is Identifier)) + { + if (ExpressionNeedsBrackets(callExpression.Callee)) + _sb.Append("("); + Visit(callExpression.Callee); + if (ExpressionNeedsBrackets(callExpression.Callee)) + _sb.Append(")"); + _sb.Append("("); + VisitNodeList(callExpression.Arguments, appendSeperatorString: ","); + _sb.Append(")"); + } + else if (expressionStatement.Expression is ClassExpression) + { + _sb.Append("("); + Visit(expressionStatement.Expression); + _sb.Append(")"); + } + else + Visit(expressionStatement.Expression); + } + + protected virtual void VisitForStatement(ForStatement forStatement) + { + WriteStartLineToSb("for("); + if (forStatement.Init != null) + { + Visit(forStatement.Init); + } + _sb.Append(";"); + if (forStatement.Test != null) + { + Visit(forStatement.Test); + } + _sb.Append(";"); + if (forStatement.Update != null) + { + Visit(forStatement.Update); + } + _sb.Append(")"); + Visit(forStatement.Body); + if (NodeNeedsSemicolon(forStatement.Body)) + _sb.Append(";"); + } + + protected virtual void VisitForInStatement(ForInStatement forInStatement) + { + _sb.Append("for("); + Visit(forInStatement.Left); + _sb.Append(" in "); + Visit(forInStatement.Right); + _sb.Append(")"); + Visit(forInStatement.Body); + if (NodeNeedsSemicolon(forInStatement.Body)) + _sb.Append(";"); + } + + protected virtual void VisitDoWhileStatement(DoWhileStatement doWhileStatement) + { + _sb.Append("do "); + Visit(doWhileStatement.Body); + if (NodeNeedsSemicolon(doWhileStatement.Body)) + _sb.Append(";"); + _sb.Append("while("); + Visit(doWhileStatement.Test); + _sb.Append(")"); + } + + protected virtual void VisitArrowFunctionExpression(ArrowFunctionExpression arrowFunctionExpression) + { + if (arrowFunctionExpression.Async) + { + _sb.Append("async "); + } + + if (arrowFunctionExpression.Id != null) + { + Visit(arrowFunctionExpression.Id); + } + + if (arrowFunctionExpression.Params.Count == 1) + { + if (arrowFunctionExpression.Params[0] is RestElement || ExpressionNeedsBrackets(arrowFunctionExpression.Params[0])) + _sb.Append("("); + Visit(arrowFunctionExpression.Params[0]); + if (arrowFunctionExpression.Params[0] is RestElement || ExpressionNeedsBrackets(arrowFunctionExpression.Params[0])) + _sb.Append(")"); + } + else + { + _sb.Append("("); + VisitNodeList(arrowFunctionExpression.Params, appendSeperatorString: ",", appendBracketsIfNeeded: true); ; + _sb.Append(")"); + } + _sb.Append("=>"); + if (arrowFunctionExpression.Body is ObjectExpression || arrowFunctionExpression.Body is SequenceExpression) + _sb.Append("("); + Visit(arrowFunctionExpression.Body); + if (arrowFunctionExpression.Body is ObjectExpression || arrowFunctionExpression.Body is SequenceExpression) + _sb.Append(")"); + } + + protected virtual void VisitUnaryExpression(UnaryExpression unaryExpression) + { + var op = GetEnumValue("unaryoperator", unaryExpression.Operator); + if (unaryExpression.Prefix) + { + _sb.Append(op); + if (char.IsLetter(op[0])) + _sb.Append(" "); + } + if (!(unaryExpression.Argument is Literal) && !(unaryExpression.Argument is UnaryExpression)) + _sb.Append("("); + Visit(unaryExpression.Argument); + if (!(unaryExpression.Argument is Literal) && !(unaryExpression.Argument is UnaryExpression)) + _sb.Append(")"); + if (!unaryExpression.Prefix) + _sb.Append(op); + } + + protected virtual void VisitUpdateExpression(UpdateExpression updateExpression) + { + if (updateExpression.Prefix) + _sb.Append(GetEnumValue("unaryoperator", updateExpression.Operator)); + Visit(updateExpression.Argument); + if (!updateExpression.Prefix) + _sb.Append(GetEnumValue("unaryoperator", updateExpression.Operator)); + } + + protected virtual void VisitThisExpression(ThisExpression thisExpression) + { + _sb.Append("this"); + } + + protected virtual void VisitSequenceExpression(SequenceExpression sequenceExpression) + { + VisitNodeList(sequenceExpression.Expressions, appendSeperatorString: ","); + } + + protected virtual void VisitObjectExpression(ObjectExpression objectExpression) + { + _sb.Append("{"); + VisitNodeList(objectExpression.Properties, appendSeperatorString: ","); + _sb.Append("}"); + } + + protected virtual void VisitNewExpression(NewExpression newExpression) + { + _sb.Append("new"); + if (ExpressionNeedsBrackets(newExpression.Callee)) + _sb.Append("("); + else + _sb.Append(" "); + Visit(newExpression.Callee); + if (ExpressionNeedsBrackets(newExpression.Callee)) + _sb.Append(")"); + if (newExpression.Arguments.Count > 0) + { + _sb.Append("("); + VisitNodeList(newExpression.Arguments, appendSeperatorString: ","); + _sb.Append(")"); + } + } + + protected virtual void VisitMemberExpression(MemberExpression memberExpression) + { + if (ExpressionNeedsBrackets(memberExpression.Object) || (memberExpression.Object is Literal l && l.TokenType != TokenType.StringLiteral)) + _sb.Append("("); + Visit(memberExpression.Object); + if (ExpressionNeedsBrackets(memberExpression.Object) || (memberExpression.Object is Literal l2 && l2.TokenType != TokenType.StringLiteral)) + _sb.Append(")"); + if (memberExpression.Computed) + _sb.Append("["); + else + { + if (TryGetParentAt(0) is ChainExpression) + _sb.Append("?"); + _sb.Append("."); + } + Visit(memberExpression.Property); + if (memberExpression.Computed) + _sb.Append("]"); + } + + protected virtual void VisitLiteral(Literal literal) + { + _sb.Append(literal.Raw); + } + + protected virtual void VisitIdentifier(Identifier identifier) + { + _sb.Append(identifier.Name); + } + + protected virtual void VisitFunctionExpression(IFunction function) + { + var isParentMethod = TryGetParentAt(1) is MethodDefinition; + if (!isParentMethod) + { + if (function.Async) + _sb.Append("async "); + if (!(TryGetParentAt(1) is MethodDefinition)) + _sb.Append("function"); + if (function.Generator) + _sb.Append("*"); + } + if (function.Id != null) + { + _sb.Append(" "); + Visit(function.Id); + } + _sb.Append("("); + VisitNodeList(function.Params, appendSeperatorString: ","); + _sb.Append(")"); + Visit(function.Body); + } + + protected virtual void VisitClassExpression(ClassExpression classExpression) + { + _sb.Append("class "); + if (classExpression.Id != null) + { + Visit(classExpression.Id); + } + + if (classExpression.SuperClass != null) + { + _sb.Append(" extends "); + Visit(classExpression.SuperClass); + } + _sb.Append("{"); + Visit(classExpression.Body); + _sb.Append("}"); + } + + protected virtual void VisitExportDefaultDeclaration(ExportDefaultDeclaration exportDefaultDeclaration) + { + _sb.Append("export default "); + if (exportDefaultDeclaration.Declaration != null) + { + Visit(exportDefaultDeclaration.Declaration); + } + } + + protected virtual void VisitExportAllDeclaration(ExportAllDeclaration exportAllDeclaration) + { + _sb.Append("export*from"); + Visit(exportAllDeclaration.Source); + } + + protected virtual void VisitExportNamedDeclaration(ExportNamedDeclaration exportNamedDeclaration) + { + _sb.Append("export"); + if (exportNamedDeclaration.Declaration != null) + { + _sb.Append(" "); + Visit(exportNamedDeclaration.Declaration); + } + if (exportNamedDeclaration.Specifiers.Count > 0) + { + _sb.Append("{"); + VisitNodeList(exportNamedDeclaration.Specifiers, appendSeperatorString: ","); + _sb.Append("}"); + } + if (exportNamedDeclaration.Source != null) + { + _sb.Append("from"); + Visit(exportNamedDeclaration.Source); + } + if (exportNamedDeclaration.Declaration == null && exportNamedDeclaration.Specifiers.Count == 0 && exportNamedDeclaration.Source == null) + _sb.Append("{}"); + + } + + protected virtual void VisitExportSpecifier(ExportSpecifier exportSpecifier) + { + Visit(exportSpecifier.Local); + if (exportSpecifier.Local != exportSpecifier.Exported) + { + _sb.Append(" as "); + Visit(exportSpecifier.Exported); + } + } + + protected virtual void VisitImport(Import import) + { + _sb.Append("import("); + Visit(import.Source); + _sb.Append(")"); + } + + protected virtual void VisitImportDeclaration(ImportDeclaration importDeclaration) + { + _sb.Append("import "); + var firstSpecifier = importDeclaration.Specifiers.FirstOrDefault(); + if (firstSpecifier is ImportDefaultSpecifier) + { + Visit(firstSpecifier); + if (importDeclaration.Specifiers.Count > 1) + { + _sb.Append(","); + if (importDeclaration.Specifiers[1] is ImportNamespaceSpecifier) + VisitNodeList(importDeclaration.Specifiers.Skip(1), appendSeperatorString: ","); + else + { + _sb.Append("{"); + VisitNodeList(importDeclaration.Specifiers.Skip(1), appendSeperatorString: ","); + _sb.Append("}"); + } + } + } + else if (importDeclaration.Specifiers.Any()) + { + if (importDeclaration.Specifiers[0] is ImportNamespaceSpecifier) + VisitNodeList(importDeclaration.Specifiers, appendSeperatorString: ","); + else + { + _sb.Append("{"); + VisitNodeList(importDeclaration.Specifiers, appendSeperatorString: ","); + _sb.Append("}"); + } + } + if (importDeclaration.Specifiers.Count > 0) + { + _sb.Append(" from "); + } + Visit(importDeclaration.Source); + } + + protected virtual void VisitImportNamespaceSpecifier(ImportNamespaceSpecifier importNamespaceSpecifier) + { + _sb.Append("* as "); + Visit(importNamespaceSpecifier.Local); + } + + protected virtual void VisitImportDefaultSpecifier(ImportDefaultSpecifier importDefaultSpecifier) + { + Visit(importDefaultSpecifier.Local); + } + + protected virtual void VisitImportSpecifier(ImportSpecifier importSpecifier) + { + Visit(importSpecifier.Imported); + if (importSpecifier.Local != importSpecifier.Imported) + { + _sb.Append(" as "); + Visit(importSpecifier.Local); + } + } + + protected virtual void VisitMethodDefinition(MethodDefinition methodDefinition) + { + if (methodDefinition.Static) + _sb.Append("static "); + if (IsAsync(methodDefinition.Value)) + _sb.Append("async "); + if (methodDefinition.Value is FunctionExpression f && f.Generator) + _sb.Append("*"); + if (methodDefinition.Kind == PropertyKind.Get) + _sb.Append("get "); + else if (methodDefinition.Kind == PropertyKind.Set) + _sb.Append("set "); + if (methodDefinition.Key is MemberExpression || ExpressionNeedsBrackets(methodDefinition.Key)) + _sb.Append("["); + if (ExpressionNeedsBrackets(methodDefinition.Key)) + _sb.Append("("); + Visit(methodDefinition.Key); + if (ExpressionNeedsBrackets(methodDefinition.Key)) + _sb.Append(")"); + if (methodDefinition.Key is MemberExpression || ExpressionNeedsBrackets(methodDefinition.Key)) + _sb.Append("]"); + Visit(methodDefinition.Value); + } + + protected virtual void VisitForOfStatement(ForOfStatement forOfStatement) + { + _sb.Append("for("); + Visit(forOfStatement.Left); + _sb.Append(" of "); + Visit(forOfStatement.Right); + _sb.Append(")"); + Visit(forOfStatement.Body); + if (NodeNeedsSemicolon(forOfStatement.Body)) + _sb.Append(";"); + } + + protected virtual void VisitClassDeclaration(ClassDeclaration classDeclaration) + { + _sb.Append("class "); + if (classDeclaration.Id != null) + { + Visit(classDeclaration.Id); + } + + if (classDeclaration.SuperClass != null) + { + _sb.Append(" extends "); + Visit(classDeclaration.SuperClass); + } + _sb.Append("{"); + Visit(classDeclaration.Body); + _sb.Append("}"); + } + + protected virtual void VisitClassBody(ClassBody classBody) + { + VisitNodeList(classBody.Body); + } + + protected virtual void VisitYieldExpression(YieldExpression yieldExpression) + { + _sb.Append("yield "); + if (yieldExpression.Argument != null) + { + Visit(yieldExpression.Argument); + } + } + + protected virtual void VisitTaggedTemplateExpression(TaggedTemplateExpression taggedTemplateExpression) + { + Visit(taggedTemplateExpression.Tag); + Visit(taggedTemplateExpression.Quasi); + } + + protected virtual void VisitSuper(Super super) + { + _sb.Append("super"); + } + + protected virtual void VisitMetaProperty(MetaProperty metaProperty) + { + Visit(metaProperty.Meta); + _sb.Append("."); + Visit(metaProperty.Property); + } + + protected virtual void VisitArrowParameterPlaceHolder(ArrowParameterPlaceHolder arrowParameterPlaceHolder) + { + VisitNodeList(arrowParameterPlaceHolder.Params); + } + + protected virtual void VisitObjectPattern(ObjectPattern objectPattern) + { + _sb.Append("{"); + VisitNodeList(objectPattern.Properties, appendSeperatorString: ","); + _sb.Append("}"); + } + + protected virtual void VisitSpreadElement(SpreadElement spreadElement) + { + _sb.Append("..."); + Visit(spreadElement.Argument); + } + + protected virtual void VisitAssignmentPattern(AssignmentPattern assignmentPattern) + { + Visit(assignmentPattern.Left); + _sb.Append("="); + Visit(assignmentPattern.Right); + } + + protected virtual void VisitArrayPattern(ArrayPattern arrayPattern) + { + _sb.Append("["); + VisitNodeList(arrayPattern.Elements, appendSeperatorString: ","); + _sb.Append("]"); + } + + protected virtual void VisitVariableDeclarator(VariableDeclarator variableDeclarator) + { + if (variableDeclarator.Id is ObjectPattern) + { + //_sb.Append("{"); + } + Visit(variableDeclarator.Id); + if (variableDeclarator.Id is ObjectPattern) + { + //_sb.Append("}"); + } + if (variableDeclarator.Init != null) + { + _sb.Append("="); + if (ExpressionNeedsBrackets(variableDeclarator.Init)) + _sb.Append("("); + Visit(variableDeclarator.Init); + if (ExpressionNeedsBrackets(variableDeclarator.Init)) + _sb.Append(")"); + } + } + + protected virtual void VisitTemplateLiteral(TemplateLiteral templateLiteral) + { + _sb.Append("`"); + for (int n = 0; n < templateLiteral.Quasis.Count; n++) + { + Visit(templateLiteral.Quasis[n]); + if (templateLiteral.Expressions.Count > n) + { + _sb.Append("${"); + Visit(templateLiteral.Expressions[n]); + _sb.Append("}"); + } + } + _sb.Append("`"); + } + + protected virtual void VisitTemplateElement(TemplateElement templateElement) + { + _sb.Append(templateElement.Value.Raw); + } + + protected virtual void VisitRestElement(RestElement restElement) + { + _sb.Append("..."); + Visit(restElement.Argument); + } + + protected virtual void VisitProperty(Property property) + { + if (property.Key is MemberExpression || ExpressionNeedsBrackets(property.Key)) + _sb.Append("["); + if (ExpressionNeedsBrackets(property.Key)) + _sb.Append("("); + Visit(property.Key); + if (ExpressionNeedsBrackets(property.Key)) + _sb.Append(")"); + if (property.Key is MemberExpression || ExpressionNeedsBrackets(property.Key)) + _sb.Append("]"); + if (property.Key is Identifier keyI && property.Value is Identifier valueI && keyI.Name == valueI.Name) + { } + else + { + _sb.Append(":"); + if (property.Value is not ObjectPattern && ExpressionNeedsBrackets(property.Value)) + _sb.Append("("); + Visit(property.Value); + if (property.Value is not ObjectPattern && ExpressionNeedsBrackets(property.Value)) + _sb.Append(")"); + } + } + + protected virtual void VisitPropertyDefinition(PropertyDefinition propertyDefinition) + { + if (propertyDefinition.Static) + { + _sb.Append("static "); + } + if (propertyDefinition.Key is MemberExpression || ExpressionNeedsBrackets(propertyDefinition.Key)) + _sb.Append("["); + if (ExpressionNeedsBrackets(propertyDefinition.Key)) + _sb.Append("("); + Visit(propertyDefinition.Key); + if (ExpressionNeedsBrackets(propertyDefinition.Key)) + _sb.Append(")"); + if (propertyDefinition.Key is MemberExpression || ExpressionNeedsBrackets(propertyDefinition.Key)) + _sb.Append("]"); + if (propertyDefinition.Value != null) + { + _sb.Append("="); + Visit(propertyDefinition.Value); + } + _sb.Append(";"); + } + + protected virtual void VisitAwaitExpression(AwaitExpression awaitExpression) + { + _sb.Append("await "); + Visit(awaitExpression.Argument); + } + + protected virtual void VisitConditionalExpression(ConditionalExpression conditionalExpression) + { + if (conditionalExpression.Test is AssignmentExpression) + _sb.Append("("); + Visit(conditionalExpression.Test); + if (conditionalExpression.Test is AssignmentExpression) + _sb.Append(")"); + _sb.Append("?"); + if (ExpressionNeedsBrackets(conditionalExpression.Consequent)) + _sb.Append("("); + Visit(conditionalExpression.Consequent); + if (ExpressionNeedsBrackets(conditionalExpression.Consequent)) + _sb.Append(")"); + _sb.Append(":"); + if (ExpressionNeedsBrackets(conditionalExpression.Alternate)) + _sb.Append("("); + Visit(conditionalExpression.Alternate); + if (ExpressionNeedsBrackets(conditionalExpression.Alternate)) + _sb.Append(")"); + } + + protected virtual void VisitCallExpression(CallExpression callExpression) + { + if (ExpressionNeedsBrackets(callExpression.Callee)) + _sb.Append("("); + Visit(callExpression.Callee); + if (ExpressionNeedsBrackets(callExpression.Callee)) + _sb.Append(")"); + _sb.Append("("); + VisitNodeList(callExpression.Arguments, appendSeperatorString: ",", appendBracketsIfNeeded: true); + _sb.Append(")"); + } + + protected virtual void VisitBinaryExpression(BinaryExpression binaryExpression) + { + if (ExpressionNeedsBrackets(binaryExpression.Left)) + _sb.Append("("); + Visit(binaryExpression.Left); + if (ExpressionNeedsBrackets(binaryExpression.Left)) + _sb.Append(")"); + var op = GetEnumValue("operator", binaryExpression.Operator); + if (char.IsLetter(op[0])) + _sb.Append(" "); + _sb.Append(op); + if (char.IsLetter(op[0])) + _sb.Append(" "); + if (ExpressionNeedsBrackets(binaryExpression.Right)) + _sb.Append("("); + Visit(binaryExpression.Right); + if (ExpressionNeedsBrackets(binaryExpression.Right)) + _sb.Append(")"); + } + + protected virtual void VisitArrayExpression(ArrayExpression arrayExpression) + { + _sb.Append("["); + VisitNodeList(arrayExpression.Elements, appendSeperatorString: ","); + _sb.Append("]"); + } + + protected virtual void VisitAssignmentExpression(AssignmentExpression assignmentExpression) + { + if (assignmentExpression.Left is ObjectPattern) + _sb.Append("("); + var op = GetEnumValue("assignmentoperator", assignmentExpression.Operator); + Visit(assignmentExpression.Left); + _sb.Append(op); + if (ExpressionNeedsBrackets(assignmentExpression.Right) && !(assignmentExpression.Right is AssignmentExpression)) + _sb.Append("("); + Visit(assignmentExpression.Right); + if (ExpressionNeedsBrackets(assignmentExpression.Right) && !(assignmentExpression.Right is AssignmentExpression)) + _sb.Append(")"); + if (assignmentExpression.Left is ObjectPattern) + _sb.Append(")"); + } + + protected virtual void VisitContinueStatement(ContinueStatement continueStatement) + { + _sb.Append("continue "); + if (continueStatement.Label != null) + { + Visit(continueStatement.Label); + } + } + + protected virtual void VisitBreakStatement(BreakStatement breakStatement) + { + if (breakStatement.Label != null) + { + Visit(breakStatement.Label); + } + _sb.Append("break"); + } + + protected virtual void VisitBlockStatement(BlockStatement blockStatement) + { + WriteStartLineToSb("{"); + if (beautify) + _sb.AppendLine(); + _indentionLevel++; + VisitNodeList(blockStatement.Body, appendAtEnd: ";"); + _indentionLevel--; + WriteEndLineToSb("}"); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void VisitNodeList(IEnumerable nodeList, string appendAtEnd = null, string appendSeperatorString = null, bool appendBracketsIfNeeded = false) + where TNode : Node + { + var notfirst = false; + foreach (var node in nodeList) + { + if (node != null) + { + if (notfirst && appendSeperatorString != null) + _sb.Append(appendSeperatorString); + if (appendBracketsIfNeeded && ExpressionNeedsBrackets(node)) + _sb.Append("("); + Visit(node); + if (appendBracketsIfNeeded && ExpressionNeedsBrackets(node)) + _sb.Append(")"); + notfirst = true; + if (appendAtEnd != null && NodeNeedsSemicolon(node)) + _sb.Append(appendAtEnd); + } + } + } + + protected virtual void WriteStartLineToSb(string text) + { + if (!beautify) + _sb.Append(text); + else + _sb.Append(text.PadLeft(_indentionLevel * _indentionSize, _indentionChar)); + } + + protected virtual void WriteEndLineToSb(string text) + { + if (!beautify) + _sb.Append(text); + else + _sb.AppendLine(text); + } + + public override string ToString() + { + return _sb.ToString(); + } + + public bool IsAsync(Node node) + { + if (node is ArrowFunctionExpression afe) + return afe.Async; + if (node is ArrowParameterPlaceHolder apph) + return apph.Async; + if (node is FunctionDeclaration fd) + return fd.Async; + if (node is FunctionExpression fe) + return fe.Async; + return false; + } + + public bool NodeNeedsSemicolon(Node? node) + { + if (node is BlockStatement || + node is IfStatement || + node is SwitchStatement || + node is ForInStatement || + node is ForOfStatement || + node is ForStatement || + node is FunctionDeclaration || + node is ReturnStatement || + node is ThrowStatement || + node is TryStatement || + node is EmptyStatement || + node is ClassDeclaration) + return false; + if (node is ExportNamedDeclaration end) + return NodeNeedsSemicolon(end.Declaration); + return true; + } + + public bool ExpressionNeedsBrackets(Node? node) + { + if (node is FunctionExpression) + return true; + if (node is ArrowFunctionExpression) + return true; + if (node is AssignmentExpression) + return true; + if (node is SequenceExpression) + return true; + if (node is ConditionalExpression) + return true; + if (node is BinaryExpression) + return true; + if (node is UnaryExpression) + return true; + if (node is CallExpression) + return true; + if (node is NewExpression) + return true; + if (node is ObjectPattern) + return true; + if (node is ArrayPattern) + return true; + if (node is YieldExpression) + return true; + return false; + } + } +} diff --git a/test/Esprima.Tests/JavascriptTest.cs b/test/Esprima.Tests/JavascriptTest.cs new file mode 100644 index 00000000..37dc4017 --- /dev/null +++ b/test/Esprima.Tests/JavascriptTest.cs @@ -0,0 +1,425 @@ +using Esprima.Utils; +using Xunit; + +namespace Esprima.Tests +{ + public class JavascriptTest + { + [Fact] + public void ToJavascriptTest1() + { + var parser = new JavaScriptParser(@"if (true) { p(); } +switch(foo) { + case 'A': + p(); + break; +} +switch(foo) { + default: + p(); + break; +} +for (var a = []; ; ) { } +for (var elem of list) { } +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + + Assert.Equal("if(true){p();}switch(foo){case 'A':p();break;}switch(foo){default:p();break;}for(var a=[];;){}for(var elem of list){}", code); + } + + [Fact] + public void ToJavascriptTest2() + { + var parser = new JavaScriptParser(@"let tips = [ + ""Click on any AST node with a '+' to expand it"", + + ""Hovering over a node highlights the \ + corresponding location in the source code"", + + ""Shift click on an AST node to expand the whole subtree"" +]; + + function printTips() + { + tips.forEach((tip, i) => console.log(`Tip ${ i}:` +tip)); + }"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest3() + { + var parser = new JavaScriptParser(@"export class aa extends HTMLElement{ + constructor(a, b) + { + super(a); + this._div = document.createElement('div'); + } + static get is() { + return 'aa'; + } +}"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest4() + { + var parser = new JavaScriptParser(@"import { MccDialog } from '../mccDialogHandler'; +import { commonClient, bb as f } from '../commonClient/commonClient'; +import ii, { hh, jj } from '../commonClient/commonClient'; +import '../commonClient/commonClient'; +import aa from 'module-name'; +import zz, * as ff from 'module-name'; +import * as name from 'module-name'; +import('qq'); +a++; +--a; +export function checkSecurityAnswerCodeDirect(result) { + if (!result) { + MccDialog.warning({ + title: 'SecurityClientErrorOccured', + message: '

internal error, check console

', + }); + return false; + } + switch (result.SecurityAnswerCode) { + case 'Allowed': + return true; + case 'Exception': + MccDialog.warning({ + title: 'SecurityClientInfoTitle', + message: '

SecurityClientExceptionOccured

Exception: ' + result.Message + '

' + result.StackTrace, + }); + return false; + case 'Error': + MccDialog.warning({ + title: 'SecurityClientErrorOccured', + message: '

' + + commonClient.getTranslation('SecurityClientMessage') + + ': ' + + commonClient.getTranslation(result.Message) + + '

' + + (result.MessageDetails ? '

SecurityClientDetails: ' + result.MessageDetails + '

' : ' '), + }); + return false; + default: { + let messagesnippet = '

SecurityClient_' + result.SecurityAnswerCode + '

'; + if (result.Message !== undefined && result.SecurityAnswerCode === 'LoginFailed') { + messagesnippet += '\n\nSecurityClient_InternalServerErrorMessage\n' + result.Message + ''; + } + if (result.Role) { + messagesnippet += '

SecurityClient_CheckedRole' + ' [' + result.Role + ']' + '

'; + } + MccDialog.warning({ + title: 'SecurityClientInfoTitle', + message: messagesnippet, + }); + return false; + } + } +}"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest5() + { + var parser = new JavaScriptParser(@"(function () { + 'use strict'; +})(); + +(class ApplyShimInterface { + constructor() { + this.customStyleInterface = null; + applyShim['invalidCallback'] = ApplyShimUtils.invalidate; + } +}); + +( + a +)(); + + +aa({}); + +(function aa(){});"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest6() + { + var parser = new JavaScriptParser(@"function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + }"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest7() + { + var parser = new JavaScriptParser(@"if ((x ? a.nodeName.toLowerCase() === f : 1 === a.nodeType) && ++d && (p && ((i = (o = a[S] || (a[S] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] = [k, d]), a === e)) +{ +}"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest8() + { + var parser = new JavaScriptParser(@" +class a extends b { + constructor() { + super(); + this.g=1; + } + + q=1; + r='cc'; +} +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest9() + { + var parser = new JavaScriptParser(@" +d = (s = (r = (i = (o = (a = c)[S] || (a[S] = {}))[a.uniqueID] || (o[a.uniqueID] = {}))[h] || [])[0] === k && r[1]) && r[2], a = s && c.childNodes[s]; +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest10() + { + var parser = new JavaScriptParser(@" +m = (z.document, !!v.documentElement && !!v.head && 'function' == typeof v.addEventListener && v.createElement, ~a.indexOf('MSIE') || a.indexOf('Trident/'), '___FONT_AWESOME___') +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest11() + { + var parser = new JavaScriptParser(@" + var h = (c.navigator || {}).userAgent, + a = void 0 === h ? '' : h, + z = c, + v = l, + m = (z.document, !!v.documentElement && !!v.head && 'function' == typeof v.addEventListener && v.createElement, ~a.indexOf('MSIE') || a.indexOf('Trident/'), '___FONT_AWESOME___'), + e = function() { + try { + return !0 + } catch (c) { + return !1 + } + }(); +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest12() + { + var parser = new JavaScriptParser(@" +var a = { +children: (b = O, 'g' === b.tag ? b.children : [b]) +} +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest13() + { + var parser = new JavaScriptParser(@" +if (e.IsWebService) + if (h = e.HttpRequest.responseXML, 'undefined' == typeof h) Trace.Write('Error: ' + e.UniqueId + ' data has no properties!'), m = !0; + else try { + h.setProperty('SelectionLanguage', 'XPath') + } catch (l) { + Trace.Write('Error: data.setProperty('SelectionLanguage', 'XPath') because ' + l.message) + } else h = e.HttpRequest.responseText; +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest14() + { + var parser = new JavaScriptParser(@" +function tt(t, r) { + var n, e, i = b(t), + s = b(r); + if (s && (e = ft(r)), i); + else if (s) return D(t, e) ? void $(t, e) : (n = l(e, t), G(t, n), void ht(t)); + var g, o, f; + for (f = t.length < r.length ? t.length : r.length, o = 0, g = 0; f > g; g++) o += t[g] + r[g], t[g] = o & _t, o >>= at; + for (g = f; o && g < t.length; g++) o += t[g], t[g] = o & _t, o >>= at +} +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest15() + { + var parser = new JavaScriptParser(@" +h='M'+(+new Date).toString(36) +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest16() + { + var parser = new JavaScriptParser(@" +input.onchange = async (e) => { + const files = await readFiles(input.files, readMode); + document.body.removeChild(input); + resolve(files); + }; +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest17() + { + var parser = new JavaScriptParser(@" +export const Base = LegacyElementMixin(HTMLElement).prototype; +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest18() + { + var parser = new JavaScriptParser(@" +let {is} = getIsExtends(element); +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest19() + { + var parser = new JavaScriptParser(@" +export const wrap = + (window['ShadyDOM'] && window['ShadyDOM']['wrap']) || (node => node); +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest20() + { + var parser = new JavaScriptParser(@" +export {}"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest21() + { + var parser = new JavaScriptParser(@" +(() => { + mutablePropertyChange = MutableData._mutablePropertyChange; +})(); +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest22() + { + var parser = new JavaScriptParser(@" +var Ol, jl = new (function() { + var l, h, z; + return l = c + }()) +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest23() + { + var parser = new JavaScriptParser(@" + +[y, { + [Symbol.iterator]() { + return b + },a:5 + }] + +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest24() + { + var parser = new JavaScriptParser(@" + +class A { +*[Symbol.iterator]() { + let L = this._first; + for (; L !== _.Undefined; ) + yield L.element, + L = L.next + } +} + +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + + [Fact] + public void ToJavascriptTest25() + { + var parser = new JavaScriptParser(@" +var i = function e(i) { + var r = n[i]; + if (void 0 !== r) + return r.exports; + var a = n[i] = { + exports: {} + }; + return t[i](a, a.exports, e), + a.exports + }(15); +"); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program); + } + } +} From 7ac50acdec7806d2269a1ca26adc0b2825d9ffef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Wed, 3 Nov 2021 08:17:09 +0100 Subject: [PATCH 02/10] increase MaxAssignmentDepth so MonacoEditor could be parsed, and make it adjustable --- src/Esprima/JavascriptParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Esprima/JavascriptParser.cs b/src/Esprima/JavascriptParser.cs index 81529518..78d9eea7 100644 --- a/src/Esprima/JavascriptParser.cs +++ b/src/Esprima/JavascriptParser.cs @@ -2281,7 +2281,7 @@ private void CheckPatternParam(ParsedParameters options, Node param) }; } - private const int MaxAssignmentDepth = 100; + public int MaxAssignmentDepth { get; set; } = 1000; private int _assignmentDepth = 0; private Expression ParseAssignmentExpression() From b1b413517e324b5e169d623ef55f8564222047e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Thu, 4 Nov 2021 21:56:07 +0100 Subject: [PATCH 03/10] fix coding to match esprima-net style --- src/Esprima/Utils/ToJavascriptConverter.cs | 210 ++++++++++++++++++++- 1 file changed, 200 insertions(+), 10 deletions(-) diff --git a/src/Esprima/Utils/ToJavascriptConverter.cs b/src/Esprima/Utils/ToJavascriptConverter.cs index 5a90e9b3..86fd1485 100644 --- a/src/Esprima/Utils/ToJavascriptConverter.cs +++ b/src/Esprima/Utils/ToJavascriptConverter.cs @@ -298,7 +298,9 @@ protected virtual void VisitCatchClause(CatchClause catchClause) { _sb.Append("("); if (catchClause.Param is not null) + { Visit(catchClause.Param); + } _sb.Append(")"); Visit(catchClause.Body); } @@ -306,10 +308,14 @@ protected virtual void VisitCatchClause(CatchClause catchClause) protected virtual void VisitFunctionDeclaration(FunctionDeclaration functionDeclaration) { if (functionDeclaration.Async) + { _sb.Append("async "); + } _sb.Append("function"); if (functionDeclaration.Generator) + { _sb.Append("*"); + } if (functionDeclaration.Id != null) { _sb.Append(" "); @@ -379,12 +385,13 @@ protected virtual void VisitSwitchCase(SwitchCase switchCase) { if (switchCase.Test != null) { - //todo, remove space after case, if testcase is a string starting with " or ' WriteStartLineToSb("case "); Visit(switchCase.Test); } else + { WriteStartLineToSb("default"); + } WriteStartLineToSb(":"); VisitNodeList(switchCase.Consequent, appendAtEnd: ";"); @@ -415,7 +422,9 @@ protected virtual void VisitIfStatement(IfStatement ifStatement) WriteEndLineToSb(")"); Visit(ifStatement.Consequent); if (NodeNeedsSemicolon(ifStatement.Consequent)) + { _sb.Append(";"); + } if (ifStatement.Alternate != null) { _sb.Append(" else "); @@ -440,10 +449,14 @@ protected virtual void VisitExpressionStatement(ExpressionStatement expressionSt if (expressionStatement.Expression is CallExpression callExpression && !(callExpression.Callee is Identifier)) { if (ExpressionNeedsBrackets(callExpression.Callee)) + { _sb.Append("("); + } Visit(callExpression.Callee); if (ExpressionNeedsBrackets(callExpression.Callee)) + { _sb.Append(")"); + } _sb.Append("("); VisitNodeList(callExpression.Arguments, appendSeperatorString: ","); _sb.Append(")"); @@ -455,7 +468,9 @@ protected virtual void VisitExpressionStatement(ExpressionStatement expressionSt _sb.Append(")"); } else + { Visit(expressionStatement.Expression); + } } protected virtual void VisitForStatement(ForStatement forStatement) @@ -478,7 +493,9 @@ protected virtual void VisitForStatement(ForStatement forStatement) _sb.Append(")"); Visit(forStatement.Body); if (NodeNeedsSemicolon(forStatement.Body)) + { _sb.Append(";"); + } } protected virtual void VisitForInStatement(ForInStatement forInStatement) @@ -490,7 +507,9 @@ protected virtual void VisitForInStatement(ForInStatement forInStatement) _sb.Append(")"); Visit(forInStatement.Body); if (NodeNeedsSemicolon(forInStatement.Body)) + { _sb.Append(";"); + } } protected virtual void VisitDoWhileStatement(DoWhileStatement doWhileStatement) @@ -498,7 +517,9 @@ protected virtual void VisitDoWhileStatement(DoWhileStatement doWhileStatement) _sb.Append("do "); Visit(doWhileStatement.Body); if (NodeNeedsSemicolon(doWhileStatement.Body)) + { _sb.Append(";"); + } _sb.Append("while("); Visit(doWhileStatement.Test); _sb.Append(")"); @@ -519,10 +540,14 @@ protected virtual void VisitArrowFunctionExpression(ArrowFunctionExpression arro if (arrowFunctionExpression.Params.Count == 1) { if (arrowFunctionExpression.Params[0] is RestElement || ExpressionNeedsBrackets(arrowFunctionExpression.Params[0])) + { _sb.Append("("); + } Visit(arrowFunctionExpression.Params[0]); if (arrowFunctionExpression.Params[0] is RestElement || ExpressionNeedsBrackets(arrowFunctionExpression.Params[0])) + { _sb.Append(")"); + } } else { @@ -532,10 +557,14 @@ protected virtual void VisitArrowFunctionExpression(ArrowFunctionExpression arro } _sb.Append("=>"); if (arrowFunctionExpression.Body is ObjectExpression || arrowFunctionExpression.Body is SequenceExpression) + { _sb.Append("("); + } Visit(arrowFunctionExpression.Body); if (arrowFunctionExpression.Body is ObjectExpression || arrowFunctionExpression.Body is SequenceExpression) + { _sb.Append(")"); + } } protected virtual void VisitUnaryExpression(UnaryExpression unaryExpression) @@ -548,21 +577,31 @@ protected virtual void VisitUnaryExpression(UnaryExpression unaryExpression) _sb.Append(" "); } if (!(unaryExpression.Argument is Literal) && !(unaryExpression.Argument is UnaryExpression)) + { _sb.Append("("); + } Visit(unaryExpression.Argument); if (!(unaryExpression.Argument is Literal) && !(unaryExpression.Argument is UnaryExpression)) + { _sb.Append(")"); + } if (!unaryExpression.Prefix) + { _sb.Append(op); + } } protected virtual void VisitUpdateExpression(UpdateExpression updateExpression) { if (updateExpression.Prefix) + { _sb.Append(GetEnumValue("unaryoperator", updateExpression.Operator)); + } Visit(updateExpression.Argument); if (!updateExpression.Prefix) + { _sb.Append(GetEnumValue("unaryoperator", updateExpression.Operator)); + } } protected virtual void VisitThisExpression(ThisExpression thisExpression) @@ -586,12 +625,18 @@ protected virtual void VisitNewExpression(NewExpression newExpression) { _sb.Append("new"); if (ExpressionNeedsBrackets(newExpression.Callee)) + { _sb.Append("("); + } else + { _sb.Append(" "); + } Visit(newExpression.Callee); if (ExpressionNeedsBrackets(newExpression.Callee)) + { _sb.Append(")"); + } if (newExpression.Arguments.Count > 0) { _sb.Append("("); @@ -603,12 +648,18 @@ protected virtual void VisitNewExpression(NewExpression newExpression) protected virtual void VisitMemberExpression(MemberExpression memberExpression) { if (ExpressionNeedsBrackets(memberExpression.Object) || (memberExpression.Object is Literal l && l.TokenType != TokenType.StringLiteral)) + { _sb.Append("("); + } Visit(memberExpression.Object); if (ExpressionNeedsBrackets(memberExpression.Object) || (memberExpression.Object is Literal l2 && l2.TokenType != TokenType.StringLiteral)) + { _sb.Append(")"); + } if (memberExpression.Computed) + { _sb.Append("["); + } else { if (TryGetParentAt(0) is ChainExpression) @@ -617,7 +668,9 @@ protected virtual void VisitMemberExpression(MemberExpression memberExpression) } Visit(memberExpression.Property); if (memberExpression.Computed) + { _sb.Append("]"); + } } protected virtual void VisitLiteral(Literal literal) @@ -636,11 +689,17 @@ protected virtual void VisitFunctionExpression(IFunction function) if (!isParentMethod) { if (function.Async) + { _sb.Append("async "); + } if (!(TryGetParentAt(1) is MethodDefinition)) + { _sb.Append("function"); + } if (function.Generator) + { _sb.Append("*"); + } } if (function.Id != null) { @@ -660,7 +719,6 @@ protected virtual void VisitClassExpression(ClassExpression classExpression) { Visit(classExpression.Id); } - if (classExpression.SuperClass != null) { _sb.Append(" extends "); @@ -706,7 +764,9 @@ protected virtual void VisitExportNamedDeclaration(ExportNamedDeclaration export Visit(exportNamedDeclaration.Source); } if (exportNamedDeclaration.Declaration == null && exportNamedDeclaration.Specifiers.Count == 0 && exportNamedDeclaration.Source == null) + { _sb.Append("{}"); + } } @@ -738,7 +798,9 @@ protected virtual void VisitImportDeclaration(ImportDeclaration importDeclaratio { _sb.Append(","); if (importDeclaration.Specifiers[1] is ImportNamespaceSpecifier) + { VisitNodeList(importDeclaration.Specifiers.Skip(1), appendSeperatorString: ","); + } else { _sb.Append("{"); @@ -750,7 +812,9 @@ protected virtual void VisitImportDeclaration(ImportDeclaration importDeclaratio else if (importDeclaration.Specifiers.Any()) { if (importDeclaration.Specifiers[0] is ImportNamespaceSpecifier) + { VisitNodeList(importDeclaration.Specifiers, appendSeperatorString: ","); + } else { _sb.Append("{"); @@ -789,24 +853,42 @@ protected virtual void VisitImportSpecifier(ImportSpecifier importSpecifier) protected virtual void VisitMethodDefinition(MethodDefinition methodDefinition) { if (methodDefinition.Static) + { _sb.Append("static "); + } if (IsAsync(methodDefinition.Value)) + { _sb.Append("async "); + } if (methodDefinition.Value is FunctionExpression f && f.Generator) + { _sb.Append("*"); + } if (methodDefinition.Kind == PropertyKind.Get) + { _sb.Append("get "); + } else if (methodDefinition.Kind == PropertyKind.Set) + { _sb.Append("set "); + } if (methodDefinition.Key is MemberExpression || ExpressionNeedsBrackets(methodDefinition.Key)) + { _sb.Append("["); + } if (ExpressionNeedsBrackets(methodDefinition.Key)) + { _sb.Append("("); + } Visit(methodDefinition.Key); if (ExpressionNeedsBrackets(methodDefinition.Key)) + { _sb.Append(")"); + } if (methodDefinition.Key is MemberExpression || ExpressionNeedsBrackets(methodDefinition.Key)) + { _sb.Append("]"); + } Visit(methodDefinition.Value); } @@ -819,7 +901,9 @@ protected virtual void VisitForOfStatement(ForOfStatement forOfStatement) _sb.Append(")"); Visit(forOfStatement.Body); if (NodeNeedsSemicolon(forOfStatement.Body)) + { _sb.Append(";"); + } } protected virtual void VisitClassDeclaration(ClassDeclaration classDeclaration) @@ -906,23 +990,19 @@ protected virtual void VisitArrayPattern(ArrayPattern arrayPattern) protected virtual void VisitVariableDeclarator(VariableDeclarator variableDeclarator) { - if (variableDeclarator.Id is ObjectPattern) - { - //_sb.Append("{"); - } Visit(variableDeclarator.Id); - if (variableDeclarator.Id is ObjectPattern) - { - //_sb.Append("}"); - } if (variableDeclarator.Init != null) { _sb.Append("="); if (ExpressionNeedsBrackets(variableDeclarator.Init)) + { _sb.Append("("); + } Visit(variableDeclarator.Init); if (ExpressionNeedsBrackets(variableDeclarator.Init)) + { _sb.Append(")"); + } } } @@ -956,24 +1036,36 @@ protected virtual void VisitRestElement(RestElement restElement) protected virtual void VisitProperty(Property property) { if (property.Key is MemberExpression || ExpressionNeedsBrackets(property.Key)) + { _sb.Append("["); + } if (ExpressionNeedsBrackets(property.Key)) + { _sb.Append("("); + } Visit(property.Key); if (ExpressionNeedsBrackets(property.Key)) + { _sb.Append(")"); + } if (property.Key is MemberExpression || ExpressionNeedsBrackets(property.Key)) + { _sb.Append("]"); + } if (property.Key is Identifier keyI && property.Value is Identifier valueI && keyI.Name == valueI.Name) { } else { _sb.Append(":"); if (property.Value is not ObjectPattern && ExpressionNeedsBrackets(property.Value)) + { _sb.Append("("); + } Visit(property.Value); if (property.Value is not ObjectPattern && ExpressionNeedsBrackets(property.Value)) + { _sb.Append(")"); + } } } @@ -984,14 +1076,22 @@ protected virtual void VisitPropertyDefinition(PropertyDefinition propertyDefini _sb.Append("static "); } if (propertyDefinition.Key is MemberExpression || ExpressionNeedsBrackets(propertyDefinition.Key)) + { _sb.Append("["); + } if (ExpressionNeedsBrackets(propertyDefinition.Key)) + { _sb.Append("("); + } Visit(propertyDefinition.Key); if (ExpressionNeedsBrackets(propertyDefinition.Key)) + { _sb.Append(")"); + } if (propertyDefinition.Key is MemberExpression || ExpressionNeedsBrackets(propertyDefinition.Key)) + { _sb.Append("]"); + } if (propertyDefinition.Value != null) { _sb.Append("="); @@ -1009,31 +1109,47 @@ protected virtual void VisitAwaitExpression(AwaitExpression awaitExpression) protected virtual void VisitConditionalExpression(ConditionalExpression conditionalExpression) { if (conditionalExpression.Test is AssignmentExpression) + { _sb.Append("("); + } Visit(conditionalExpression.Test); if (conditionalExpression.Test is AssignmentExpression) + { _sb.Append(")"); + } _sb.Append("?"); if (ExpressionNeedsBrackets(conditionalExpression.Consequent)) + { _sb.Append("("); + } Visit(conditionalExpression.Consequent); if (ExpressionNeedsBrackets(conditionalExpression.Consequent)) + { _sb.Append(")"); + } _sb.Append(":"); if (ExpressionNeedsBrackets(conditionalExpression.Alternate)) + { _sb.Append("("); + } Visit(conditionalExpression.Alternate); if (ExpressionNeedsBrackets(conditionalExpression.Alternate)) + { _sb.Append(")"); + } } protected virtual void VisitCallExpression(CallExpression callExpression) { if (ExpressionNeedsBrackets(callExpression.Callee)) + { _sb.Append("("); + } Visit(callExpression.Callee); if (ExpressionNeedsBrackets(callExpression.Callee)) + { _sb.Append(")"); + } _sb.Append("("); VisitNodeList(callExpression.Arguments, appendSeperatorString: ",", appendBracketsIfNeeded: true); _sb.Append(")"); @@ -1042,21 +1158,33 @@ protected virtual void VisitCallExpression(CallExpression callExpression) protected virtual void VisitBinaryExpression(BinaryExpression binaryExpression) { if (ExpressionNeedsBrackets(binaryExpression.Left)) + { _sb.Append("("); + } Visit(binaryExpression.Left); if (ExpressionNeedsBrackets(binaryExpression.Left)) + { _sb.Append(")"); + } var op = GetEnumValue("operator", binaryExpression.Operator); if (char.IsLetter(op[0])) + { _sb.Append(" "); + } _sb.Append(op); if (char.IsLetter(op[0])) + { _sb.Append(" "); + } if (ExpressionNeedsBrackets(binaryExpression.Right)) + { _sb.Append("("); + } Visit(binaryExpression.Right); if (ExpressionNeedsBrackets(binaryExpression.Right)) + { _sb.Append(")"); + } } protected virtual void VisitArrayExpression(ArrayExpression arrayExpression) @@ -1069,17 +1197,25 @@ protected virtual void VisitArrayExpression(ArrayExpression arrayExpression) protected virtual void VisitAssignmentExpression(AssignmentExpression assignmentExpression) { if (assignmentExpression.Left is ObjectPattern) + { _sb.Append("("); + } var op = GetEnumValue("assignmentoperator", assignmentExpression.Operator); Visit(assignmentExpression.Left); _sb.Append(op); if (ExpressionNeedsBrackets(assignmentExpression.Right) && !(assignmentExpression.Right is AssignmentExpression)) + { _sb.Append("("); + } Visit(assignmentExpression.Right); if (ExpressionNeedsBrackets(assignmentExpression.Right) && !(assignmentExpression.Right is AssignmentExpression)) + { _sb.Append(")"); + } if (assignmentExpression.Left is ObjectPattern) + { _sb.Append(")"); + } } protected virtual void VisitContinueStatement(ContinueStatement continueStatement) @@ -1104,7 +1240,9 @@ protected virtual void VisitBlockStatement(BlockStatement blockStatement) { WriteStartLineToSb("{"); if (beautify) + { _sb.AppendLine(); + } _indentionLevel++; VisitNodeList(blockStatement.Body, appendAtEnd: ";"); _indentionLevel--; @@ -1121,15 +1259,23 @@ private void VisitNodeList(IEnumerable nodeList, string appendAtEn if (node != null) { if (notfirst && appendSeperatorString != null) + { _sb.Append(appendSeperatorString); + } if (appendBracketsIfNeeded && ExpressionNeedsBrackets(node)) + { _sb.Append("("); + } Visit(node); if (appendBracketsIfNeeded && ExpressionNeedsBrackets(node)) + { _sb.Append(")"); + } notfirst = true; if (appendAtEnd != null && NodeNeedsSemicolon(node)) + { _sb.Append(appendAtEnd); + } } } } @@ -1137,17 +1283,25 @@ private void VisitNodeList(IEnumerable nodeList, string appendAtEn protected virtual void WriteStartLineToSb(string text) { if (!beautify) + { _sb.Append(text); + } else + { _sb.Append(text.PadLeft(_indentionLevel * _indentionSize, _indentionChar)); + } } protected virtual void WriteEndLineToSb(string text) { if (!beautify) + { _sb.Append(text); + } else + { _sb.AppendLine(text); + } } public override string ToString() @@ -1158,13 +1312,21 @@ public override string ToString() public bool IsAsync(Node node) { if (node is ArrowFunctionExpression afe) + { return afe.Async; + } if (node is ArrowParameterPlaceHolder apph) + { return apph.Async; + } if (node is FunctionDeclaration fd) + { return fd.Async; + } if (node is FunctionExpression fe) + { return fe.Async; + } return false; } @@ -1182,38 +1344,66 @@ node is ThrowStatement || node is TryStatement || node is EmptyStatement || node is ClassDeclaration) + { return false; + } if (node is ExportNamedDeclaration end) + { return NodeNeedsSemicolon(end.Declaration); + } return true; } public bool ExpressionNeedsBrackets(Node? node) { if (node is FunctionExpression) + { return true; + } if (node is ArrowFunctionExpression) + { return true; + } if (node is AssignmentExpression) + { return true; + } if (node is SequenceExpression) + { return true; + } if (node is ConditionalExpression) + { return true; + } if (node is BinaryExpression) + { return true; + } if (node is UnaryExpression) + { return true; + } if (node is CallExpression) + { return true; + } if (node is NewExpression) + { return true; + } if (node is ObjectPattern) + { return true; + } if (node is ArrayPattern) + { return true; + } if (node is YieldExpression) + { return true; + } return false; } } From e481e8b7eeece25e4a451d8fcfc5a87ad98ea1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Thu, 4 Nov 2021 23:27:29 +0100 Subject: [PATCH 04/10] fixes after code review --- src/Esprima/Ast/AssignmentExpression.cs | 25 ++++++- src/Esprima/Ast/BinaryExpression.cs | 33 +++++++++ src/Esprima/Ast/UnaryExpression.cs | 19 ++++- src/Esprima/Utils/ToJavascriptConverter.cs | 86 ++++++---------------- 4 files changed, 98 insertions(+), 65 deletions(-) diff --git a/src/Esprima/Ast/AssignmentExpression.cs b/src/Esprima/Ast/AssignmentExpression.cs index 826cf62a..6c8c3414 100644 --- a/src/Esprima/Ast/AssignmentExpression.cs +++ b/src/Esprima/Ast/AssignmentExpression.cs @@ -42,7 +42,6 @@ public AssignmentExpression( Right = right; } - public static AssignmentOperator ParseAssignmentOperator(string op) { return op switch @@ -67,6 +66,30 @@ public static AssignmentOperator ParseAssignmentOperator(string op) }; } + public static string ConvertAssignmentOperator(AssignmentOperator op) + { + return op switch + { + AssignmentOperator.Assign => "=", + AssignmentOperator.PlusAssign => "+=", + AssignmentOperator.MinusAssign => "-=", + AssignmentOperator.TimesAssign => "*=", + AssignmentOperator.DivideAssign => "/=", + AssignmentOperator.ModuloAssign => "%=", + AssignmentOperator.BitwiseAndAssign => "&=", + AssignmentOperator.BitwiseOrAssign => "|=", + AssignmentOperator.BitwiseXOrAssign => "^=", + AssignmentOperator.ExponentiationAssign => "**=", + AssignmentOperator.LeftShiftAssign => "<<=", + AssignmentOperator.RightShiftAssign => ">>=", + AssignmentOperator.UnsignedRightShiftAssign => ">>>=", + AssignmentOperator.NullishAssign => "??=", + AssignmentOperator.AndAssign => "&&=", + AssignmentOperator.OrAssign => "||=", + _ => ThrowArgumentOutOfRangeException(nameof(op), "Invalid assignment operator: " + op) + }; + } + public override NodeCollection ChildNodes => new(Left, Right); protected internal override void Accept(AstVisitor visitor) diff --git a/src/Esprima/Ast/BinaryExpression.cs b/src/Esprima/Ast/BinaryExpression.cs index d210fb23..b0b27c3d 100644 --- a/src/Esprima/Ast/BinaryExpression.cs +++ b/src/Esprima/Ast/BinaryExpression.cs @@ -84,6 +84,39 @@ public static BinaryOperator ParseBinaryOperator(string op) }; } + public static string ConvertBinaryOperator(BinaryOperator op) + { + return op switch + { + BinaryOperator.Plus => "+", + BinaryOperator.Minus => "-", + BinaryOperator.Times => "*", + BinaryOperator.Divide => "/", + BinaryOperator.Modulo => "%", + BinaryOperator.Equal => "==", + BinaryOperator.NotEqual => "!=", + BinaryOperator.Greater => ">", + BinaryOperator.GreaterOrEqual => ">=", + BinaryOperator.Less => "<", + BinaryOperator.LessOrEqual => "<=", + BinaryOperator.StrictlyEqual => "===", + BinaryOperator.StricltyNotEqual => "!==", + BinaryOperator.BitwiseAnd => "&", + BinaryOperator.BitwiseOr => "|", + BinaryOperator.BitwiseXOr => "^", + BinaryOperator.LeftShift => "<<", + BinaryOperator.RightShift => ">>", + BinaryOperator.UnsignedRightShift => ">>>", + BinaryOperator.InstanceOf => "instanceof", + BinaryOperator.In => "in", + BinaryOperator.LogicalAnd => "&&", + BinaryOperator.LogicalOr => "||", + BinaryOperator.Exponentiation => "**", + BinaryOperator.NullishCoalescing => "??", + _ => ThrowArgumentOutOfRangeException(nameof(op), "Invalid binary operator: " + op) + }; + } + public override NodeCollection ChildNodes => new(Left, Right); protected internal override void Accept(AstVisitor visitor) diff --git a/src/Esprima/Ast/UnaryExpression.cs b/src/Esprima/Ast/UnaryExpression.cs index be1794b1..6232ac6f 100644 --- a/src/Esprima/Ast/UnaryExpression.cs +++ b/src/Esprima/Ast/UnaryExpression.cs @@ -33,7 +33,7 @@ protected UnaryExpression(Nodes type, string? op, Expression arg) : base(type) Prefix = true; } - private static UnaryOperator ParseUnaryOperator(string? op) + public static UnaryOperator ParseUnaryOperator(string? op) { return op switch { @@ -50,6 +50,23 @@ private static UnaryOperator ParseUnaryOperator(string? op) }; } + public static string ConvertUnaryOperator(UnaryOperator op) + { + return op switch + { + UnaryOperator.Plus => "+", + UnaryOperator.Minus => "-", + UnaryOperator.Increment => "++", + UnaryOperator.Decrement => "--", + UnaryOperator.BitwiseNot => "~", + UnaryOperator.LogicalNot => "!", + UnaryOperator.Delete => "delete", + UnaryOperator.Void => "void", + UnaryOperator.TypeOf => "typeof", + _ => ThrowArgumentOutOfRangeException(nameof(op), "Invalid unary operator: " + op) + }; + } + public override NodeCollection ChildNodes => new(Argument); protected internal override void Accept(AstVisitor visitor) diff --git a/src/Esprima/Utils/ToJavascriptConverter.cs b/src/Esprima/Utils/ToJavascriptConverter.cs index 86fd1485..dab5e1b9 100644 --- a/src/Esprima/Utils/ToJavascriptConverter.cs +++ b/src/Esprima/Utils/ToJavascriptConverter.cs @@ -9,6 +9,14 @@ namespace Esprima.Utils { + public static class ToJavascriptConverterExtension + { + public static string ToJavascript(this Node node) + { + return ToJavascriptConverter.ToJavascript(node); + } + } + public class ToJavascriptConverter { public static string ToJavascript(Node node) @@ -19,25 +27,7 @@ public static string ToJavascript(Node node) } protected StringBuilder _sb = new StringBuilder(); - protected int _indentionLevel = 0; - protected bool beautify = false; - protected int _indentionSize = 4; - protected char _indentionChar = ' '; - - private static readonly ConditionalWeakTable EnumMap = new ConditionalWeakTable(); - - private string GetEnumValue(string name, T value) where T : Enum - { - var map = (Dictionary) - EnumMap.GetValue(value.GetType(), - t => t.GetRuntimeFields() - .Where(f => f.IsStatic) - .ToDictionary(f => (T) f.GetValue(null), - f => f.GetCustomAttribute() is EnumMemberAttribute a - ? a.Value : f.Name.ToLowerInvariant())); - return map[value]; - } - + private readonly List _parentStack = new List(); protected IReadOnlyList ParentStack => _parentStack; @@ -374,7 +364,7 @@ protected virtual void VisitThrowStatement(ThrowStatement throwStatement) protected virtual void VisitSwitchStatement(SwitchStatement switchStatement) { - WriteStartLineToSb("switch("); + _sb.Append("switch("); Visit(switchStatement.Discriminant); _sb.Append("){"); VisitNodeList(switchStatement.Cases); @@ -385,14 +375,14 @@ protected virtual void VisitSwitchCase(SwitchCase switchCase) { if (switchCase.Test != null) { - WriteStartLineToSb("case "); + _sb.Append("case "); Visit(switchCase.Test); } else { - WriteStartLineToSb("default"); + _sb.Append("default"); } - WriteStartLineToSb(":"); + _sb.Append(":"); VisitNodeList(switchCase.Consequent, appendAtEnd: ";"); } @@ -417,9 +407,9 @@ protected virtual void VisitLabeledStatement(LabeledStatement labeledStatement) protected virtual void VisitIfStatement(IfStatement ifStatement) { - WriteStartLineToSb("if("); + _sb.Append("if("); Visit(ifStatement.Test); - WriteEndLineToSb(")"); + _sb.Append(")"); Visit(ifStatement.Consequent); if (NodeNeedsSemicolon(ifStatement.Consequent)) { @@ -475,7 +465,7 @@ protected virtual void VisitExpressionStatement(ExpressionStatement expressionSt protected virtual void VisitForStatement(ForStatement forStatement) { - WriteStartLineToSb("for("); + _sb.Append("for("); if (forStatement.Init != null) { Visit(forStatement.Init); @@ -569,7 +559,7 @@ protected virtual void VisitArrowFunctionExpression(ArrowFunctionExpression arro protected virtual void VisitUnaryExpression(UnaryExpression unaryExpression) { - var op = GetEnumValue("unaryoperator", unaryExpression.Operator); + var op = UnaryExpression.ConvertUnaryOperator(unaryExpression.Operator); if (unaryExpression.Prefix) { _sb.Append(op); @@ -595,12 +585,12 @@ protected virtual void VisitUpdateExpression(UpdateExpression updateExpression) { if (updateExpression.Prefix) { - _sb.Append(GetEnumValue("unaryoperator", updateExpression.Operator)); + _sb.Append(UnaryExpression.ConvertUnaryOperator(updateExpression.Operator)); } Visit(updateExpression.Argument); if (!updateExpression.Prefix) { - _sb.Append(GetEnumValue("unaryoperator", updateExpression.Operator)); + _sb.Append(UnaryExpression.ConvertUnaryOperator(updateExpression.Operator)); } } @@ -1166,7 +1156,7 @@ protected virtual void VisitBinaryExpression(BinaryExpression binaryExpression) { _sb.Append(")"); } - var op = GetEnumValue("operator", binaryExpression.Operator); + var op = BinaryExpression.ConvertBinaryOperator(binaryExpression.Operator); if (char.IsLetter(op[0])) { _sb.Append(" "); @@ -1200,7 +1190,7 @@ protected virtual void VisitAssignmentExpression(AssignmentExpression assignment { _sb.Append("("); } - var op = GetEnumValue("assignmentoperator", assignmentExpression.Operator); + var op = AssignmentExpression.ConvertAssignmentOperator(assignmentExpression.Operator); Visit(assignmentExpression.Left); _sb.Append(op); if (ExpressionNeedsBrackets(assignmentExpression.Right) && !(assignmentExpression.Right is AssignmentExpression)) @@ -1238,15 +1228,9 @@ protected virtual void VisitBreakStatement(BreakStatement breakStatement) protected virtual void VisitBlockStatement(BlockStatement blockStatement) { - WriteStartLineToSb("{"); - if (beautify) - { - _sb.AppendLine(); - } - _indentionLevel++; + _sb.Append("{"); VisitNodeList(blockStatement.Body, appendAtEnd: ";"); - _indentionLevel--; - WriteEndLineToSb("}"); + _sb.Append("}"); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1280,30 +1264,6 @@ private void VisitNodeList(IEnumerable nodeList, string appendAtEn } } - protected virtual void WriteStartLineToSb(string text) - { - if (!beautify) - { - _sb.Append(text); - } - else - { - _sb.Append(text.PadLeft(_indentionLevel * _indentionSize, _indentionChar)); - } - } - - protected virtual void WriteEndLineToSb(string text) - { - if (!beautify) - { - _sb.Append(text); - } - else - { - _sb.AppendLine(text); - } - } - public override string ToString() { return _sb.ToString(); From 8a35bb722f1244943b234c015461beec942b2655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Tue, 9 Nov 2021 22:56:30 +0100 Subject: [PATCH 05/10] work on ToJavascriptTest and Beautification --- src/Esprima/Utils/ToJavascriptConverter.cs | 604 +++++++++++++-------- test/Esprima.Tests/JavascriptTest.cs | 146 ++++- 2 files changed, 518 insertions(+), 232 deletions(-) diff --git a/src/Esprima/Utils/ToJavascriptConverter.cs b/src/Esprima/Utils/ToJavascriptConverter.cs index dab5e1b9..8afadd69 100644 --- a/src/Esprima/Utils/ToJavascriptConverter.cs +++ b/src/Esprima/Utils/ToJavascriptConverter.cs @@ -1,8 +1,6 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using Esprima.Ast; @@ -11,26 +9,70 @@ namespace Esprima.Utils { public static class ToJavascriptConverterExtension { - public static string ToJavascript(this Node node) + public static string ToJavascript(this Node node, bool beautify = false) { - return ToJavascriptConverter.ToJavascript(node); + return ToJavascriptConverter.ToJavascript(node, beautify); } } public class ToJavascriptConverter { - public static string ToJavascript(Node node) + public static string ToJavascript(Node node, bool beautify = false) { - var visitor = new ToJavascriptConverter(); + var visitor = new ToJavascriptConverter() { Beautify = beautify }; visitor.Visit(node); return visitor.ToString(); } + public bool Beautify { get; set; } + + public int IndentionSize { get; set; } = 4; + protected StringBuilder _sb = new StringBuilder(); - + private int _indentionLevel = 0; + private readonly List _parentStack = new List(); protected IReadOnlyList ParentStack => _parentStack; + private void Append(string text) + { + _sb.Append(text); + } + + private void AppendBeautificationSpace() + { + if (Beautify) + { + _sb.Append(" "); + } + } + + private void AppendIndent() + { + if (Beautify) + { + _sb.Append("".PadLeft(_indentionLevel * IndentionSize, ' ')); + } + } + + private void AppendNewline() + { + if (Beautify) + { + _sb.AppendLine(); + } + } + + private void IncreaseIndent() + { + _indentionLevel++; + } + + private void DecreaseIndent() + { + _indentionLevel--; + } + /// /// Returns parent node at specified position. /// @@ -271,7 +313,7 @@ public virtual void Visit(Node node) protected virtual void VisitProgram(Program program) { - VisitNodeList(program.Body, appendAtEnd: ";"); + VisitNodeList(program.Body, appendAtEnd: ";", addLineBreaks: true); } protected virtual void VisitUnknownNode(Node node) @@ -286,12 +328,12 @@ protected virtual void VisitChainExpression(ChainExpression chainExpression) protected virtual void VisitCatchClause(CatchClause catchClause) { - _sb.Append("("); + Append("("); if (catchClause.Param is not null) { Visit(catchClause.Param); } - _sb.Append(")"); + Append(")"); Visit(catchClause.Body); } @@ -299,139 +341,171 @@ protected virtual void VisitFunctionDeclaration(FunctionDeclaration functionDecl { if (functionDeclaration.Async) { - _sb.Append("async "); + Append("async "); } - _sb.Append("function"); + Append("function"); if (functionDeclaration.Generator) { - _sb.Append("*"); + Append("*"); } if (functionDeclaration.Id != null) { - _sb.Append(" "); + Append(" "); Visit(functionDeclaration.Id); } - _sb.Append("("); + Append("("); VisitNodeList(functionDeclaration.Params, appendSeperatorString: ","); - _sb.Append(")"); + Append(")"); + AppendBeautificationSpace(); Visit(functionDeclaration.Body); } protected virtual void VisitWithStatement(WithStatement withStatement) { - _sb.Append("with("); + Append("with("); Visit(withStatement.Object); - _sb.Append(")"); + Append(")"); Visit(withStatement.Body); } protected virtual void VisitWhileStatement(WhileStatement whileStatement) { - _sb.Append("while("); + Append("while("); Visit(whileStatement.Test); - _sb.Append(")"); + Append(")"); Visit(whileStatement.Body); } protected virtual void VisitVariableDeclaration(VariableDeclaration variableDeclaration) { - _sb.Append(variableDeclaration.Kind.ToString().ToLower() + " "); + Append(variableDeclaration.Kind.ToString().ToLower() + " "); VisitNodeList(variableDeclaration.Declarations, appendSeperatorString: ","); } protected virtual void VisitTryStatement(TryStatement tryStatement) { - _sb.Append("try "); + Append("try "); Visit(tryStatement.Block); if (tryStatement.Handler != null) { - _sb.Append(" catch"); + Append(" catch"); Visit(tryStatement.Handler); } if (tryStatement.Finalizer != null) { - _sb.Append(" finally"); + Append(" finally"); Visit(tryStatement.Finalizer); } } protected virtual void VisitThrowStatement(ThrowStatement throwStatement) { - _sb.Append("throw "); + Append("throw "); Visit(throwStatement.Argument); - _sb.Append(";"); + Append(";"); } protected virtual void VisitSwitchStatement(SwitchStatement switchStatement) { - _sb.Append("switch("); + Append("switch("); Visit(switchStatement.Discriminant); - _sb.Append("){"); + Append("){"); VisitNodeList(switchStatement.Cases); - _sb.Append("}"); + Append("}"); } protected virtual void VisitSwitchCase(SwitchCase switchCase) { if (switchCase.Test != null) { - _sb.Append("case "); + Append("case "); Visit(switchCase.Test); } else { - _sb.Append("default"); + Append("default"); } - _sb.Append(":"); + Append(":"); VisitNodeList(switchCase.Consequent, appendAtEnd: ";"); } protected virtual void VisitReturnStatement(ReturnStatement returnStatement) { - _sb.Append("return"); + Append("return"); if (returnStatement.Argument != null) { - _sb.Append(" "); + Append(" "); Visit(returnStatement.Argument); } - _sb.Append(";"); + Append(";"); } protected virtual void VisitLabeledStatement(LabeledStatement labeledStatement) { Visit(labeledStatement.Label); - _sb.Append(":"); + Append(":"); Visit(labeledStatement.Body); } protected virtual void VisitIfStatement(IfStatement ifStatement) { - _sb.Append("if("); + Append("if"); + AppendBeautificationSpace(); + Append("("); Visit(ifStatement.Test); - _sb.Append(")"); + Append(")"); + AppendBeautificationSpace(); + + if (ifStatement.Consequent is not BlockStatement) + { + AppendNewline(); + IncreaseIndent(); + AppendIndent(); + } Visit(ifStatement.Consequent); if (NodeNeedsSemicolon(ifStatement.Consequent)) { - _sb.Append(";"); + Append(";"); + } + if (ifStatement.Consequent is not BlockStatement) + { + DecreaseIndent(); + if (ifStatement.Alternate != null) + { + AppendNewline(); + AppendIndent(); + } } if (ifStatement.Alternate != null) { - _sb.Append(" else "); + Append(" else "); + if (ifStatement.Alternate is not BlockStatement && ifStatement.Alternate is not IfStatement) + { + AppendNewline(); + IncreaseIndent(); + AppendIndent(); + } Visit(ifStatement.Alternate); if (NodeNeedsSemicolon(ifStatement.Alternate)) - _sb.Append(";"); + { + Append(";"); + } + if (ifStatement.Alternate is not BlockStatement && ifStatement.Alternate is not IfStatement) + { + DecreaseIndent(); + } } } protected virtual void VisitEmptyStatement(EmptyStatement emptyStatement) { - _sb.Append(";"); + Append(";"); } protected virtual void VisitDebuggerStatement(DebuggerStatement debuggerStatement) { - _sb.Append("debugger"); + Append("debugger"); } protected virtual void VisitExpressionStatement(ExpressionStatement expressionStatement) @@ -440,22 +514,22 @@ protected virtual void VisitExpressionStatement(ExpressionStatement expressionSt { if (ExpressionNeedsBrackets(callExpression.Callee)) { - _sb.Append("("); + Append("("); } Visit(callExpression.Callee); if (ExpressionNeedsBrackets(callExpression.Callee)) { - _sb.Append(")"); + Append(")"); } - _sb.Append("("); + Append("("); VisitNodeList(callExpression.Arguments, appendSeperatorString: ","); - _sb.Append(")"); + Append(")"); } else if (expressionStatement.Expression is ClassExpression) { - _sb.Append("("); + Append("("); Visit(expressionStatement.Expression); - _sb.Append(")"); + Append(")"); } else { @@ -465,61 +539,85 @@ protected virtual void VisitExpressionStatement(ExpressionStatement expressionSt protected virtual void VisitForStatement(ForStatement forStatement) { - _sb.Append("for("); + Append("for("); if (forStatement.Init != null) { Visit(forStatement.Init); } - _sb.Append(";"); + Append(";"); if (forStatement.Test != null) { Visit(forStatement.Test); } - _sb.Append(";"); + Append(";"); if (forStatement.Update != null) { Visit(forStatement.Update); } - _sb.Append(")"); + Append(")"); + AppendBeautificationSpace(); + + if (forStatement.Body is not BlockStatement) + { + AppendNewline(); + IncreaseIndent(); + AppendIndent(); + } Visit(forStatement.Body); if (NodeNeedsSemicolon(forStatement.Body)) { - _sb.Append(";"); + Append(";"); + } + if (forStatement.Body is not BlockStatement) + { + DecreaseIndent(); } } protected virtual void VisitForInStatement(ForInStatement forInStatement) { - _sb.Append("for("); + Append("for("); Visit(forInStatement.Left); - _sb.Append(" in "); + Append(" in "); Visit(forInStatement.Right); - _sb.Append(")"); + Append(")"); + AppendBeautificationSpace(); + + if (forInStatement.Body is not BlockStatement) + { + AppendNewline(); + IncreaseIndent(); + AppendIndent(); + } Visit(forInStatement.Body); if (NodeNeedsSemicolon(forInStatement.Body)) { - _sb.Append(";"); + Append(";"); + } + if (forInStatement.Body is not BlockStatement) + { + DecreaseIndent(); } } protected virtual void VisitDoWhileStatement(DoWhileStatement doWhileStatement) { - _sb.Append("do "); + Append("do "); Visit(doWhileStatement.Body); if (NodeNeedsSemicolon(doWhileStatement.Body)) { - _sb.Append(";"); + Append(";"); } - _sb.Append("while("); + Append("while("); Visit(doWhileStatement.Test); - _sb.Append(")"); + Append(")"); } protected virtual void VisitArrowFunctionExpression(ArrowFunctionExpression arrowFunctionExpression) { if (arrowFunctionExpression.Async) { - _sb.Append("async "); + Append("async "); } if (arrowFunctionExpression.Id != null) @@ -531,29 +629,29 @@ protected virtual void VisitArrowFunctionExpression(ArrowFunctionExpression arro { if (arrowFunctionExpression.Params[0] is RestElement || ExpressionNeedsBrackets(arrowFunctionExpression.Params[0])) { - _sb.Append("("); + Append("("); } Visit(arrowFunctionExpression.Params[0]); if (arrowFunctionExpression.Params[0] is RestElement || ExpressionNeedsBrackets(arrowFunctionExpression.Params[0])) { - _sb.Append(")"); + Append(")"); } } else { - _sb.Append("("); + Append("("); VisitNodeList(arrowFunctionExpression.Params, appendSeperatorString: ",", appendBracketsIfNeeded: true); ; - _sb.Append(")"); + Append(")"); } - _sb.Append("=>"); + Append("=>"); if (arrowFunctionExpression.Body is ObjectExpression || arrowFunctionExpression.Body is SequenceExpression) { - _sb.Append("("); + Append("("); } Visit(arrowFunctionExpression.Body); if (arrowFunctionExpression.Body is ObjectExpression || arrowFunctionExpression.Body is SequenceExpression) { - _sb.Append(")"); + Append(")"); } } @@ -562,22 +660,22 @@ protected virtual void VisitUnaryExpression(UnaryExpression unaryExpression) var op = UnaryExpression.ConvertUnaryOperator(unaryExpression.Operator); if (unaryExpression.Prefix) { - _sb.Append(op); + Append(op); if (char.IsLetter(op[0])) - _sb.Append(" "); + Append(" "); } if (!(unaryExpression.Argument is Literal) && !(unaryExpression.Argument is UnaryExpression)) { - _sb.Append("("); + Append("("); } Visit(unaryExpression.Argument); if (!(unaryExpression.Argument is Literal) && !(unaryExpression.Argument is UnaryExpression)) { - _sb.Append(")"); + Append(")"); } if (!unaryExpression.Prefix) { - _sb.Append(op); + Append(op); } } @@ -585,53 +683,65 @@ protected virtual void VisitUpdateExpression(UpdateExpression updateExpression) { if (updateExpression.Prefix) { - _sb.Append(UnaryExpression.ConvertUnaryOperator(updateExpression.Operator)); + Append(UnaryExpression.ConvertUnaryOperator(updateExpression.Operator)); } Visit(updateExpression.Argument); if (!updateExpression.Prefix) { - _sb.Append(UnaryExpression.ConvertUnaryOperator(updateExpression.Operator)); + Append(UnaryExpression.ConvertUnaryOperator(updateExpression.Operator)); } } protected virtual void VisitThisExpression(ThisExpression thisExpression) { - _sb.Append("this"); + Append("this"); } protected virtual void VisitSequenceExpression(SequenceExpression sequenceExpression) { - VisitNodeList(sequenceExpression.Expressions, appendSeperatorString: ","); + VisitNodeList(sequenceExpression.Expressions, appendSeperatorString: Beautify ? ", " : ","); } protected virtual void VisitObjectExpression(ObjectExpression objectExpression) { - _sb.Append("{"); - VisitNodeList(objectExpression.Properties, appendSeperatorString: ","); - _sb.Append("}"); + Append("{"); + if (objectExpression.Properties.Count > 0) + { + AppendNewline(); + IncreaseIndent(); + AppendIndent(); + } + VisitNodeList(objectExpression.Properties, appendSeperatorString: ",", addLineBreaks: true); + if (objectExpression.Properties.Count > 0) + { + AppendNewline(); + DecreaseIndent(); + AppendIndent(); + } + Append("}"); } protected virtual void VisitNewExpression(NewExpression newExpression) { - _sb.Append("new"); + Append("new"); if (ExpressionNeedsBrackets(newExpression.Callee)) { - _sb.Append("("); + Append("("); } else { - _sb.Append(" "); + Append(" "); } Visit(newExpression.Callee); if (ExpressionNeedsBrackets(newExpression.Callee)) { - _sb.Append(")"); + Append(")"); } if (newExpression.Arguments.Count > 0) { - _sb.Append("("); + Append("("); VisitNodeList(newExpression.Arguments, appendSeperatorString: ","); - _sb.Append(")"); + Append(")"); } } @@ -639,38 +749,38 @@ protected virtual void VisitMemberExpression(MemberExpression memberExpression) { if (ExpressionNeedsBrackets(memberExpression.Object) || (memberExpression.Object is Literal l && l.TokenType != TokenType.StringLiteral)) { - _sb.Append("("); + Append("("); } Visit(memberExpression.Object); if (ExpressionNeedsBrackets(memberExpression.Object) || (memberExpression.Object is Literal l2 && l2.TokenType != TokenType.StringLiteral)) { - _sb.Append(")"); + Append(")"); } if (memberExpression.Computed) { - _sb.Append("["); + Append("["); } else { if (TryGetParentAt(0) is ChainExpression) - _sb.Append("?"); - _sb.Append("."); + Append("?"); + Append("."); } Visit(memberExpression.Property); if (memberExpression.Computed) { - _sb.Append("]"); + Append("]"); } } protected virtual void VisitLiteral(Literal literal) { - _sb.Append(literal.Raw); + Append(literal.Raw); } protected virtual void VisitIdentifier(Identifier identifier) { - _sb.Append(identifier.Name); + Append(identifier.Name); } protected virtual void VisitFunctionExpression(IFunction function) @@ -680,48 +790,49 @@ protected virtual void VisitFunctionExpression(IFunction function) { if (function.Async) { - _sb.Append("async "); + Append("async "); } if (!(TryGetParentAt(1) is MethodDefinition)) { - _sb.Append("function"); + Append("function"); } if (function.Generator) { - _sb.Append("*"); + Append("*"); } } if (function.Id != null) { - _sb.Append(" "); + Append(" "); Visit(function.Id); } - _sb.Append("("); + Append("("); VisitNodeList(function.Params, appendSeperatorString: ","); - _sb.Append(")"); + Append(")"); + AppendBeautificationSpace(); Visit(function.Body); } protected virtual void VisitClassExpression(ClassExpression classExpression) { - _sb.Append("class "); + Append("class "); if (classExpression.Id != null) { Visit(classExpression.Id); } if (classExpression.SuperClass != null) { - _sb.Append(" extends "); + Append(" extends "); Visit(classExpression.SuperClass); } - _sb.Append("{"); + Append("{"); Visit(classExpression.Body); - _sb.Append("}"); + Append("}"); } protected virtual void VisitExportDefaultDeclaration(ExportDefaultDeclaration exportDefaultDeclaration) { - _sb.Append("export default "); + Append("export default "); if (exportDefaultDeclaration.Declaration != null) { Visit(exportDefaultDeclaration.Declaration); @@ -730,32 +841,32 @@ protected virtual void VisitExportDefaultDeclaration(ExportDefaultDeclaration ex protected virtual void VisitExportAllDeclaration(ExportAllDeclaration exportAllDeclaration) { - _sb.Append("export*from"); + Append("export*from"); Visit(exportAllDeclaration.Source); } protected virtual void VisitExportNamedDeclaration(ExportNamedDeclaration exportNamedDeclaration) { - _sb.Append("export"); + Append("export"); if (exportNamedDeclaration.Declaration != null) { - _sb.Append(" "); + Append(" "); Visit(exportNamedDeclaration.Declaration); } if (exportNamedDeclaration.Specifiers.Count > 0) { - _sb.Append("{"); + Append("{"); VisitNodeList(exportNamedDeclaration.Specifiers, appendSeperatorString: ","); - _sb.Append("}"); + Append("}"); } if (exportNamedDeclaration.Source != null) { - _sb.Append("from"); + Append("from"); Visit(exportNamedDeclaration.Source); } if (exportNamedDeclaration.Declaration == null && exportNamedDeclaration.Specifiers.Count == 0 && exportNamedDeclaration.Source == null) { - _sb.Append("{}"); + Append("{}"); } } @@ -765,37 +876,40 @@ protected virtual void VisitExportSpecifier(ExportSpecifier exportSpecifier) Visit(exportSpecifier.Local); if (exportSpecifier.Local != exportSpecifier.Exported) { - _sb.Append(" as "); + Append(" as "); Visit(exportSpecifier.Exported); } } protected virtual void VisitImport(Import import) { - _sb.Append("import("); + Append("import("); Visit(import.Source); - _sb.Append(")"); + Append(")"); } protected virtual void VisitImportDeclaration(ImportDeclaration importDeclaration) { - _sb.Append("import "); + Append("import "); var firstSpecifier = importDeclaration.Specifiers.FirstOrDefault(); if (firstSpecifier is ImportDefaultSpecifier) { Visit(firstSpecifier); if (importDeclaration.Specifiers.Count > 1) { - _sb.Append(","); + Append(","); + AppendBeautificationSpace(); if (importDeclaration.Specifiers[1] is ImportNamespaceSpecifier) { - VisitNodeList(importDeclaration.Specifiers.Skip(1), appendSeperatorString: ","); + VisitNodeList(importDeclaration.Specifiers.Skip(1), appendSeperatorString: Beautify ? ", " : ","); } else { - _sb.Append("{"); - VisitNodeList(importDeclaration.Specifiers.Skip(1), appendSeperatorString: ","); - _sb.Append("}"); + Append("{"); + AppendBeautificationSpace(); + VisitNodeList(importDeclaration.Specifiers.Skip(1), appendSeperatorString: Beautify ? ", " : ","); + AppendBeautificationSpace(); + Append("}"); } } } @@ -803,25 +917,27 @@ protected virtual void VisitImportDeclaration(ImportDeclaration importDeclaratio { if (importDeclaration.Specifiers[0] is ImportNamespaceSpecifier) { - VisitNodeList(importDeclaration.Specifiers, appendSeperatorString: ","); + VisitNodeList(importDeclaration.Specifiers, appendSeperatorString: Beautify ? ", " : ","); } else { - _sb.Append("{"); - VisitNodeList(importDeclaration.Specifiers, appendSeperatorString: ","); - _sb.Append("}"); + Append("{"); + AppendBeautificationSpace(); + VisitNodeList(importDeclaration.Specifiers, appendSeperatorString: Beautify ? ", " : ","); + AppendBeautificationSpace(); + Append("}"); } } if (importDeclaration.Specifiers.Count > 0) { - _sb.Append(" from "); + Append(" from "); } Visit(importDeclaration.Source); } protected virtual void VisitImportNamespaceSpecifier(ImportNamespaceSpecifier importNamespaceSpecifier) { - _sb.Append("* as "); + Append("* as "); Visit(importNamespaceSpecifier.Local); } @@ -835,7 +951,7 @@ protected virtual void VisitImportSpecifier(ImportSpecifier importSpecifier) Visit(importSpecifier.Imported); if (importSpecifier.Local != importSpecifier.Imported) { - _sb.Append(" as "); + Append(" as "); Visit(importSpecifier.Local); } } @@ -844,61 +960,73 @@ protected virtual void VisitMethodDefinition(MethodDefinition methodDefinition) { if (methodDefinition.Static) { - _sb.Append("static "); + Append("static "); } if (IsAsync(methodDefinition.Value)) { - _sb.Append("async "); + Append("async "); } if (methodDefinition.Value is FunctionExpression f && f.Generator) { - _sb.Append("*"); + Append("*"); } if (methodDefinition.Kind == PropertyKind.Get) { - _sb.Append("get "); + Append("get "); } else if (methodDefinition.Kind == PropertyKind.Set) { - _sb.Append("set "); + Append("set "); } if (methodDefinition.Key is MemberExpression || ExpressionNeedsBrackets(methodDefinition.Key)) { - _sb.Append("["); + Append("["); } if (ExpressionNeedsBrackets(methodDefinition.Key)) { - _sb.Append("("); + Append("("); } Visit(methodDefinition.Key); if (ExpressionNeedsBrackets(methodDefinition.Key)) { - _sb.Append(")"); + Append(")"); } if (methodDefinition.Key is MemberExpression || ExpressionNeedsBrackets(methodDefinition.Key)) { - _sb.Append("]"); + Append("]"); } Visit(methodDefinition.Value); } protected virtual void VisitForOfStatement(ForOfStatement forOfStatement) { - _sb.Append("for("); + Append("for("); Visit(forOfStatement.Left); - _sb.Append(" of "); + Append(" of "); Visit(forOfStatement.Right); - _sb.Append(")"); + Append(")"); + AppendBeautificationSpace(); + + if (forOfStatement.Body is not BlockStatement) + { + AppendNewline(); + IncreaseIndent(); + AppendIndent(); + } Visit(forOfStatement.Body); if (NodeNeedsSemicolon(forOfStatement.Body)) { - _sb.Append(";"); + Append(";"); + } + if (forOfStatement.Body is not BlockStatement) + { + DecreaseIndent(); } } protected virtual void VisitClassDeclaration(ClassDeclaration classDeclaration) { - _sb.Append("class "); + Append("class "); if (classDeclaration.Id != null) { Visit(classDeclaration.Id); @@ -906,22 +1034,34 @@ protected virtual void VisitClassDeclaration(ClassDeclaration classDeclaration) if (classDeclaration.SuperClass != null) { - _sb.Append(" extends "); + Append(" extends "); Visit(classDeclaration.SuperClass); } - _sb.Append("{"); + + AppendBeautificationSpace(); + Append("{"); + + AppendNewline(); + IncreaseIndent(); + AppendIndent(); + Visit(classDeclaration.Body); - _sb.Append("}"); + + AppendNewline(); + DecreaseIndent(); + AppendIndent(); + + Append("}"); } protected virtual void VisitClassBody(ClassBody classBody) { - VisitNodeList(classBody.Body); + VisitNodeList(classBody.Body, addLineBreaks: true); } protected virtual void VisitYieldExpression(YieldExpression yieldExpression) { - _sb.Append("yield "); + Append("yield "); if (yieldExpression.Argument != null) { Visit(yieldExpression.Argument); @@ -936,13 +1076,13 @@ protected virtual void VisitTaggedTemplateExpression(TaggedTemplateExpression ta protected virtual void VisitSuper(Super super) { - _sb.Append("super"); + Append("super"); } protected virtual void VisitMetaProperty(MetaProperty metaProperty) { Visit(metaProperty.Meta); - _sb.Append("."); + Append("."); Visit(metaProperty.Property); } @@ -953,29 +1093,29 @@ protected virtual void VisitArrowParameterPlaceHolder(ArrowParameterPlaceHolder protected virtual void VisitObjectPattern(ObjectPattern objectPattern) { - _sb.Append("{"); + Append("{"); VisitNodeList(objectPattern.Properties, appendSeperatorString: ","); - _sb.Append("}"); + Append("}"); } protected virtual void VisitSpreadElement(SpreadElement spreadElement) { - _sb.Append("..."); + Append("..."); Visit(spreadElement.Argument); } protected virtual void VisitAssignmentPattern(AssignmentPattern assignmentPattern) { Visit(assignmentPattern.Left); - _sb.Append("="); + Append("="); Visit(assignmentPattern.Right); } protected virtual void VisitArrayPattern(ArrayPattern arrayPattern) { - _sb.Append("["); + Append("["); VisitNodeList(arrayPattern.Elements, appendSeperatorString: ","); - _sb.Append("]"); + Append("]"); } protected virtual void VisitVariableDeclarator(VariableDeclarator variableDeclarator) @@ -983,43 +1123,45 @@ protected virtual void VisitVariableDeclarator(VariableDeclarator variableDeclar Visit(variableDeclarator.Id); if (variableDeclarator.Init != null) { - _sb.Append("="); + AppendBeautificationSpace(); + Append("="); + AppendBeautificationSpace(); if (ExpressionNeedsBrackets(variableDeclarator.Init)) { - _sb.Append("("); + Append("("); } Visit(variableDeclarator.Init); if (ExpressionNeedsBrackets(variableDeclarator.Init)) { - _sb.Append(")"); + Append(")"); } } } protected virtual void VisitTemplateLiteral(TemplateLiteral templateLiteral) { - _sb.Append("`"); + Append("`"); for (int n = 0; n < templateLiteral.Quasis.Count; n++) { Visit(templateLiteral.Quasis[n]); if (templateLiteral.Expressions.Count > n) { - _sb.Append("${"); + Append("${"); Visit(templateLiteral.Expressions[n]); - _sb.Append("}"); + Append("}"); } } - _sb.Append("`"); + Append("`"); } protected virtual void VisitTemplateElement(TemplateElement templateElement) { - _sb.Append(templateElement.Value.Raw); + Append(templateElement.Value.Raw); } protected virtual void VisitRestElement(RestElement restElement) { - _sb.Append("..."); + Append("..."); Visit(restElement.Argument); } @@ -1027,34 +1169,36 @@ protected virtual void VisitProperty(Property property) { if (property.Key is MemberExpression || ExpressionNeedsBrackets(property.Key)) { - _sb.Append("["); + Append("["); } if (ExpressionNeedsBrackets(property.Key)) { - _sb.Append("("); + Append("("); } Visit(property.Key); if (ExpressionNeedsBrackets(property.Key)) { - _sb.Append(")"); + Append(")"); } if (property.Key is MemberExpression || ExpressionNeedsBrackets(property.Key)) { - _sb.Append("]"); + Append("]"); } if (property.Key is Identifier keyI && property.Value is Identifier valueI && keyI.Name == valueI.Name) { } else { - _sb.Append(":"); + AppendBeautificationSpace(); + Append(":"); + AppendBeautificationSpace(); if (property.Value is not ObjectPattern && ExpressionNeedsBrackets(property.Value)) { - _sb.Append("("); + Append("("); } Visit(property.Value); if (property.Value is not ObjectPattern && ExpressionNeedsBrackets(property.Value)) { - _sb.Append(")"); + Append(")"); } } } @@ -1063,36 +1207,36 @@ protected virtual void VisitPropertyDefinition(PropertyDefinition propertyDefini { if (propertyDefinition.Static) { - _sb.Append("static "); + Append("static "); } if (propertyDefinition.Key is MemberExpression || ExpressionNeedsBrackets(propertyDefinition.Key)) { - _sb.Append("["); + Append("["); } if (ExpressionNeedsBrackets(propertyDefinition.Key)) { - _sb.Append("("); + Append("("); } Visit(propertyDefinition.Key); if (ExpressionNeedsBrackets(propertyDefinition.Key)) { - _sb.Append(")"); + Append(")"); } if (propertyDefinition.Key is MemberExpression || ExpressionNeedsBrackets(propertyDefinition.Key)) { - _sb.Append("]"); + Append("]"); } if (propertyDefinition.Value != null) { - _sb.Append("="); + Append("="); Visit(propertyDefinition.Value); } - _sb.Append(";"); + Append(";"); } protected virtual void VisitAwaitExpression(AwaitExpression awaitExpression) { - _sb.Append("await "); + Append("await "); Visit(awaitExpression.Argument); } @@ -1100,32 +1244,32 @@ protected virtual void VisitConditionalExpression(ConditionalExpression conditio { if (conditionalExpression.Test is AssignmentExpression) { - _sb.Append("("); + Append("("); } Visit(conditionalExpression.Test); if (conditionalExpression.Test is AssignmentExpression) { - _sb.Append(")"); + Append(")"); } - _sb.Append("?"); + Append("?"); if (ExpressionNeedsBrackets(conditionalExpression.Consequent)) { - _sb.Append("("); + Append("("); } Visit(conditionalExpression.Consequent); if (ExpressionNeedsBrackets(conditionalExpression.Consequent)) { - _sb.Append(")"); + Append(")"); } - _sb.Append(":"); + Append(":"); if (ExpressionNeedsBrackets(conditionalExpression.Alternate)) { - _sb.Append("("); + Append("("); } Visit(conditionalExpression.Alternate); if (ExpressionNeedsBrackets(conditionalExpression.Alternate)) { - _sb.Append(")"); + Append(")"); } } @@ -1133,84 +1277,94 @@ protected virtual void VisitCallExpression(CallExpression callExpression) { if (ExpressionNeedsBrackets(callExpression.Callee)) { - _sb.Append("("); + Append("("); } Visit(callExpression.Callee); if (ExpressionNeedsBrackets(callExpression.Callee)) { - _sb.Append(")"); + Append(")"); } - _sb.Append("("); + Append("("); VisitNodeList(callExpression.Arguments, appendSeperatorString: ",", appendBracketsIfNeeded: true); - _sb.Append(")"); + Append(")"); } protected virtual void VisitBinaryExpression(BinaryExpression binaryExpression) { if (ExpressionNeedsBrackets(binaryExpression.Left)) { - _sb.Append("("); + Append("("); } Visit(binaryExpression.Left); if (ExpressionNeedsBrackets(binaryExpression.Left)) { - _sb.Append(")"); + Append(")"); } var op = BinaryExpression.ConvertBinaryOperator(binaryExpression.Operator); if (char.IsLetter(op[0])) { - _sb.Append(" "); + Append(" "); + } + else + { + AppendBeautificationSpace(); } - _sb.Append(op); + Append(op); if (char.IsLetter(op[0])) { - _sb.Append(" "); + Append(" "); + } + else + { + AppendBeautificationSpace(); } if (ExpressionNeedsBrackets(binaryExpression.Right)) { - _sb.Append("("); + Append("("); } Visit(binaryExpression.Right); if (ExpressionNeedsBrackets(binaryExpression.Right)) { - _sb.Append(")"); + Append(")"); } } protected virtual void VisitArrayExpression(ArrayExpression arrayExpression) { - _sb.Append("["); + Append("["); VisitNodeList(arrayExpression.Elements, appendSeperatorString: ","); - _sb.Append("]"); + Append("]"); } protected virtual void VisitAssignmentExpression(AssignmentExpression assignmentExpression) { if (assignmentExpression.Left is ObjectPattern) { - _sb.Append("("); + Append("("); } var op = AssignmentExpression.ConvertAssignmentOperator(assignmentExpression.Operator); Visit(assignmentExpression.Left); - _sb.Append(op); + AppendBeautificationSpace(); + Append(op); + AppendBeautificationSpace(); if (ExpressionNeedsBrackets(assignmentExpression.Right) && !(assignmentExpression.Right is AssignmentExpression)) { - _sb.Append("("); + Append("("); } Visit(assignmentExpression.Right); if (ExpressionNeedsBrackets(assignmentExpression.Right) && !(assignmentExpression.Right is AssignmentExpression)) { - _sb.Append(")"); + Append(")"); } if (assignmentExpression.Left is ObjectPattern) { - _sb.Append(")"); + Append(")"); } } protected virtual void VisitContinueStatement(ContinueStatement continueStatement) { - _sb.Append("continue "); + Append("continue "); if (continueStatement.Label != null) { Visit(continueStatement.Label); @@ -1223,18 +1377,28 @@ protected virtual void VisitBreakStatement(BreakStatement breakStatement) { Visit(breakStatement.Label); } - _sb.Append("break"); + Append("break"); } protected virtual void VisitBlockStatement(BlockStatement blockStatement) { - _sb.Append("{"); - VisitNodeList(blockStatement.Body, appendAtEnd: ";"); - _sb.Append("}"); + Append("{"); + + AppendNewline(); + IncreaseIndent(); + AppendIndent(); + + VisitNodeList(blockStatement.Body, appendAtEnd: ";", addLineBreaks: true); + + AppendNewline(); + DecreaseIndent(); + AppendIndent(); + + Append("}"); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void VisitNodeList(IEnumerable nodeList, string appendAtEnd = null, string appendSeperatorString = null, bool appendBracketsIfNeeded = false) + private void VisitNodeList(IEnumerable nodeList, string appendAtEnd = null, string appendSeperatorString = null, bool appendBracketsIfNeeded = false, bool addLineBreaks = false) where TNode : Node { var notfirst = false; @@ -1242,23 +1406,29 @@ private void VisitNodeList(IEnumerable nodeList, string appendAtEn { if (node != null) { + if (notfirst && addLineBreaks) + { + AppendNewline(); + AppendIndent(); + } + if (notfirst && appendSeperatorString != null) { - _sb.Append(appendSeperatorString); + Append(appendSeperatorString); } if (appendBracketsIfNeeded && ExpressionNeedsBrackets(node)) { - _sb.Append("("); + Append("("); } Visit(node); if (appendBracketsIfNeeded && ExpressionNeedsBrackets(node)) { - _sb.Append(")"); + Append(")"); } notfirst = true; if (appendAtEnd != null && NodeNeedsSemicolon(node)) { - _sb.Append(appendAtEnd); + Append(appendAtEnd); } } } diff --git a/test/Esprima.Tests/JavascriptTest.cs b/test/Esprima.Tests/JavascriptTest.cs index 37dc4017..24366e2c 100644 --- a/test/Esprima.Tests/JavascriptTest.cs +++ b/test/Esprima.Tests/JavascriptTest.cs @@ -1,4 +1,6 @@ -using Esprima.Utils; +using System; +using System.Text.RegularExpressions; +using Esprima.Utils; using Xunit; namespace Esprima.Tests @@ -46,6 +48,7 @@ function printTips() }"); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("let tips=[\"Click on any AST node with a '+' to expand it\",\"Hovering over a node highlights the \\\r\n corresponding location in the source code\",\"Shift click on an AST node to expand the whole subtree\"];function printTips(){tips.forEach((tip,i)=>console.log((`Tip ${i}:`+tip)));}", code); } [Fact] @@ -63,12 +66,13 @@ static get is() { }"); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("export class aa extends HTMLElement{constructor(a,b){super(a);this._div=(document.createElement('div'));}static get is(){return 'aa';}}", code); } [Fact] public void ToJavascriptTest4() { - var parser = new JavaScriptParser(@"import { MccDialog } from '../mccDialogHandler'; + var source = @"import { MccDialog } from '../mccDialogHandler'; import { commonClient, bb as f } from '../commonClient/commonClient'; import ii, { hh, jj } from '../commonClient/commonClient'; import '../commonClient/commonClient'; @@ -121,9 +125,52 @@ export function checkSecurityAnswerCodeDirect(result) { return false; } } -}"); +}"; + source = Regex.Replace(source, @"\r\n|\n\r|\n|\r", Environment.NewLine); + var parser = new JavaScriptParser(source); var program = parser.ParseScript(); - var code = ToJavascriptConverter.ToJavascript(program); + var code = ToJavascriptConverter.ToJavascript(program, true); + + var expected = @"import { MccDialog } from '../mccDialogHandler'; +import { commonClient, bb as f } from '../commonClient/commonClient'; +import ii, { hh, jj } from '../commonClient/commonClient'; +import '../commonClient/commonClient'; +import aa from 'module-name'; +import zz, * as ff from 'module-name'; +import * as name from 'module-name'; +import('qq'); +a++; +--a; +export function checkSecurityAnswerCodeDirect(result) { + if (!(result)) { + MccDialog.warning({ + title : 'SecurityClientErrorOccured' + ,message : '

internal error, check console

' + }); + return false; + } + switch(result.SecurityAnswerCode){case 'Allowed':return true;case 'Exception':MccDialog.warning({ + title : 'SecurityClientInfoTitle' + ,message : ((('

SecurityClientExceptionOccured

Exception: ' + result.Message) + '

') + result.StackTrace) + });return false;case 'Error':MccDialog.warning({ + title : 'SecurityClientErrorOccured' + ,message : ((((('

' + (commonClient.getTranslation('SecurityClientMessage'))) + ': ') + (commonClient.getTranslation(result.Message))) + '

') + (result.MessageDetails?(('

SecurityClientDetails: ' + result.MessageDetails) + '

'):' ')) + });return false;default:{ + let messagesnippet = (('

SecurityClient_' + result.SecurityAnswerCode) + '

'); + if ((result.Message !== undefined) && (result.SecurityAnswerCode === 'LoginFailed')) { + messagesnippet += (('\n\nSecurityClient_InternalServerErrorMessage\n' + result.Message) + ''); + } + if (result.Role) { + messagesnippet += (((('

SecurityClient_CheckedRole' + ' [') + result.Role) + ']') + '

'); + } + MccDialog.warning({ + title : 'SecurityClientInfoTitle' + ,message : messagesnippet + }); + return false; + }} +}"; + Assert.Equal(expected, code); } [Fact] @@ -264,8 +311,7 @@ public void ToJavascriptTest13() [Fact] public void ToJavascriptTest14() { - var parser = new JavaScriptParser(@" -function tt(t, r) { + var source = @"function tt(t, r) { var n, e, i = b(t), s = b(r); if (s && (e = ft(r)), i); @@ -274,9 +320,25 @@ function tt(t, r) { for (f = t.length < r.length ? t.length : r.length, o = 0, g = 0; f > g; g++) o += t[g] + r[g], t[g] = o & _t, o >>= at; for (g = f; o && g < t.length; g++) o += t[g], t[g] = o & _t, o >>= at } -"); +"; + source = Regex.Replace(source, @"\r\n|\n\r|\n|\r", Environment.NewLine); + var parser = new JavaScriptParser(source); var program = parser.ParseScript(); - var code = ToJavascriptConverter.ToJavascript(program); + var code = ToJavascriptConverter.ToJavascript(program, true); + + var expected = @"function tt(t,r) { + var n,e,i = (b(t)),s = (b(r)); + if (s && (e = (ft(r))), i) + ; + else if (s) + return D(t,e)?(void ($(t,e))):(n = (l(e,t)), G(t,n), void (ht(t))); + var g,o,f; + for(f = (t.length < r.length?t.length:r.length), o = 0, g = 0;f > g;g++) + o += (t[g] + r[g]), t[g] = (o & _t), o >>= at; + for(g = f;o && (g < t.length);g++) + o += t[g], t[g] = (o & _t), o >>= at; +}"; + Assert.Equal(expected, code); } [Fact] @@ -287,6 +349,7 @@ public void ToJavascriptTest15() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("h=('M'+((+(new Date)).toString(36)));", code); } [Fact] @@ -301,6 +364,7 @@ public void ToJavascriptTest16() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("input.onchange=(async e=>{const files=await readFiles(input.files,readMode);document.body.removeChild(input);resolve(files);});", code); } [Fact] @@ -311,6 +375,7 @@ public void ToJavascriptTest17() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("export const Base=(LegacyElementMixin(HTMLElement)).prototype;", code); } [Fact] @@ -321,6 +386,7 @@ public void ToJavascriptTest18() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("let {is}=(getIsExtends(element));", code); } [Fact] @@ -332,6 +398,7 @@ public void ToJavascriptTest19() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("export const wrap=((window['ShadyDOM']&&window['ShadyDOM']['wrap'])||(node=>node));", code); } [Fact] @@ -341,6 +408,7 @@ public void ToJavascriptTest20() export {}"); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("export{};", code); } [Fact] @@ -353,6 +421,7 @@ public void ToJavascriptTest21() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("(()=>{mutablePropertyChange=MutableData._mutablePropertyChange;})();", code); } [Fact] @@ -366,6 +435,7 @@ public void ToJavascriptTest22() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("var Ol,jl=(new((function(){var l,h,z;return l=c;})()));", code); } [Fact] @@ -382,12 +452,13 @@ public void ToJavascriptTest23() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("[y,{[Symbol.iterator]:(function(){return b;}),a:5}];", code); } [Fact] public void ToJavascriptTest24() { - var parser = new JavaScriptParser(@" + var source = @" class A { *[Symbol.iterator]() { @@ -398,16 +469,26 @@ class A { } } -"); +"; + source = Regex.Replace(source, @"\r\n|\n\r|\n|\r", Environment.NewLine); + var parser = new JavaScriptParser(source); var program = parser.ParseScript(); - var code = ToJavascriptConverter.ToJavascript(program); + var code = ToJavascriptConverter.ToJavascript(program, true); + + var expected = @"class A { + *[Symbol.iterator]() { + let L = this._first; + for(;L !== _.Undefined;) + yield L.element, L = L.next; + } +}"; + Assert.Equal(expected, code); } [Fact] public void ToJavascriptTest25() { - var parser = new JavaScriptParser(@" -var i = function e(i) { + var source = @"var i = function e(i) { var r = n[i]; if (void 0 !== r) return r.exports; @@ -417,9 +498,44 @@ public void ToJavascriptTest25() return t[i](a, a.exports, e), a.exports }(15); -"); +"; + source = Regex.Replace(source, @"\r\n|\n\r|\n|\r", Environment.NewLine); + var parser = new JavaScriptParser(source); var program = parser.ParseScript(); - var code = ToJavascriptConverter.ToJavascript(program); + var code = ToJavascriptConverter.ToJavascript(program, true); + + var expected = @"var i = ((function e(i) { + var r = n[i]; + if ((void 0) !== r) + return r.exports; + var a = (n[i] = { + exports : {} + }); + return t[i](a,a.exports,e), a.exports; +})(15));"; + Assert.Equal(expected, code); + } + + [Fact] + public void ToJavascriptTest26() + { + var source = @"class A { + aa() { + let a = 1; + } +} +var b = 1; +var c; +if (b == 2) { + c = 1; +} else { + c = 3; +}"; + source = Regex.Replace(source, @"\r\n|\n\r|\n|\r", Environment.NewLine); + var parser = new JavaScriptParser(source); + var program = parser.ParseScript(); + var code = ToJavascriptConverter.ToJavascript(program, true); + Assert.Equal(source, code); } } } From dbbba8085a7cfdec099975e940db156b6b0642b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Tue, 9 Nov 2021 23:14:08 +0100 Subject: [PATCH 06/10] more tests, nicer code --- src/Esprima/Utils/ToJavascriptConverter.cs | 33 ++++++-- test/Esprima.Tests/JavascriptTest.cs | 88 +++++++++++++++------- 2 files changed, 85 insertions(+), 36 deletions(-) diff --git a/src/Esprima/Utils/ToJavascriptConverter.cs b/src/Esprima/Utils/ToJavascriptConverter.cs index 8afadd69..901b0b7d 100644 --- a/src/Esprima/Utils/ToJavascriptConverter.cs +++ b/src/Esprima/Utils/ToJavascriptConverter.cs @@ -409,8 +409,20 @@ protected virtual void VisitSwitchStatement(SwitchStatement switchStatement) { Append("switch("); Visit(switchStatement.Discriminant); - Append("){"); - VisitNodeList(switchStatement.Cases); + Append(")"); + AppendBeautificationSpace(); + Append("{"); + + AppendNewline(); + IncreaseIndent(); + AppendIndent(); + + VisitNodeList(switchStatement.Cases, addLineBreaks: true); + + AppendNewline(); + DecreaseIndent(); + AppendIndent(); + Append("}"); } @@ -427,7 +439,13 @@ protected virtual void VisitSwitchCase(SwitchCase switchCase) } Append(":"); - VisitNodeList(switchCase.Consequent, appendAtEnd: ";"); + AppendNewline(); + IncreaseIndent(); + AppendIndent(); + + VisitNodeList(switchCase.Consequent, appendAtEnd: ";", addLineBreaks: true); + + DecreaseIndent(); } protected virtual void VisitReturnStatement(ReturnStatement returnStatement) @@ -1406,16 +1424,15 @@ private void VisitNodeList(IEnumerable nodeList, string appendAtEn { if (node != null) { + if (notfirst && appendSeperatorString != null) + { + Append(appendSeperatorString); + } if (notfirst && addLineBreaks) { AppendNewline(); AppendIndent(); } - - if (notfirst && appendSeperatorString != null) - { - Append(appendSeperatorString); - } if (appendBracketsIfNeeded && ExpressionNeedsBrackets(node)) { Append("("); diff --git a/test/Esprima.Tests/JavascriptTest.cs b/test/Esprima.Tests/JavascriptTest.cs index 24366e2c..707322db 100644 --- a/test/Esprima.Tests/JavascriptTest.cs +++ b/test/Esprima.Tests/JavascriptTest.cs @@ -130,7 +130,7 @@ export function checkSecurityAnswerCodeDirect(result) { var parser = new JavaScriptParser(source); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program, true); - + var expected = @"import { MccDialog } from '../mccDialogHandler'; import { commonClient, bb as f } from '../commonClient/commonClient'; import ii, { hh, jj } from '../commonClient/commonClient'; @@ -144,31 +144,42 @@ export function checkSecurityAnswerCodeDirect(result) { export function checkSecurityAnswerCodeDirect(result) { if (!(result)) { MccDialog.warning({ - title : 'SecurityClientErrorOccured' - ,message : '

internal error, check console

' + title : 'SecurityClientErrorOccured', + message : '

internal error, check console

' }); return false; } - switch(result.SecurityAnswerCode){case 'Allowed':return true;case 'Exception':MccDialog.warning({ - title : 'SecurityClientInfoTitle' - ,message : ((('

SecurityClientExceptionOccured

Exception: ' + result.Message) + '

') + result.StackTrace) - });return false;case 'Error':MccDialog.warning({ - title : 'SecurityClientErrorOccured' - ,message : ((((('

' + (commonClient.getTranslation('SecurityClientMessage'))) + ': ') + (commonClient.getTranslation(result.Message))) + '

') + (result.MessageDetails?(('

SecurityClientDetails: ' + result.MessageDetails) + '

'):' ')) - });return false;default:{ - let messagesnippet = (('

SecurityClient_' + result.SecurityAnswerCode) + '

'); - if ((result.Message !== undefined) && (result.SecurityAnswerCode === 'LoginFailed')) { - messagesnippet += (('\n\nSecurityClient_InternalServerErrorMessage\n' + result.Message) + ''); - } - if (result.Role) { - messagesnippet += (((('

SecurityClient_CheckedRole' + ' [') + result.Role) + ']') + '

'); - } - MccDialog.warning({ - title : 'SecurityClientInfoTitle' - ,message : messagesnippet - }); - return false; - }} + switch(result.SecurityAnswerCode) { + case 'Allowed': + return true; + case 'Exception': + MccDialog.warning({ + title : 'SecurityClientInfoTitle', + message : ((('

SecurityClientExceptionOccured

Exception: ' + result.Message) + '

') + result.StackTrace) + }); + return false; + case 'Error': + MccDialog.warning({ + title : 'SecurityClientErrorOccured', + message : ((((('

' + (commonClient.getTranslation('SecurityClientMessage'))) + ': ') + (commonClient.getTranslation(result.Message))) + '

') + (result.MessageDetails?(('

SecurityClientDetails: ' + result.MessageDetails) + '

'):' ')) + }); + return false; + default: + { + let messagesnippet = (('

SecurityClient_' + result.SecurityAnswerCode) + '

'); + if ((result.Message !== undefined) && (result.SecurityAnswerCode === 'LoginFailed')) { + messagesnippet += (('\n\nSecurityClient_InternalServerErrorMessage\n' + result.Message) + ''); + } + if (result.Role) { + messagesnippet += (((('

SecurityClient_CheckedRole' + ' [') + result.Role) + ']') + '

'); + } + MccDialog.warning({ + title : 'SecurityClientInfoTitle', + message : messagesnippet + }); + return false; + } + } }"; Assert.Equal(expected, code); } @@ -176,7 +187,7 @@ export function checkSecurityAnswerCodeDirect(result) { [Fact] public void ToJavascriptTest5() { - var parser = new JavaScriptParser(@"(function () { + var source = @"(function () { 'use strict'; })(); @@ -194,21 +205,40 @@ public void ToJavascriptTest5() aa({}); -(function aa(){});"); +(function aa(){});"; + source = Regex.Replace(source, @"\r\n|\n\r|\n|\r", Environment.NewLine); + var parser = new JavaScriptParser(source); var program = parser.ParseScript(); - var code = ToJavascriptConverter.ToJavascript(program); + var code = ToJavascriptConverter.ToJavascript(program, true); + + var expected = @"(function() { + 'use strict'; +})(); +(class ApplyShimInterface{constructor() { + this.customStyleInterface = null; + applyShim['invalidCallback'] = ApplyShimUtils.invalidate; +}}); +a(); +aa({}); +function aa() { + +};"; + Assert.Equal(expected, code); } [Fact] public void ToJavascriptTest6() { - var parser = new JavaScriptParser(@"function _createClass(Constructor, protoProps, staticProps) { + var source = @"function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; - }"); + }"; + source = Regex.Replace(source, @"\r\n|\n\r|\n|\r", Environment.NewLine); + var parser = new JavaScriptParser(source); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}", code); } [Fact] @@ -219,6 +249,7 @@ public void ToJavascriptTest7() }"); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("if(((x?((a.nodeName.toLowerCase())===f):(1===a.nodeType))&&(++d))&&(p&&((i=((o=(a[S]||(a[S]={})))[a.uniqueID]||(o[a.uniqueID]={})))[h]=[k,d]),a===e)){}", code); } [Fact] @@ -237,6 +268,7 @@ class a extends b { "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("class a extends b{constructor(){super();this.g=1;}q=1;r='cc';}", code); } [Fact] From db00bc8a10206b3da755be28c4e69cd69aaf7e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Tue, 9 Nov 2021 23:23:05 +0100 Subject: [PATCH 07/10] bugfix rest of tests --- test/Esprima.Tests/JavascriptTest.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/Esprima.Tests/JavascriptTest.cs b/test/Esprima.Tests/JavascriptTest.cs index 707322db..73532563 100644 --- a/test/Esprima.Tests/JavascriptTest.cs +++ b/test/Esprima.Tests/JavascriptTest.cs @@ -279,6 +279,7 @@ public void ToJavascriptTest9() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("d=((s=(((r=((i=((o=((a=c)[S]||(a[S]={})))[a.uniqueID]||(o[a.uniqueID]={})))[h]||[]))[0]===k)&&r[1]))&&r[2]),a=(s&&c.childNodes[s]);", code); } [Fact] @@ -289,6 +290,7 @@ public void ToJavascriptTest10() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("m=(z.document,(((!!(v.documentElement))&&(!!(v.head)))&&('function'==(typeof (v.addEventListener))))&&v.createElement,(~(a.indexOf('MSIE')))||(a.indexOf('Trident/')),'___FONT_AWESOME___');", code); } [Fact] @@ -310,6 +312,7 @@ public void ToJavascriptTest11() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("var h=(c.navigator||{}).userAgent,a=((void 0)===h?'':h),z=c,v=l,m=(z.document,(((!!(v.documentElement))&&(!!(v.head)))&&('function'==(typeof (v.addEventListener))))&&v.createElement,(~(a.indexOf('MSIE')))||(a.indexOf('Trident/')),'___FONT_AWESOME___'),e=((function(){try {return !0;} catch(c){return !1;}})());", code); } [Fact] @@ -322,6 +325,7 @@ public void ToJavascriptTest12() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("var a={children:(b=O,'g'===b.tag?b.children:[b])};", code); } [Fact] @@ -338,6 +342,7 @@ public void ToJavascriptTest13() "); var program = parser.ParseScript(); var code = ToJavascriptConverter.ToJavascript(program); + Assert.Equal("if(e.IsWebService)if(h=e.HttpRequest.responseXML,'undefined'==(typeof (h)))Trace.Write((('Error: '+e.UniqueId)+' data has no properties!')),m=(!0); else try {h.setProperty('SelectionLanguage','XPath');} catch(l){Trace.Write('Error: data.setProperty(',SelectionLanguage,', ',XPath,') because '+l.message);} else h=e.HttpRequest.responseText;", code); } [Fact] From aee97292ad30fe3538ff4cb2193738a50e9be36d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Wed, 10 Nov 2021 07:21:14 +0100 Subject: [PATCH 08/10] bugfx test, add newline type --- src/Esprima/Utils/ToJavascriptConverter.cs | 72 +++++++++++----------- test/Esprima.Tests/JavascriptTest.cs | 5 ++ 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/Esprima/Utils/ToJavascriptConverter.cs b/src/Esprima/Utils/ToJavascriptConverter.cs index 901b0b7d..12f5009e 100644 --- a/src/Esprima/Utils/ToJavascriptConverter.cs +++ b/src/Esprima/Utils/ToJavascriptConverter.cs @@ -28,6 +28,8 @@ public static string ToJavascript(Node node, bool beautify = false) public int IndentionSize { get; set; } = 4; + public string NewlineFormat { get; set; } = Environment.NewLine; + protected StringBuilder _sb = new StringBuilder(); private int _indentionLevel = 0; @@ -47,7 +49,7 @@ private void AppendBeautificationSpace() } } - private void AppendIndent() + private void AppendBeautificationIndent() { if (Beautify) { @@ -55,11 +57,11 @@ private void AppendIndent() } } - private void AppendNewline() + private void AppendBeautificationNewline() { if (Beautify) { - _sb.AppendLine(); + _sb.Append(NewlineFormat); } } @@ -413,15 +415,15 @@ protected virtual void VisitSwitchStatement(SwitchStatement switchStatement) AppendBeautificationSpace(); Append("{"); - AppendNewline(); + AppendBeautificationNewline(); IncreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); VisitNodeList(switchStatement.Cases, addLineBreaks: true); - AppendNewline(); + AppendBeautificationNewline(); DecreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); Append("}"); } @@ -439,9 +441,9 @@ protected virtual void VisitSwitchCase(SwitchCase switchCase) } Append(":"); - AppendNewline(); + AppendBeautificationNewline(); IncreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); VisitNodeList(switchCase.Consequent, appendAtEnd: ";", addLineBreaks: true); @@ -477,9 +479,9 @@ protected virtual void VisitIfStatement(IfStatement ifStatement) if (ifStatement.Consequent is not BlockStatement) { - AppendNewline(); + AppendBeautificationNewline(); IncreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); } Visit(ifStatement.Consequent); if (NodeNeedsSemicolon(ifStatement.Consequent)) @@ -491,8 +493,8 @@ protected virtual void VisitIfStatement(IfStatement ifStatement) DecreaseIndent(); if (ifStatement.Alternate != null) { - AppendNewline(); - AppendIndent(); + AppendBeautificationNewline(); + AppendBeautificationIndent(); } } if (ifStatement.Alternate != null) @@ -500,9 +502,9 @@ protected virtual void VisitIfStatement(IfStatement ifStatement) Append(" else "); if (ifStatement.Alternate is not BlockStatement && ifStatement.Alternate is not IfStatement) { - AppendNewline(); + AppendBeautificationNewline(); IncreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); } Visit(ifStatement.Alternate); if (NodeNeedsSemicolon(ifStatement.Alternate)) @@ -577,9 +579,9 @@ protected virtual void VisitForStatement(ForStatement forStatement) if (forStatement.Body is not BlockStatement) { - AppendNewline(); + AppendBeautificationNewline(); IncreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); } Visit(forStatement.Body); if (NodeNeedsSemicolon(forStatement.Body)) @@ -603,9 +605,9 @@ protected virtual void VisitForInStatement(ForInStatement forInStatement) if (forInStatement.Body is not BlockStatement) { - AppendNewline(); + AppendBeautificationNewline(); IncreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); } Visit(forInStatement.Body); if (NodeNeedsSemicolon(forInStatement.Body)) @@ -725,16 +727,16 @@ protected virtual void VisitObjectExpression(ObjectExpression objectExpression) Append("{"); if (objectExpression.Properties.Count > 0) { - AppendNewline(); + AppendBeautificationNewline(); IncreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); } VisitNodeList(objectExpression.Properties, appendSeperatorString: ",", addLineBreaks: true); if (objectExpression.Properties.Count > 0) { - AppendNewline(); + AppendBeautificationNewline(); DecreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); } Append("}"); } @@ -1027,9 +1029,9 @@ protected virtual void VisitForOfStatement(ForOfStatement forOfStatement) if (forOfStatement.Body is not BlockStatement) { - AppendNewline(); + AppendBeautificationNewline(); IncreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); } Visit(forOfStatement.Body); if (NodeNeedsSemicolon(forOfStatement.Body)) @@ -1059,15 +1061,15 @@ protected virtual void VisitClassDeclaration(ClassDeclaration classDeclaration) AppendBeautificationSpace(); Append("{"); - AppendNewline(); + AppendBeautificationNewline(); IncreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); Visit(classDeclaration.Body); - AppendNewline(); + AppendBeautificationNewline(); DecreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); Append("}"); } @@ -1402,15 +1404,15 @@ protected virtual void VisitBlockStatement(BlockStatement blockStatement) { Append("{"); - AppendNewline(); + AppendBeautificationNewline(); IncreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); VisitNodeList(blockStatement.Body, appendAtEnd: ";", addLineBreaks: true); - AppendNewline(); + AppendBeautificationNewline(); DecreaseIndent(); - AppendIndent(); + AppendBeautificationIndent(); Append("}"); } @@ -1430,8 +1432,8 @@ private void VisitNodeList(IEnumerable nodeList, string appendAtEn } if (notfirst && addLineBreaks) { - AppendNewline(); - AppendIndent(); + AppendBeautificationNewline(); + AppendBeautificationIndent(); } if (appendBracketsIfNeeded && ExpressionNeedsBrackets(node)) { diff --git a/test/Esprima.Tests/JavascriptTest.cs b/test/Esprima.Tests/JavascriptTest.cs index 73532563..15fd2357 100644 --- a/test/Esprima.Tests/JavascriptTest.cs +++ b/test/Esprima.Tests/JavascriptTest.cs @@ -181,6 +181,7 @@ export function checkSecurityAnswerCodeDirect(result) { } } }"; + expected = Regex.Replace(expected, @"\r\n|\n\r|\n|\r", Environment.NewLine); Assert.Equal(expected, code); } @@ -223,6 +224,7 @@ public void ToJavascriptTest5() function aa() { };"; + expected = Regex.Replace(expected, @"\r\n|\n\r|\n|\r", Environment.NewLine); Assert.Equal(expected, code); } @@ -375,6 +377,7 @@ public void ToJavascriptTest14() for(g = f;o && (g < t.length);g++) o += t[g], t[g] = (o & _t), o >>= at; }"; + expected = Regex.Replace(expected, @"\r\n|\n\r|\n|\r", Environment.NewLine); Assert.Equal(expected, code); } @@ -519,6 +522,7 @@ class A { yield L.element, L = L.next; } }"; + expected = Regex.Replace(expected, @"\r\n|\n\r|\n|\r", Environment.NewLine); Assert.Equal(expected, code); } @@ -550,6 +554,7 @@ public void ToJavascriptTest25() }); return t[i](a,a.exports,e), a.exports; })(15));"; + expected = Regex.Replace(expected, @"\r\n|\n\r|\n|\r", Environment.NewLine); Assert.Equal(expected, code); } From fe88dce55dee8801247d06a6ed1c2ee7b4ccddbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Wed, 10 Nov 2021 07:39:57 +0100 Subject: [PATCH 09/10] bugfix function expression --- src/Esprima/Utils/ToJavascriptConverter.cs | 20 ++++++++++++++++++++ test/Esprima.Tests/JavascriptTest.cs | 14 ++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/Esprima/Utils/ToJavascriptConverter.cs b/src/Esprima/Utils/ToJavascriptConverter.cs index 12f5009e..180330c6 100644 --- a/src/Esprima/Utils/ToJavascriptConverter.cs +++ b/src/Esprima/Utils/ToJavascriptConverter.cs @@ -553,7 +553,15 @@ protected virtual void VisitExpressionStatement(ExpressionStatement expressionSt } else { + if (expressionStatement.Expression is FunctionExpression) + { + Append("("); + } Visit(expressionStatement.Expression); + if (expressionStatement.Expression is FunctionExpression) + { + Append(")"); + } } } @@ -845,8 +853,20 @@ protected virtual void VisitClassExpression(ClassExpression classExpression) Append(" extends "); Visit(classExpression.SuperClass); } + + AppendBeautificationSpace(); Append("{"); + + AppendBeautificationNewline(); + IncreaseIndent(); + AppendBeautificationIndent(); + Visit(classExpression.Body); + + AppendBeautificationNewline(); + DecreaseIndent(); + AppendBeautificationIndent(); + Append("}"); } diff --git a/test/Esprima.Tests/JavascriptTest.cs b/test/Esprima.Tests/JavascriptTest.cs index 15fd2357..a9660ec1 100644 --- a/test/Esprima.Tests/JavascriptTest.cs +++ b/test/Esprima.Tests/JavascriptTest.cs @@ -215,15 +215,17 @@ public void ToJavascriptTest5() var expected = @"(function() { 'use strict'; })(); -(class ApplyShimInterface{constructor() { - this.customStyleInterface = null; - applyShim['invalidCallback'] = ApplyShimUtils.invalidate; -}}); +(class ApplyShimInterface { + constructor() { + this.customStyleInterface = null; + applyShim['invalidCallback'] = ApplyShimUtils.invalidate; + } +}); a(); aa({}); -function aa() { +(function aa() { -};"; +});"; expected = Regex.Replace(expected, @"\r\n|\n\r|\n|\r", Environment.NewLine); Assert.Equal(expected, code); } From 9107e160c41fe975546ae7a64979d4c542004583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20K=C3=BChner?= Date: Wed, 10 Nov 2021 07:45:16 +0100 Subject: [PATCH 10/10] more beautification --- src/Esprima/Utils/ToJavascriptConverter.cs | 6 ++++++ test/Esprima.Tests/JavascriptTest.cs | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Esprima/Utils/ToJavascriptConverter.cs b/src/Esprima/Utils/ToJavascriptConverter.cs index 180330c6..3a06d283 100644 --- a/src/Esprima/Utils/ToJavascriptConverter.cs +++ b/src/Esprima/Utils/ToJavascriptConverter.cs @@ -573,11 +573,13 @@ protected virtual void VisitForStatement(ForStatement forStatement) Visit(forStatement.Init); } Append(";"); + AppendBeautificationSpace(); if (forStatement.Test != null) { Visit(forStatement.Test); } Append(";"); + AppendBeautificationSpace(); if (forStatement.Update != null) { Visit(forStatement.Update); @@ -1291,7 +1293,9 @@ protected virtual void VisitConditionalExpression(ConditionalExpression conditio { Append(")"); } + AppendBeautificationSpace(); Append("?"); + AppendBeautificationSpace(); if (ExpressionNeedsBrackets(conditionalExpression.Consequent)) { Append("("); @@ -1301,7 +1305,9 @@ protected virtual void VisitConditionalExpression(ConditionalExpression conditio { Append(")"); } + AppendBeautificationSpace(); Append(":"); + AppendBeautificationSpace(); if (ExpressionNeedsBrackets(conditionalExpression.Alternate)) { Append("("); diff --git a/test/Esprima.Tests/JavascriptTest.cs b/test/Esprima.Tests/JavascriptTest.cs index a9660ec1..fbf64f9b 100644 --- a/test/Esprima.Tests/JavascriptTest.cs +++ b/test/Esprima.Tests/JavascriptTest.cs @@ -161,7 +161,7 @@ export function checkSecurityAnswerCodeDirect(result) { case 'Error': MccDialog.warning({ title : 'SecurityClientErrorOccured', - message : ((((('

' + (commonClient.getTranslation('SecurityClientMessage'))) + ': ') + (commonClient.getTranslation(result.Message))) + '

') + (result.MessageDetails?(('

SecurityClientDetails: ' + result.MessageDetails) + '

'):' ')) + message : ((((('

' + (commonClient.getTranslation('SecurityClientMessage'))) + ': ') + (commonClient.getTranslation(result.Message))) + '

') + (result.MessageDetails ? (('

SecurityClientDetails: ' + result.MessageDetails) + '

') : ' ')) }); return false; default: @@ -372,11 +372,11 @@ public void ToJavascriptTest14() if (s && (e = (ft(r))), i) ; else if (s) - return D(t,e)?(void ($(t,e))):(n = (l(e,t)), G(t,n), void (ht(t))); + return D(t,e) ? (void ($(t,e))) : (n = (l(e,t)), G(t,n), void (ht(t))); var g,o,f; - for(f = (t.length < r.length?t.length:r.length), o = 0, g = 0;f > g;g++) + for(f = (t.length < r.length ? t.length : r.length), o = 0, g = 0; f > g; g++) o += (t[g] + r[g]), t[g] = (o & _t), o >>= at; - for(g = f;o && (g < t.length);g++) + for(g = f; o && (g < t.length); g++) o += t[g], t[g] = (o & _t), o >>= at; }"; expected = Regex.Replace(expected, @"\r\n|\n\r|\n|\r", Environment.NewLine); @@ -520,7 +520,7 @@ class A { var expected = @"class A { *[Symbol.iterator]() { let L = this._first; - for(;L !== _.Undefined;) + for(; L !== _.Undefined; ) yield L.element, L = L.next; } }";