diff --git a/.gitignore b/.gitignore index a39cb33b..5485250d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,22 +2,12 @@ *.hi *.o *~ -/dist/* -/parse.txt -/src/Language/JavaScript/Parser/Grammar5.hs -/src/Language/JavaScript/Parser/Lexer.info -/unicode/uc-ll.htm -/unicode/uc-lm.htm -/unicode/uc-lo.htm -/unicode/uc-lt.htm -/unicode/uc-lu.htm -/unicode/uc-mc.htm -/unicode/uc-mn.htm -/unicode/uc-nd.htm -/unicode/uc-nl.htm -/unicode/uc-nl.htm -/unicode/uc-pc.htm -cabal.sandbox.config +dist/ +dist-newstyle/ +parse.txt +src/Language/JavaScript/Parser/Grammar5.hs +src/Language/JavaScript/Parser/Lexer.info +unicode/*.htm # stack -/.stack-work/ +.stack-work/ diff --git a/.travis.yml b/.travis.yml index bbf9cb99..365d6c09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ env: - GHCVER=8.2.2 - GHCVER=8.4.4 - GHCVER=8.6.5 - - GHCVER=8.8.1 + - GHCVER=8.8.3 before_install: - sudo add-apt-repository -y ppa:hvr/ghc diff --git a/ChangeLog.md b/ChangeLog.md index a1278d88..490983ef 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,8 @@ # ChangeLog for `language-javascript` +## 0.7.1.0 -- 2020-03-22 ++ Add support `async` function specifiers and `await` keyword. + ## 0.7.0.0 -- 2019-10-10 + Add support for (Ryan Hendrickson): diff --git a/buildall.sh b/buildall.sh deleted file mode 100755 index 6964a41f..00000000 --- a/buildall.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -# First run alex on Lexer.x to generate Lexer.hs -#./runalex.sh - -# do a clean build of all, including the tests -#cabal clean && cabal configure -fbuildtests && cabal build && cabal haddock -cabal clean && cabal configure --enable-tests && cabal build && cabal test && cabal haddock diff --git a/cabal.project b/cabal.project new file mode 100644 index 00000000..299276e2 --- /dev/null +++ b/cabal.project @@ -0,0 +1,6 @@ +packages: + ./ + +test-show-details: direct + +tests: True diff --git a/language-javascript.cabal b/language-javascript.cabal index 294402b9..e3eb005b 100644 --- a/language-javascript.cabal +++ b/language-javascript.cabal @@ -1,5 +1,5 @@ Name: language-javascript -Version: 0.7.0.0 +Version: 0.7.1.0 Synopsis: Parser for JavaScript Description: Parses Javascript into an Abstract Syntax Tree (AST). Initially intended as frontend to hjsmin. . @@ -19,7 +19,6 @@ bug-reports: https://github.com/erikd/language-javascript/issues Extra-source-files: README.md ChangeLog.md .ghci - buildall.sh test/Unicode.js test/k.js test/unicode.txt diff --git a/quickcheck.hs b/quickcheck.hs deleted file mode 100644 index fe41d0f3..00000000 --- a/quickcheck.hs +++ /dev/null @@ -1,116 +0,0 @@ -{-# LANGUAGE TemplateHaskell #-} -{-# OPTIONS_GHC -fno-warn-orphans #-} - --- Requires package 'derive'. - -import Control.Applicative -import Data.Derive.Arbitrary -import Data.DeriveTH -import Test.QuickCheck - -import Language.JavaScript.Parser -import Language.JavaScript.Parser.AST - - -import Debug.Trace - - -main :: IO () -main = quickCheck (propertyParsableAST parseWrapper) - -propertyParsableAST :: (String -> JSAST) -> TestAST -> Bool -propertyParsableAST parser (TestAST ast) = - let parsed = parser (renderToString ast) - in showStripped parsed == showStripped (trace ("\n" ++ showStripped ast ++ "\n" ++ showStripped parsed ++ "\n\n") ast) - -parseWrapper :: String -> JSAST -parseWrapper code = - if null code - then JSSourceElementsTop [] - else case parse code "generated javascript" of - Left _ -> JSSourceElementsTop [] - Right tree -> tree - --- Use a newtype wrapper so we can define a Show instance that renders the --- AST to Javascript. -newtype TestAST - = TestAST JSAST - deriving Eq - -instance Show TestAST where - show (TestAST ast) = "-------\n" ++ renderToString ast ++ "\n-------" - --------------------------------------------------------------------------------- --- QuickCheck Arbitrary instances. - -instance Arbitrary TestAST where - arbitrary = TestAST <$> arbitrary - - -instance Arbitrary JSAnnot where - -- Always stick in whitespace. - arbitrary = return $ JSAnnot tokenPosnEmpty [ WhiteSpace tokenPosnEmpty " "] - - -instance Arbitrary JSSemi where - -- The generated test code should always use semicolons. - arbitrary = JSSemi <$> arbitrary - - -instance Arbitrary JSNode where - arbitrary = sizeLimited jsNode - -jsNode :: Int -> Gen JSNode -jsNode 0 = - oneof - [ JSDecimal <$> arbitrary <*> arbDecimalString - , JSIdentifier <$> arbitrary <*> arbIdentifier - ] -jsNode n = - oneof - [ JSUnaryExpression <$> arbitrary <*> jsNode (n - 1) - , JSExpressionBinary <$> jsNode (n - 1) <*> arbitrary <*> jsNode (n - 1) - ] - - -instance Arbitrary JSStatement where - arbitrary = sizeLimited jsStatement - -jsStatement :: Int -> Gen JSStatement -jsStatement 0 = - oneof - [ JSExpressionStatement <$> arbitrary <*> arbitrary - , JSThrow <$> arbitrary <*> arbitrary - ] -jsStatement _ = - oneof - [ JSExpressionStatement <$> arbitrary <*> arbitrary - , JSThrow <$> arbitrary <*> arbitrary - ] - --------------------------------------------------------------------------------- --- A couple more helper generators. - -sizeLimited :: (Int -> Gen a) -> Gen a -sizeLimited f = do - x <- arbitrary - f (max (abs x) 2) - -arbDecimalString :: Gen String -arbDecimalString = arbDecimal >>= \i -> return (show $ abs i) - where - arbDecimal :: Gen Integer - arbDecimal = arbitrary - -arbIdentifier :: Gen String -arbIdentifier = do - s <- choose ('a', 'z') - ss <- oneof [ choose ('a', 'z'), choose ('0', '9') ] - return [ s, ss ] - --------------------------------------------------------------------------------- --- Use template Haskell to automagically derive Aribitrary instances for these. - -$(derive makeArbitrary ''JSBinOp) -$(derive makeArbitrary ''JSUnaryOp) -$(derive makeArbitrary ''JSAST) diff --git a/src/Language/JavaScript/Parser/AST.hs b/src/Language/JavaScript/Parser/AST.hs index c3075520..32302727 100644 --- a/src/Language/JavaScript/Parser/AST.hs +++ b/src/Language/JavaScript/Parser/AST.hs @@ -146,6 +146,7 @@ data JSStatement | JSForConstOf !JSAnnot !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,var,vardecl,in,expr,rb,stmt | JSForOf !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,expr,in,expr,rb,stmt | JSForVarOf !JSAnnot !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,var,vardecl,in,expr,rb,stmt + | JSAsyncFunction !JSAnnot !JSAnnot !JSIdent !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSBlock !JSSemi -- ^fn,name, lb,parameter list,rb,block,autosemi | JSFunction !JSAnnot !JSIdent !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSBlock !JSSemi -- ^fn,name, lb,parameter list,rb,block,autosemi | JSGenerator !JSAnnot !JSAnnot !JSIdent !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSBlock !JSSemi -- ^fn,*,name, lb,parameter list,rb,block,autosemi | JSIf !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSStatement -- ^if,(,expr,),stmt @@ -177,6 +178,7 @@ data JSExpression -- | Non Terminals | JSArrayLiteral !JSAnnot ![JSArrayElement] !JSAnnot -- ^lb, contents, rb | JSAssignExpression !JSExpression !JSAssignOp !JSExpression -- ^lhs, assignop, rhs + | JSAwaitExpression !JSAnnot !JSExpression -- ^await, expr | JSCallExpression !JSExpression !JSAnnot !(JSCommaList JSExpression) !JSAnnot -- ^expr, bl, args, rb | JSCallExpressionDot !JSExpression !JSAnnot !JSExpression -- ^expr, dot, expr | JSCallExpressionSquare !JSExpression !JSAnnot !JSExpression !JSAnnot -- ^expr, [, expr, ] @@ -391,6 +393,7 @@ instance ShowStripped JSStatement where ss (JSForOf _ _lb x1s _i x2 _rb x3) = "JSForOf " ++ ss x1s ++ " (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")" ss (JSForVarOf _ _lb _v x1 _i x2 _rb x3) = "JSForVarOf (" ++ ss x1 ++ ") (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")" ss (JSFunction _ n _lb pl _rb x3 _) = "JSFunction " ++ ssid n ++ " " ++ ss pl ++ " (" ++ ss x3 ++ ")" + ss (JSAsyncFunction _ _ n _lb pl _rb x3 _) = "JSAsyncFunction " ++ ssid n ++ " " ++ ss pl ++ " (" ++ ss x3 ++ ")" ss (JSGenerator _ _ n _lb pl _rb x3 _) = "JSGenerator " ++ ssid n ++ " " ++ ss pl ++ " (" ++ ss x3 ++ ")" ss (JSIf _ _lb x1 _rb x2) = "JSIf (" ++ ss x1 ++ ") (" ++ ss x2 ++ ")" ss (JSIfElse _ _lb x1 _rb x2 _e x3) = "JSIfElse (" ++ ss x1 ++ ") (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")" @@ -412,6 +415,7 @@ instance ShowStripped JSStatement where instance ShowStripped JSExpression where ss (JSArrayLiteral _lb xs _rb) = "JSArrayLiteral " ++ ss xs ss (JSAssignExpression lhs op rhs) = "JSOpAssign (" ++ ss op ++ "," ++ ss lhs ++ "," ++ ss rhs ++ ")" + ss (JSAwaitExpression _ e) = "JSAwaitExpresson " ++ ss e ss (JSCallExpression ex _ xs _) = "JSCallExpression ("++ ss ex ++ ",JSArguments " ++ ss xs ++ ")" ss (JSCallExpressionDot ex _os xs) = "JSCallExpressionDot (" ++ ss ex ++ "," ++ ss xs ++ ")" ss (JSCallExpressionSquare ex _os xs _cs) = "JSCallExpressionSquare (" ++ ss ex ++ "," ++ ss xs ++ ")" diff --git a/src/Language/JavaScript/Parser/Grammar7.y b/src/Language/JavaScript/Parser/Grammar7.y index bd822233..13a15269 100644 --- a/src/Language/JavaScript/Parser/Grammar7.y +++ b/src/Language/JavaScript/Parser/Grammar7.y @@ -86,6 +86,8 @@ import qualified Language.JavaScript.Parser.AST as AST 'as' { AsToken {} } 'autosemi' { AutoSemiToken {} } + 'async' { AsyncToken {} } + 'await' { AwaitToken {} } 'break' { BreakToken {} } 'case' { CaseToken {} } 'catch' { CatchToken {} } @@ -331,6 +333,8 @@ OpAssign : '*=' { AST.JSTimesAssign (mkJSAnnot $1) } -- TODO: make this include any reserved word too, including future ones IdentifierName :: { AST.JSExpression } IdentifierName : Identifier {$1} + | 'async' { AST.JSIdentifier (mkJSAnnot $1) "async" } + | 'await' { AST.JSIdentifier (mkJSAnnot $1) "await" } | 'break' { AST.JSIdentifier (mkJSAnnot $1) "break" } | 'case' { AST.JSIdentifier (mkJSAnnot $1) "case" } | 'catch' { AST.JSIdentifier (mkJSAnnot $1) "catch" } @@ -407,6 +411,12 @@ For : 'for' { mkJSAnnot $1 } Continue :: { AST.JSAnnot } Continue : 'continue' { mkJSAnnot $1 } +Async :: { AST.JSAnnot } +Async : 'async' { mkJSAnnot $1 } + +Await :: { AST.JSAnnot } +Await : 'await' { mkJSAnnot $1 } + Break :: { AST.JSAnnot } Break : 'break' { mkJSAnnot $1 } @@ -657,6 +667,10 @@ NewExpression :: { AST.JSExpression } NewExpression : MemberExpression { $1 {- 'NewExpression1' -} } | New NewExpression { AST.JSNewExpression $1 $2 {- 'NewExpression2' -} } +AwaitExpression :: { AST.JSExpression } +AwaitExpression + : Await Expression { AST.JSAwaitExpression $1 $2 } + -- CallExpression : See 11.2 -- MemberExpression Arguments -- CallExpression Arguments @@ -696,6 +710,7 @@ ArgumentList : AssignmentExpression { AST.JSLOne $1 LeftHandSideExpression :: { AST.JSExpression } LeftHandSideExpression : NewExpression { $1 {- 'LeftHandSideExpression1' -} } | CallExpression { $1 {- 'LeftHandSideExpression12' -} } + | AwaitExpression { $1 {- 'LeftHandSideExpression13' -} } -- PostfixExpression : See 11.3 -- LeftHandSideExpression @@ -976,20 +991,23 @@ Statement : StatementNoEmpty { $1 {- 'Statement1' -} } | EmptyStatement { $1 {- 'Statement2' -} } StatementNoEmpty :: { AST.JSStatement } -StatementNoEmpty : StatementBlock { $1 {- 'StatementNoEmpty1' -} } - | VariableStatement { $1 {- 'StatementNoEmpty2' -} } - | ExpressionStatement { $1 {- 'StatementNoEmpty4' -} } - | IfStatement { $1 {- 'StatementNoEmpty5' -} } - | IterationStatement { $1 {- 'StatementNoEmpty6' -} } - | ContinueStatement { $1 {- 'StatementNoEmpty7' -} } - | BreakStatement { $1 {- 'StatementNoEmpty8' -} } - | ReturnStatement { $1 {- 'StatementNoEmpty9' -} } - | WithStatement { $1 {- 'StatementNoEmpty10' -} } - | LabelledStatement { $1 {- 'StatementNoEmpty11' -} } - | SwitchStatement { $1 {- 'StatementNoEmpty12' -} } - | ThrowStatement { $1 {- 'StatementNoEmpty13' -} } - | TryStatement { $1 {- 'StatementNoEmpty14' -} } - | DebuggerStatement { $1 {- 'StatementNoEmpty15' -} } +StatementNoEmpty + : IfStatement { $1 {- 'StatementNoEmpty5' -} } + | ContinueStatement { $1 {- 'StatementNoEmpty7' -} } + | BreakStatement { $1 {- 'StatementNoEmpty8' -} } + | ReturnStatement { $1 {- 'StatementNoEmpty9' -} } + | WithStatement { $1 {- 'StatementNoEmpty10' -} } + | LabelledStatement { $1 {- 'StatementNoEmpty11' -} } + | SwitchStatement { $1 {- 'StatementNoEmpty12' -} } + | ThrowStatement { $1 {- 'StatementNoEmpty13' -} } + | TryStatement { $1 {- 'StatementNoEmpty14' -} } + | StatementBlock { $1 {- 'StatementNoEmpty1' -} } + | VariableStatement { $1 {- 'StatementNoEmpty2' -} } + | IterationStatement { $1 {- 'StatementNoEmpty6' -} } + | ExpressionStatement { $1 {- 'StatementNoEmpty4' -} } + | AsyncFunctionStatement { $1 {- 'StatementNoEmpty15' -} } + | DebuggerStatement { $1 {- 'StatementNoEmpty15' -} } + StatementBlock :: { AST.JSStatement } @@ -1208,7 +1226,10 @@ DebuggerStatement : 'debugger' MaybeSemi { AST.JSExpressionStatement (AST.JSLite -- FunctionDeclaration : See clause 13 -- function Identifier ( FormalParameterListopt ) { FunctionBody } FunctionDeclaration :: { AST.JSStatement } -FunctionDeclaration : NamedFunctionExpression MaybeSemi { expressionToStatement $1 $2 {- 'FunctionDeclaration1' -} } +FunctionDeclaration : NamedFunctionExpression MaybeSemi { expressionToStatement $1 $2 {- 'FunctionDeclaration1' -} } + +AsyncFunctionStatement :: { AST.JSStatement } +AsyncFunctionStatement : Async NamedFunctionExpression MaybeSemi { expressionToAsyncFunction $1 $2 $3 {- 'AsyncFunctionStatement1' -} } -- FunctionExpression : See clause 13 -- function Identifieropt ( FormalParameterListopt ) { FunctionBody } @@ -1499,6 +1520,9 @@ expressionToStatement (AST.JSMemberExpression e l a r) s = AST.JSMethodCall e l expressionToStatement (AST.JSClassExpression a b@(AST.JSIdentName{}) c d e f) s = AST.JSClass a b c d e f s expressionToStatement exp s = AST.JSExpressionStatement exp s +expressionToAsyncFunction :: AST.JSAnnot -> AST.JSExpression -> AST.JSSemi -> AST.JSStatement +expressionToAsyncFunction aa (AST.JSFunctionExpression a b@(AST.JSIdentName{}) c d e f) s = AST.JSAsyncFunction aa a b c d e f s +expressionToAsyncFunction _aa _exp _s = error "Bad async function." mkJSCallExpression :: AST.JSExpression -> JSArguments -> AST.JSExpression mkJSCallExpression e (JSArguments l arglist r) = AST.JSCallExpression e l arglist r diff --git a/src/Language/JavaScript/Parser/Lexer.x b/src/Language/JavaScript/Parser/Lexer.x index 62d8e186..d28be52c 100644 --- a/src/Language/JavaScript/Parser/Lexer.x +++ b/src/Language/JavaScript/Parser/Lexer.x @@ -529,7 +529,9 @@ keywords = Map.fromList keywordNames keywordNames :: [(String, TokenPosn -> String -> [CommentAnnotation] -> Token)] keywordNames = - [ ( "break", BreakToken ) + [ ( "async", AsyncToken ) + , ( "await", AwaitToken ) + , ( "break", BreakToken ) , ( "case", CaseToken ) , ( "catch", CatchToken ) diff --git a/src/Language/JavaScript/Parser/Token.hs b/src/Language/JavaScript/Parser/Token.hs index 36b3b77a..72188284 100644 --- a/src/Language/JavaScript/Parser/Token.hs +++ b/src/Language/JavaScript/Parser/Token.hs @@ -56,6 +56,8 @@ data Token -- ^ Literal: Regular Expression -- Keywords + | AsyncToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } + | AwaitToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } | BreakToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } | CaseToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } | CatchToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } diff --git a/src/Language/JavaScript/Pretty/Printer.hs b/src/Language/JavaScript/Pretty/Printer.hs index 995933d6..6ef75b0b 100644 --- a/src/Language/JavaScript/Pretty/Printer.hs +++ b/src/Language/JavaScript/Pretty/Printer.hs @@ -1,5 +1,5 @@ -{-# LANGUAGE FlexibleInstances, NoOverloadedStrings, TypeSynonymInstances #-} +{-# LANGUAGE CPP, FlexibleInstances, NoOverloadedStrings, TypeSynonymInstances #-} module Language.JavaScript.Pretty.Printer ( -- * Printing @@ -10,8 +10,10 @@ module Language.JavaScript.Pretty.Printer import Blaze.ByteString.Builder (Builder, toLazyByteString) import Data.List +#if ! MIN_VERSION_base(4,13,0) import Data.Monoid (mempty) import Data.Semigroup ((<>)) +#endif import Data.Text.Lazy (Text) import Language.JavaScript.Parser.AST import Language.JavaScript.Parser.SrcLocation @@ -74,6 +76,7 @@ instance RenderJS JSExpression where (|>) pacc (JSArrayLiteral als xs ars) = pacc |> als |> "[" |> xs |> ars |> "]" (|>) pacc (JSArrowExpression xs a x) = pacc |> xs |> a |> "=>" |> x (|>) pacc (JSAssignExpression lhs op rhs) = pacc |> lhs |> op |> rhs + (|>) pacc (JSAwaitExpression a e) = pacc |> a |> "await" |> e (|>) pacc (JSCallExpression ex lb xs rb) = pacc |> ex |> lb |> "(" |> xs |> rb |> ")" (|>) pacc (JSCallExpressionDot ex os xs) = pacc |> ex |> os |> "." |> xs (|>) pacc (JSCallExpressionSquare ex als xs ars) = pacc |> ex |> als |> "[" |> xs |> ars |> "]" @@ -242,6 +245,7 @@ instance RenderJS JSStatement where (|>) pacc (JSForConstOf af alb v x1 i x2 arb x3) = pacc |> af |> "for" |> alb |> "(" |> "const" |> v |> x1 |> i |> x2 |> arb |> ")" |> x3 (|>) pacc (JSForOf af alb x1s i x2 arb x3) = pacc |> af |> "for" |> alb |> "(" |> x1s |> i |> x2 |> arb |> ")" |> x3 (|>) pacc (JSForVarOf af alb v x1 i x2 arb x3) = pacc |> af |> "for" |> alb |> "(" |> "var" |> v |> x1 |> i |> x2 |> arb |> ")" |> x3 + (|>) pacc (JSAsyncFunction aa af n alb x2s arb x3 s) = pacc |> aa |> "async" |> af |> "function" |> n |> alb |> "(" |> x2s |> arb |> ")" |> x3 |> s (|>) pacc (JSFunction af n alb x2s arb x3 s) = pacc |> af |> "function" |> n |> alb |> "(" |> x2s |> arb |> ")" |> x3 |> s (|>) pacc (JSGenerator af as n alb x2s arb x3 s) = pacc |> af |> "function" |> as |> "*" |> n |> alb |> "(" |> x2s |> arb |> ")" |> x3 |> s (|>) pacc (JSIf annot alb x1 arb x2s) = pacc |> annot |> "if" |> alb |> "(" |> x1 |> arb |> ")" |> x2s diff --git a/src/Language/JavaScript/Process/Minify.hs b/src/Language/JavaScript/Process/Minify.hs index 4f52b42f..b6121ea8 100644 --- a/src/Language/JavaScript/Process/Minify.hs +++ b/src/Language/JavaScript/Process/Minify.hs @@ -5,7 +5,9 @@ module Language.JavaScript.Process.Minify minifyJS ) where +#if ! MIN_VERSION_base(4,13,0) import Control.Applicative ((<$>)) +#endif import Language.JavaScript.Parser.AST import Language.JavaScript.Parser.SrcLocation @@ -57,6 +59,7 @@ fixStmt a s (JSForConstIn _ _ _ e1 op e2 _ st) = JSForConstIn a emptyAnnot space fixStmt a s (JSForConstOf _ _ _ e1 op e2 _ st) = JSForConstOf a emptyAnnot spaceAnnot (fixEmpty e1) (fixSpace op) (fixSpace e2) emptyAnnot (fixStmtE s st) fixStmt a s (JSForOf _ _ e1 op e2 _ st) = JSForOf a emptyAnnot (fixEmpty e1) (fixSpace op) (fixSpace e2) emptyAnnot (fixStmtE s st) fixStmt a s (JSForVarOf _ _ _ e1 op e2 _ st) = JSForVarOf a emptyAnnot spaceAnnot (fixEmpty e1) (fixSpace op) (fixSpace e2) emptyAnnot (fixStmtE s st) +fixStmt a s (JSAsyncFunction _ _ n _ ps _ blk _) = JSAsyncFunction a spaceAnnot (fixSpace n) emptyAnnot (fixEmpty ps) emptyAnnot (fixEmpty blk) s fixStmt a s (JSFunction _ n _ ps _ blk _) = JSFunction a (fixSpace n) emptyAnnot (fixEmpty ps) emptyAnnot (fixEmpty blk) s fixStmt a s (JSGenerator _ _ n _ ps _ blk _) = JSGenerator a emptyAnnot (fixEmpty n) emptyAnnot (fixEmpty ps) emptyAnnot (fixEmpty blk) s fixStmt a s (JSIf _ _ e _ st) = JSIf a emptyAnnot (fixEmpty e) emptyAnnot (fixIfElseBlock emptyAnnot s st) @@ -155,6 +158,7 @@ instance MinifyJS JSExpression where fix _ (JSArrayLiteral _ xs _) = JSArrayLiteral emptyAnnot (map fixEmpty xs) emptyAnnot fix a (JSArrowExpression ps _ ss) = JSArrowExpression (fix a ps) emptyAnnot (fixStmt emptyAnnot noSemi ss) fix a (JSAssignExpression lhs op rhs) = JSAssignExpression (fix a lhs) (fixEmpty op) (fixEmpty rhs) + fix a (JSAwaitExpression _ ex) = JSAwaitExpression a (fixSpace ex) fix a (JSCallExpression ex _ xs _) = JSCallExpression (fix a ex) emptyAnnot (fixEmpty xs) emptyAnnot fix a (JSCallExpressionDot ex _ xs) = JSCallExpressionDot (fix a ex) emptyAnnot (fixEmpty xs) fix a (JSCallExpressionSquare ex _ xs _) = JSCallExpressionSquare (fix a ex) emptyAnnot (fixEmpty xs) emptyAnnot diff --git a/test/Test/Language/Javascript/Lexer.hs b/test/Test/Language/Javascript/Lexer.hs index edaca02f..1eda282d 100644 --- a/test/Test/Language/Javascript/Lexer.hs +++ b/test/Test/Language/Javascript/Lexer.hs @@ -69,6 +69,9 @@ testLexer = describe "Lexer:" $ do testLex "in\n" `shouldBe` "[InToken,WsToken]" testLex "of\n" `shouldBe` "[OfToken,WsToken]" + it "function" $ do + testLex "async function\n" `shouldBe` "[AsyncToken,WsToken,FunctionToken,WsToken]" + testLex :: String -> String testLex str = diff --git a/test/Test/Language/Javascript/Minify.hs b/test/Test/Language/Javascript/Minify.hs index 0b5abce3..233ac5d3 100644 --- a/test/Test/Language/Javascript/Minify.hs +++ b/test/Test/Language/Javascript/Minify.hs @@ -232,6 +232,7 @@ testMinifyStmt = describe "Minify statements:" $ do minifyStmt " function f ( a = 1 , b = 2 ) { return a + b ; } ; " `shouldBe` "function f(a=1,b=2){return a+b}" minifyStmt " function f ( [ a , b ] ) { return a + b ; } ; " `shouldBe` "function f([a,b]){return a+b}" minifyStmt " function f ( { a , b , } ) { return a + b ; } ; " `shouldBe` "function f({a,b}){return a+b}" + minifyStmt " async function f ( ) { } " `shouldBe` "async function f(){}" it "generator" $ do minifyStmt " function * f ( ) { } ; " `shouldBe` "function*f(){}" @@ -279,6 +280,9 @@ testMinifyStmt = describe "Minify statements:" $ do minifyStmt " class Foo extends (getBase()) {} " `shouldBe` "class Foo extends(getBase()){}" minifyStmt " class Foo extends [ Bar1, Bar2 ][getBaseIndex()] {} " `shouldBe` "class Foo extends[Bar1,Bar2][getBaseIndex()]{}" + it "miscellaneous" $ + minifyStmt " let r = await p ; " `shouldBe` "let r=await p" + testMinifyProg :: Spec testMinifyProg = describe "Minify programs:" $ do it "simple" $ do diff --git a/test/Test/Language/Javascript/ProgramParser.hs b/test/Test/Language/Javascript/ProgramParser.hs index d7f26fcf..b7dc900c 100644 --- a/test/Test/Language/Javascript/ProgramParser.hs +++ b/test/Test/Language/Javascript/ProgramParser.hs @@ -1,9 +1,11 @@ +{-# LANGUAGE CPP #-} module Test.Language.Javascript.ProgramParser ( testProgramParser ) where - +#if ! MIN_VERSION_base(4,13,0) import Control.Applicative ((<$>)) +#endif import Test.Hspec import Language.JavaScript.Parser