packages feed

language-ecmascript 0.9.1 → 0.10

raw patch · 12 files changed

+1196/−590 lines, 12 filesdep +QuickCheckdep ~containersdep ~data-defaultPVP ok

version bump matches the API change (PVP)

Dependencies added: QuickCheck

Dependency ranges changed: containers, data-default

API changes (from Hackage documentation)

- Language.ECMAScript3.Syntax: ParenExpr :: a -> (Expression a) -> Expression a
+ Language.ECMAScript3.Parser: intLen :: (Integral a, Num a1) => a -> a1
+ Language.ECMAScript3.Parser: mkDecimal :: Integer -> Integer -> Integer -> Integer -> Double
+ Language.ECMAScript3.Syntax.Arbitrary: atLeastOfSize :: Arbitrary a => Int -> Gen a -> Gen a
+ Language.ECMAScript3.Syntax.Arbitrary: cshrink :: Arbitrary a => [a] -> [a]
+ Language.ECMAScript3.Syntax.Arbitrary: emptyConstantPool :: Map k a
+ Language.ECMAScript3.Syntax.Arbitrary: emptyStmtShrink :: Arbitrary a => a -> [Statement a]
+ Language.ECMAScript3.Syntax.Arbitrary: fixBreakContinueLabels :: Data a => JavaScript a -> Gen (JavaScript a)
+ Language.ECMAScript3.Syntax.Arbitrary: fixLabels :: Data a => JavaScript a -> Gen (JavaScript a)
+ Language.ECMAScript3.Syntax.Arbitrary: identifier :: Gen String
+ Language.ECMAScript3.Syntax.Arbitrary: instance (Data a, Arbitrary a) => Arbitrary (JavaScript a)
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary AssignOp
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary InfixOp
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary PrefixOp
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary UnaryAssignOp
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary a => Arbitrary (CaseClause a)
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary a => Arbitrary (CatchClause a)
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary a => Arbitrary (Expression a)
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary a => Arbitrary (ForInInit a)
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary a => Arbitrary (ForInit a)
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary a => Arbitrary (Id a)
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary a => Arbitrary (LValue a)
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary a => Arbitrary (Prop a)
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary a => Arbitrary (Statement a)
+ Language.ECMAScript3.Syntax.Arbitrary: instance Arbitrary a => Arbitrary (VarDecl a)
+ Language.ECMAScript3.Syntax.Arbitrary: isBreakContinueFixable :: Data a => Statement a -> Bool -> Bool -> Bool -> Bool
+ Language.ECMAScript3.Syntax.Arbitrary: isProgramFixable :: Data a => JavaScript a -> Bool
+ Language.ECMAScript3.Syntax.Arbitrary: isSwitchStmt :: Statement a -> Bool
+ Language.ECMAScript3.Syntax.Arbitrary: nonEmptyString :: Gen String
+ Language.ECMAScript3.Syntax.Arbitrary: nonNegative :: (Arbitrary a, Num a) => Gen a
+ Language.ECMAScript3.Syntax.Arbitrary: rChooseElem :: [a] -> Int -> Gen [a]
+ Language.ECMAScript3.Syntax.Arbitrary: rarbitrary :: Arbitrary a => Gen a
+ Language.ECMAScript3.Syntax.Arbitrary: recursive :: Gen a -> Gen a
+ Language.ECMAScript3.Syntax.Arbitrary: regexpBody :: Gen String
+ Language.ECMAScript3.Syntax.Arbitrary: removeDuplicateLabels :: Data a => JavaScript a -> Gen (JavaScript a)
+ Language.ECMAScript3.Syntax.Arbitrary: rrarbitrary :: Arbitrary a => Gen a
+ Language.ECMAScript3.Syntax.Arbitrary: sGen :: [MSGen a] -> Gen a
+ Language.ECMAScript3.Syntax.Arbitrary: selectRandomElement :: [a] -> Gen a
+ Language.ECMAScript3.Syntax.Arbitrary: stringOfLength :: Int -> Gen String
+ Language.ECMAScript3.Syntax.Arbitrary: type LabelSubst = Map (Id ()) (Id ())
+ Language.ECMAScript3.Syntax.Arbitrary: type MSGen a = (Int, Gen a)
- Language.ECMAScript3.Syntax: FuncExpr :: a -> (Maybe (Id a)) -> [Id a] -> (Statement a) -> Expression a
+ Language.ECMAScript3.Syntax: FuncExpr :: a -> (Maybe (Id a)) -> [Id a] -> [Statement a] -> Expression a
- Language.ECMAScript3.Syntax: FunctionStmt :: a -> (Id a) -> [Id a] -> (Statement a) -> Statement a
+ Language.ECMAScript3.Syntax: FunctionStmt :: a -> (Id a) -> [Id a] -> [Statement a] -> Statement a

Files

CHANGELOG view
@@ -1,5 +1,14 @@ Version change log. +=0.10=++The ParenExpr constructor was removed from the Expression AST+(WARNING: might break some builds). The pretty printer was rewritten+to automatically parenthesize sub-expressions based on operator+precedence. Added a (beta quality) arbitrary instance for all the+AST's to generate random JavaScript programs (useful for testing).++ =0.9.1=  Increased the upper bound on data-default in dependencies. See https://github.com/jswebtools/language-ecmascript/pull/5
language-ecmascript.cabal view
@@ -1,5 +1,5 @@ Name:           language-ecmascript-Version:        0.9.1+Version:        0.10 Cabal-Version:	>= 1.10 Copyright:      (c) 2007-2012 Brown University, (c) 2008-2010 Claudiu Saftoiu,                 (c) 2012 Stevens Institute of Technology@@ -30,7 +30,7 @@ Source-repository this    type: git    location: git://github.com/jswebtools/language-ecmascript.git-   tag: 0.9+   tag: 0.9.1  Library   Hs-Source-Dirs:@@ -43,7 +43,8 @@     containers >= 0.1,     syb >= 0.1,     uniplate >= 1.6 && <1.7,-    data-default >= 0.4 && <0.6+    data-default >= 0.4 && <0.6,+    QuickCheck >= 2.4.1.1   ghc-options:     -fwarn-incomplete-patterns   Exposed-Modules:@@ -53,6 +54,7 @@     Language.ECMAScript3.PrettyPrint     Language.ECMAScript3.Syntax     Language.ECMAScript3.Syntax.Annotations+    Language.ECMAScript3.Syntax.Arbitrary     Language.ECMAScript3.Analysis.Environment     Language.ECMAScript3.Analysis.LabelSets   Default-Extensions:@@ -73,7 +75,30 @@     directory,     filepath,     HUnit,-    data-default >=0.4 && <0.6+    data-default >=0.4 && <0.6,+    QuickCheck >= 2.4.1.1+  Default-Extensions: DeriveDataTypeable, ScopedTypeVariables, DeriveFunctor, DeriveFoldable, DeriveTraversable, FlexibleContexts+  Default-Language: Haskell2010+  ghc-options:+    -fwarn-incomplete-patterns++Test-Suite prettytest+  Hs-Source-Dirs: src+  Type: exitcode-stdio-1.0+  Main-Is: PrettyTest.hs+  Build-Depends:+    base >= 4 && < 5,+    mtl >= 1.1.0.1,+    parsec < 3.2.0,+    pretty >= 0.1,+    containers >= 0.1,+    syb >= 0.1,+    directory,+    filepath,+    HUnit,+    data-default >=0.4 && <0.5,+    QuickCheck >= 2.4.1.1,+    uniplate >= 1.6 && <1.7   Default-Extensions: DeriveDataTypeable, ScopedTypeVariables, DeriveFunctor, DeriveFoldable, DeriveTraversable, FlexibleContexts   Default-Language: Haskell2010   ghc-options:
src/Language/ECMAScript3/Analysis/Environment.hs view
@@ -72,10 +72,10 @@   CondExpr _ e1 e2 e3 -> unions [expr e1, expr e2, expr e3]   AssignExpr _ _ lv e -> unions [lvalue lv, expr e]   UnaryAssignExpr _ _ lv -> lvalue lv-  ParenExpr _ e -> expr e   ListExpr _ es -> unions (map expr es)   CallExpr _ e es -> unions [expr e, unions $ map expr es]-  FuncExpr _ _ args s -> nest $ unions [unions $ map decl args, stmt s]+  FuncExpr _ _ args ss -> nest $ unions [unions $ map decl args+                                        ,unions $ map stmt ss]  caseClause :: CaseClause SourcePos -> Partial caseClause cc = case cc of@@ -122,8 +122,9 @@   ReturnStmt _ me -> maybe empty expr me   WithStmt _ e s -> unions [expr e, stmt s]   VarDeclStmt _ decls -> unions $ map varDecl decls-  FunctionStmt _ fnId args s ->-    unions [decl fnId, nest $ unions [unions $ map decl args, stmt s]]+  FunctionStmt _ fnId args ss ->+    unions [decl fnId, nest $ unions [unions $ map decl args,+                                      unions $ map stmt ss]]  -- |The statically-determinate lexical structure of a JavaScript program. data EnvTree = EnvTree (M.Map String SourcePos) [EnvTree]
src/Language/ECMAScript3/Analysis/LabelSets.hs view
@@ -41,7 +41,7 @@                        -> Statement a annotateFuncStmtBodies r w s = case s of   FunctionStmt a name params body -> -    let newbody = descend (annotateStatement r w) body+    let newbody = map (descend (annotateStatement r w)) body     in  FunctionStmt a name params newbody   _ -> s                        @@ -52,7 +52,7 @@                        -> Expression a annotateFuncExprBodies r w e = case e of   FuncExpr a mname params body -> -    let newbody = descend (annotateStatement r w) body+    let newbody = map (descend (annotateStatement r w)) body     in  FuncExpr a mname params newbody   _ -> e 
src/Language/ECMAScript3/Parser.hs view
@@ -1,5 +1,5 @@--- | Parser for ECMAScript 3.-+ -- | Parser for ECMAScript 3.+{-# LANGUAGE FlexibleContexts #-} module Language.ECMAScript3.Parser   (parse   , parseScriptFromString@@ -15,6 +15,9 @@   , StatementParser   , ExpressionParser   , assignExpr+  -- debugging, remove the next 2 lines+  , mkDecimal+  , intLen   ) where  import Language.ECMAScript3.Lexer hiding (identifier)@@ -137,7 +140,7 @@ parseDoWhileStmt = do   pos <- getPosition   reserved "do"-  body <- parseBlockStmt+  body <- parseStatement   reserved "while" <?> "while at the end of a do block"   test <- parseParenExpr <?> "parenthesized test-expression in do loop"   optional semi@@ -294,7 +297,8 @@   name <- try (reserved "function" >> identifier) -- ambiguity with FuncExpr   args <- parens (identifier `sepBy` comma)   -- label sets don't cross function boundaries-  body <- withFreshLabelStack parseBlockStmt <?> "function body in { ... }"+  BlockStmt _ body <- withFreshLabelStack parseBlockStmt <?> +                      "function body in { ... }"   return (FunctionStmt pos name args body)  parseStatement:: StatementParser@@ -359,7 +363,7 @@   name <- optionMaybe identifier   args <- parens (identifier `sepBy` comma)   -- labels don't cross function boundaries-  body <- withFreshLabelStack parseBlockStmt+  BlockStmt _ body <- withFreshLabelStack parseBlockStmt   return $ FuncExpr pos name args body  --{{{ parsing strings@@ -432,12 +436,13 @@       parseChar = noneOf "/"   let parseRe = (char '/' >> return "") <|>                  (do char '\\'-                    ch <- anyChar -- TOOD: too lenient+                    ch <- anyChar -- TODO: too lenient                     rest <- parseRe                     return ('\\':ch:rest)) <|>                  liftM2 (:) anyChar parseRe   pos <- getPosition   char '/'+  notFollowedBy $ char '/'   pat <- parseRe --many1 parseChar   flags <- parseFlags   spaces -- crucial for Parsec.Token parsers@@ -467,12 +472,16 @@   [(hex,"")] <- return $ Numeric.readHex digits   return (True, hex) --- Creates a decimal value from a whole, fractional and exponent part.-mkDecimal:: Double -> Double -> Int -> Double-mkDecimal w f e =  if f >= 1.0-                   then mkDecimal w (f / 10.0) e-                   else (w + f) * (10.0 ^^ e)+-- | Creates a decimal value from a whole, fractional and exponent part.+mkDecimal :: Integer -> Integer -> Integer -> Integer -> Double+mkDecimal whole frac fracLen exp = +  ((fromInteger whole) + ((fromInteger frac) * (10 ^^ (-fracLen)))) * (10 ^^ exp) +-- mkDecimal:: Double -> Double -> Int -> Double+-- mkDecimal w f e =  if f >= 1.0+--                    then mkDecimal w (f / 10.0) e+--                    else (w + f) * (10.0 ^^ e)+ exponentPart = do   oneOf "eE"   (char '+' >> decimal) <|> (char '-' >> negate `fmap` decimal) <|> decimal@@ -486,13 +495,19 @@       mexp <-  option Nothing (jparser exponentPart)       if isNothing mfrac && isNothing mexp         then return (True, fromIntegral whole)-        else return (False, mkDecimal (fromIntegral whole) -                                      (fromIntegral (fromMaybe 0 mfrac))-                                      (fromIntegral (fromMaybe 0 mexp)))) <|>+        else let frac = fromIntegral (fromMaybe 0 mfrac)+             in  return (False, mkDecimal (fromIntegral whole) frac +                                          (intLen frac)+                                          (fromIntegral (fromMaybe 0 mexp))))+  <|>   (do frac <- char '.' >> decimal       exp <- option 0 exponentPart-      return (False, mkDecimal 0.0 (fromIntegral frac) (fromIntegral exp)))+      let ifrac = fromIntegral frac+      return (False, mkDecimal 0 ifrac (intLen frac) (fromIntegral exp))) +intLen i | i `div` 10 < 1 = 1+intLen i | otherwise = 1 + intLen (i `div` 10)+ parseNumLit:: ExpressionParser parseNumLit = do     pos <- getPosition@@ -528,7 +543,7 @@ -------------------------------------------------------------------------------  parseParenExpr:: ExpressionParser-parseParenExpr = withPos ParenExpr (parens parseListExpr)+parseParenExpr = parens parseListExpr  -- everything above expect functions parseExprForNew = parseThisRef <|> parseNullLit <|> parseBoolLit <|> parseStringLit @@ -720,7 +735,10 @@ parseExpression:: ExpressionParser parseExpression = assignExpr -parseListExpr = liftM2 ListExpr getPosition (assignExpr `sepBy1` comma)+parseListExpr = assignExpr `sepBy1` comma >>= \exprs ->+  case exprs of+    [expr] -> return expr+    es     -> liftM2 ListExpr getPosition (return es)  parseScript:: CharParser (JavaScript SourcePos) parseScript = do@@ -728,8 +746,8 @@   liftM2 Script getPosition (parseStatement `sepBy` whiteSpace)    -- | Parse from a stream; same as 'Text.Parsec.parse'-parse :: Stream s Identity t =>-         Parsec s [String] a -- ^ The parser to use+parse :: Stream s Identity t +      => Parsec s [String] a -- ^ The parser to use       -> SourceName -- ^ Name of the source file       -> s -- ^ the stream to parse, usually a 'String'       -> Either ParseError a
src/Language/ECMAScript3/PrettyPrint.hs view
@@ -1,8 +1,6 @@ -- |Pretty-printing JavaScript. module Language.ECMAScript3.PrettyPrint   ( ---    stmt---  , expr   javaScript   , renderStatements   , renderExpression@@ -10,6 +8,7 @@  import Text.PrettyPrint.HughesPJ import Language.ECMAScript3.Syntax+import Prelude hiding (maybe)  -- | Renders a list of statements as a 'String' renderStatements :: [Statement a] -> String@@ -17,69 +16,76 @@  -- | Renders a list of statements as a 'String' renderExpression :: Expression a -> String-renderExpression = render . expr+renderExpression = render . (ppExpression True)  -- Displays the statement in { ... }, unless it is a block itself. inBlock:: Statement a -> Doc-inBlock s@(BlockStmt _ _) = stmt s-inBlock s                 = lbrace $+$ nest 2 (stmt s) $+$ rbrace+inBlock s@(BlockStmt _ _) = ppStatement s+inBlock s                 = asBlock [s] --- Displays the expression in ( ... ), unless it is a parenthesized expression-inParens:: Expression a -> Doc-inParens e@(ParenExpr _ _) = expr e-inParens e                 = parens (expr e)+asBlock :: [Statement a] -> Doc+asBlock ss = lbrace $+$ nest 2 (stmtList ss) $$ rbrace -pp (Id _ str) = text str+ppId (Id _ str) = text str  forInit :: ForInit a -> Doc forInit t = case t of   NoInit     -> empty-  VarInit vs -> text "var" <+> cat (punctuate comma $ map varDecl vs)-  ExprInit e -> expr e+  VarInit vs -> text "var" <+> cat (punctuate comma $ map (ppVarDecl False) vs)+  ExprInit e -> ppExpression False e  forInInit :: ForInInit a -> Doc   forInInit t = case t of-  ForInVar id   -> text "var" <+> pp id-  ForInLVal lv -> lvalue lv+  ForInVar id   -> text "var" <+> ppId id+  ForInLVal lv -> ppLValue lv  caseClause :: CaseClause a -> Doc caseClause (CaseClause _ e ss) =-  text "case" $+$ expr e <+> colon $$ nest 2 (stmtList ss)+  text "case" $+$ ppExpression True e <+> colon $$ nest 2 (stmtList ss) caseClause (CaseDefault _ ss) =   text "default:" $$ nest 2 (stmtList ss) -varDecl :: VarDecl a -> Doc-varDecl (VarDecl _ id Nothing) = pp id-varDecl (VarDecl _ id (Just e)) = pp id <+> equals <+> expr e+ppVarDecl :: Bool -> VarDecl a -> Doc+ppVarDecl hasIn vd = case vd of+  VarDecl _ id Nothing  -> ppId id+  VarDecl _ id (Just e) -> ppId id <+> equals <+> ppAssignmentExpression hasIn e -stmt :: Statement a -> Doc-stmt s = case s of-  BlockStmt _ ss -> lbrace $+$ nest 2 (stmtList ss) $$ rbrace+ppStatement :: Statement a -> Doc+ppStatement s = case s of+  BlockStmt _ ss -> asBlock ss   EmptyStmt _ -> semi-  ExprStmt _ e -> expr e <> semi-  IfSingleStmt _ test cons -> text "if" <+> inParens test $$ stmt cons-  IfStmt _ test cons alt ->-    text "if" <+> inParens test $$ stmt cons $$ text "else" <+> stmt alt+  ExprStmt _ e@(CallExpr _ (FuncExpr {}) _ ) -> +    parens (ppExpression True e) <> semi+  ExprStmt _ e -> ppExpression True e <> semi+  IfSingleStmt _ test cons -> text "if" <+> +                              parens (ppExpression True test) $$ +                              ppStatement cons+  IfStmt _ test cons alt -> text "if" <+> parens (ppExpression True test) $$ +                            ppStatement cons $$ text "else" <+> ppStatement alt   SwitchStmt _ e cases ->-    text "switch" <+> inParens e $$ +    text "switch" <+> parens (ppExpression True e) $$      braces (nest 2 (vcat (map caseClause cases)))-  WhileStmt _ test body -> text "while" <+> inParens test $$ stmt body+  WhileStmt _ test body -> text "while" <+> parens (ppExpression True test) $$+                           ppStatement body   ReturnStmt _ Nothing -> text "return"-  ReturnStmt _ (Just e) -> text "return" <+> expr e+  ReturnStmt _ (Just e) -> text "return" <+> ppExpression True e   DoWhileStmt _ s e -> -    text "do" $$ (stmt s <+> text "while" <+> inParens e <> semi)+    text "do" $$ +    (ppStatement s <+> text "while" <+> parens (ppExpression True e) <> semi)   BreakStmt _ Nothing ->  text "break" <> semi-  BreakStmt _ (Just label) -> text "break" <+> pp label <> semi+  BreakStmt _ (Just label) -> text "break" <+> ppId label <> semi   ContinueStmt _ Nothing -> text "continue" <> semi-  ContinueStmt _ (Just label) -> text"continue" <+> pp label <> semi-  LabelledStmt _ label s -> pp label <> colon $$ stmt s+  ContinueStmt _ (Just label) -> text"continue" <+> ppId label <> semi+  LabelledStmt _ label s -> ppId label <> colon $$ ppStatement s   ForInStmt p init e body ->      text "for" <+> -    parens (forInInit init <+> text "in" <+> expr e) $+$ stmt body+    parens (forInInit init <+> text "in" <+> ppExpression True e) $+$ +    ppStatement body   ForStmt _ init incr test body ->     text "for" <+> -    parens (forInit init <> semi <+> mexpr incr <> semi <+> mexpr test) $$ -    stmt body+    parens (forInit init <> semi <+> maybe incr (ppExpression True) <> +            semi <+> maybe test (ppExpression True)) $$ +    ppStatement body   TryStmt _ stmt mcatch mfinally ->     text "try" $$ inBlock stmt $$ ppCatch $$ ppFinally      where ppFinally = case mfinally of@@ -88,22 +94,22 @@           ppCatch = case mcatch of             Nothing -> empty             Just (CatchClause _ id s) -> -              text "catch" <+> (parens.pp) id <+> inBlock s-  ThrowStmt _ e -> text "throw" <+> expr e <> semi-  WithStmt _ expr s ->  text "with" <+> inParens expr $$ stmt s+              text "catch" <+> (parens.ppId) id <+> inBlock s+  ThrowStmt _ e -> text "throw" <+> ppExpression True e <> semi+  WithStmt _ e s -> text "with" <+> parens (ppExpression True e) $$ ppStatement s   VarDeclStmt _ decls ->-    text "var" <+> cat (punctuate comma (map varDecl decls)) <> semi-  FunctionStmt _ name args s ->-    text "function" <+> pp name <> -    parens (cat $ punctuate comma (map pp args)) $$ -    inBlock s+    text "var" <+> cat (punctuate comma (map (ppVarDecl True) decls)) <> semi+  FunctionStmt _ name args body ->+    text "function" <+> ppId name <> +    parens (cat $ punctuate comma (map ppId args)) $$ +    asBlock body  stmtList :: [Statement a] -> Doc-stmtList = vcat . map stmt+stmtList = vcat . map ppStatement  prop :: Prop a -> Doc prop p = case p of-  PropId _ id -> pp id+  PropId _ id -> ppId id   PropString _ str -> doubleQuotes (text (jsEscape str))   PropNum _ n -> text (show n) @@ -173,57 +179,186 @@     sel '\\' = "\\\\"     sel x    = [x]     -- We don't have to do anything about \X, \x and \u escape sequences.+    +regexpEscape :: String -> String+regexpEscape "" = ""+regexpEscape "\\" = "\\\\"+regexpEscape ('\\':c:rest) = '\\':c:(regexpEscape rest)+regexpEscape ('/':rest) = '\\':'/':regexpEscape rest+regexpEscape (c:rest)   = c:regexpEscape rest -lvalue :: LValue a -> Doc-lvalue (LVar _ x) = text x-lvalue (LDot _ e x) = expr e <> text "." <> text x-lvalue (LBracket _ e1 e2) = expr e1 <> brackets (expr e2)- -expr :: Expression a -> Doc-expr e = case e of -  StringLit _ str ->  doubleQuotes (text (jsEscape str))-  RegexpLit _ re global ci -> -    text "/" <> text re <> text "/" <> g <> i where-      g = if global then text "g" else empty-      i = if ci then text "i" else empty-  NumLit _ n ->  text (show n)+ppLValue :: LValue a -> Doc+ppLValue (LVar _ x) = text x+ppLValue (LDot _ e x) = ppMemberExpression e <> text "." <> text x+ppLValue (LBracket _ e1 e2) = ppMemberExpression e1 <> +                              brackets (ppExpression True e2)++-- 11.1+ppPrimaryExpression :: Expression a -> Doc+ppPrimaryExpression e = case e of+  ThisRef _ -> text "this"+  VarRef _ id -> ppId id+  NullLit _ -> text "null"+  BoolLit _ True -> text "true"+  BoolLit _ False -> text "false"+  NumLit  _ n -> text (show n)   IntLit _ n ->  text (show n)-  BoolLit _ True ->  text "true"-  BoolLit _ False ->  text "false"-  NullLit _ ->  text "null"-  ArrayLit _ es ->  brackets $ cat $ punctuate comma (map expr es)+  StringLit _ str -> doubleQuotes (text (jsEscape str))+  RegexpLit _ reg g ci -> text "/" <> (text (regexpEscape reg)) <> text "/" <>+                          (if g then text "g" else empty) <> +                          (if ci then text "i" else empty)+  ArrayLit _ es -> +    brackets $ cat $ punctuate comma (map (ppAssignmentExpression True) es)   ObjectLit _ xs ->       braces (hsep (punctuate comma (map pp' xs))) where-      pp' (n,v) =  prop n <> colon <+> expr v-  ThisRef _ ->  text "this"-  VarRef _ id ->  pp id-  DotRef _ e' id -> expr e' <> text "." <> pp id-  BracketRef _ container key -> expr container <> brackets (expr key)-  NewExpr _ constr args -> -    text "new" <+> expr constr <> -    parens (cat $ punctuate comma (map expr args))-  PrefixExpr _ op e' -> prefixOp op <+> expr e'-  InfixExpr _ op left right -> expr left <+> infixOp op <+> expr right-  CondExpr _ test cons alt -> -    expr test <+> text "?" <+> expr cons <+> colon <+> expr alt-  AssignExpr _ op l r ->  lvalue l <+> assignOp op <+> expr r-  UnaryAssignExpr _ op e' -> case op of-    PrefixInc -> text "++" <> lvalue e'-    PrefixDec -> text "--" <> lvalue e'-    PostfixInc -> lvalue e' <> text "++"-    PostfixDec -> lvalue e' <> text "--"-  ParenExpr _ e' ->  parens (expr e')-  ListExpr _ es ->  cat $ punctuate comma (map expr es)-  CallExpr _ f args -> -    expr f <> parens (cat $ punctuate comma (map expr args))-  FuncExpr _ name args body -> -    text "function" <+> text (maybe "" unId name) <+>-    parens (cat $ punctuate comma (map pp args)) $$ -    inBlock body+      pp' (n,v) =  prop n <> colon <+> ppAssignmentExpression True v+  _ -> parens $ ppExpression True e -mexpr :: Maybe (Expression a) -> Doc-mexpr Nothing = empty-mexpr (Just e) = expr e+-- 11.2+ppMemberExpression :: Expression a -> Doc+ppMemberExpression e = case e of+  FuncExpr _ name params body -> +    text "function" <+> maybe name ppId <+>+    parens (cat $ punctuate comma (map ppId params)) $$ +    asBlock body+  DotRef _ obj id -> ppMemberExpression obj <> text "." <> ppId id+  BracketRef _ obj key -> +    ppMemberExpression obj <> brackets (ppExpression True key)  +  NewExpr _ ctor args -> +    text "new" <+> ppMemberExpression ctor <> ppArguments args+  _ -> ppPrimaryExpression e++ppCallExpression :: Expression a -> Doc+ppCallExpression e = case e of+  CallExpr _ f args -> ppCallExpression f <> ppArguments args+  DotRef _ obj id -> ppCallExpression obj <> text "." <> ppId id+  BracketRef _ obj key ->ppCallExpression obj <> brackets (ppExpression True key)+  _ -> ppMemberExpression e  +    +ppArguments :: [Expression a] -> Doc+ppArguments es = +  parens $ cat $ punctuate comma (map (ppAssignmentExpression True) es)++ppLHSExpression :: Expression a -> Doc+ppLHSExpression = ppCallExpression++-- 11.3+ppPostfixExpression :: Expression a -> Doc+ppPostfixExpression e = case e of+  UnaryAssignExpr _ PostfixInc e' -> ppLValue e' <> text "++"+  UnaryAssignExpr _ PostfixDec e' -> ppLValue e' <> text "--"+  _ -> ppLHSExpression e+  +-- 11.4+ppUnaryExpression :: Expression a -> Doc+ppUnaryExpression e = case e of+  PrefixExpr _ op e' -> prefixOp op <+> ppUnaryExpression e'+  UnaryAssignExpr _ PrefixInc e' -> text "++" <> ppLValue e'+  UnaryAssignExpr _ PrefixDec e' -> text "--" <> ppLValue e'+  _ -> ppPostfixExpression e++-- 11.5+ppMultiplicativeExpression :: Expression a -> Doc+ppMultiplicativeExpression e = case e of+  InfixExpr _ op e1 e2 | op `elem` [OpMul, OpDiv, OpMod] -> +    ppMultiplicativeExpression e1 <+> infixOp op <+> ppUnaryExpression e2+  _ -> ppUnaryExpression e+  +-- 11.6+ppAdditiveExpression :: Expression a -> Doc+ppAdditiveExpression e = case e of+  InfixExpr _ op e1 e2 | op `elem` [OpAdd, OpSub] -> +    ppAdditiveExpression e1 <+> infixOp op <+> ppMultiplicativeExpression e2+  _ -> ppMultiplicativeExpression e++-- 11.7+ppShiftExpression :: Expression a -> Doc+ppShiftExpression e = case e of+  InfixExpr _ op e1 e2 | op `elem` [OpLShift, OpSpRShift, OpZfRShift] -> +    ppShiftExpression e1 <+> infixOp op <+> ppAdditiveExpression e2  +  _ -> ppAdditiveExpression e++-- 11.8.  +-- | @ppRelationalExpression True@ is RelationalExpression,+-- @ppRelationalExpression False@ is RelationalExpressionNoIn+ppRelationalExpression :: Bool -> Expression a -> Doc+ppRelationalExpression hasIn e = +  let opsNoIn = [OpLT, OpGT, OpLEq, OpGEq, OpInstanceof]+      ops     = if hasIn then OpIn:opsNoIn else opsNoIn+  in case e of    +    InfixExpr _ op e1 e2 | op `elem` ops -> +      ppRelationalExpression hasIn e1 <+> infixOp op <+> ppShiftExpression e2+    _ -> ppShiftExpression e+    +-- 11.9+ppEqualityExpression :: Bool -> Expression a -> Doc+ppEqualityExpression hasIn e = case e of+  InfixExpr _ op e1 e2 | op `elem` [OpEq, OpNEq, OpStrictEq, OpStrictNEq] ->+    ppEqualityExpression hasIn e1 <+> infixOp op <+> +    ppRelationalExpression hasIn e2+  _ -> ppRelationalExpression hasIn e+  +-- 11.10+ppBitwiseANDExpression :: Bool -> Expression a -> Doc+ppBitwiseANDExpression hasIn e = case e of+  InfixExpr _ op@OpBAnd e1 e2 -> ppBitwiseANDExpression hasIn e1 <+> +                                 infixOp op <+>+                                 ppEqualityExpression hasIn e2+  _ -> ppEqualityExpression hasIn e+  +ppBitwiseXORExpression :: Bool -> Expression a -> Doc+ppBitwiseXORExpression hasIn e = case e of+  InfixExpr _ op@OpBXor e1 e2 -> ppBitwiseXORExpression hasIn e1 <+>+                                 infixOp op <+>+                                 ppBitwiseANDExpression hasIn e2+  _ -> ppBitwiseANDExpression hasIn e+  +ppBitwiseORExpression :: Bool -> Expression a -> Doc+ppBitwiseORExpression hasIn e = case e of+  InfixExpr _ op@OpBOr e1 e2 -> ppBitwiseORExpression hasIn e1 <+>+                                infixOp op <+>+                                ppBitwiseXORExpression hasIn e2+  _ -> ppBitwiseXORExpression hasIn e++-- 11.11+ppLogicalANDExpression :: Bool -> Expression a -> Doc+ppLogicalANDExpression hasIn e = case e of+  InfixExpr _ op@OpLAnd e1 e2 -> ppLogicalANDExpression hasIn e1 <+>+                                 infixOp op <+>+                                 ppBitwiseORExpression hasIn e2+  _ -> ppBitwiseORExpression hasIn e                                 +                                 +ppLogicalORExpression :: Bool -> Expression a -> Doc+ppLogicalORExpression hasIn e = case e of+  InfixExpr _ op@OpLOr e1 e2 -> ppLogicalORExpression hasIn e1 <+>+                                infixOp op <+>+                                ppLogicalANDExpression hasIn e2+  _ -> ppLogicalANDExpression hasIn e+  +-- 11.12+ppConditionalExpression :: Bool -> Expression a -> Doc+ppConditionalExpression hasIn e = case e of+  CondExpr _ c et ee -> ppLogicalORExpression hasIn c <+> text "?" <+> +                        ppAssignmentExpression hasIn et <+> colon <+>+                        ppAssignmentExpression hasIn ee+  _ -> ppLogicalORExpression hasIn e++-- 11.13+ppAssignmentExpression :: Bool -> Expression a -> Doc+ppAssignmentExpression hasIn e = case e of+  AssignExpr _ op l r -> ppLValue l <+> assignOp op <+> +                         ppAssignmentExpression hasIn r+  _ -> ppConditionalExpression hasIn e+  +-- 11.14+ppExpression :: Bool -> Expression a -> Doc+ppExpression hasIn e = case e of+  ListExpr _ es -> cat $ punctuate comma (map (ppExpression hasIn) es)+  _ -> ppAssignmentExpression hasIn e++maybe :: Maybe a -> (a -> Doc) -> Doc+maybe Nothing  _ = empty+maybe (Just a) f = f a  -- | Renders a JavaScript program as a document, the show instance of -- 'Doc' will pretty-print it automatically
src/Language/ECMAScript3/Syntax.hs view
@@ -1,4 +1,9 @@--- |ECMAScript 3 syntax. /Spec/ refers to the ECMA-262 specification, 3rd edition.+-- |ECMAScript 3 syntax. /Spec/ refers to the ECMA-262 specification,+-- 3rd edition.+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE DeriveFoldable #-} module Language.ECMAScript3.Syntax (JavaScript(..)                                    ,unJavaScript                                    ,Statement(..)@@ -147,11 +152,10 @@     -- ^ @e1 ? e2 : e3@, spec 11.12   | AssignExpr a AssignOp (LValue a) (Expression a)     -- ^ @e1 \@=e2@, spec 11.13-  | ParenExpr a (Expression a) -- ^ @(e)@, spec 11.1.6   | ListExpr a [Expression a] -- ^ @e1, e2@, spec 11.14   | CallExpr a (Expression a) [Expression a] -- ^ @f(x,y,z)@, spec 11.2.3   --funcexprs are optionally named-  | FuncExpr a (Maybe (Id a)) [Id a] (Statement a) +  | FuncExpr a (Maybe (Id a)) [Id a] [Statement a]     -- ^ @function f (x,y,z) {...}@, spec 11.2.5, 13   deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable) @@ -220,7 +224,7 @@     -- ^ @with (o) stmt@, spec 12.10   | VarDeclStmt a [VarDecl a]     -- ^ @var x, y=42;@, spec 12.2-  | FunctionStmt a (Id a) {-name-} [Id a] {-args-} (Statement a) {-body-}+  | FunctionStmt a (Id a) {-name-} [Id a] {-args-} [Statement a] {-body-}     -- ^ @function f(x, y, z) {...}@, spec 13   deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable)   
src/Language/ECMAScript3/Syntax/Annotations.hs view
@@ -64,7 +64,6 @@    (InfixExpr a op e1 e2)       -> a    (CondExpr a g et ef)         -> a    (AssignExpr a op lv e)       -> a-   (ParenExpr a e)              -> a    (ListExpr a es)              -> a    (CallExpr a fn params)       -> a    (FuncExpr a mid args s)      -> a
+ src/Language/ECMAScript3/Syntax/Arbitrary.hs view
@@ -0,0 +1,383 @@+{-# LANGUAGE TemplateHaskell #-}+-- | QuickCheck $Arbitrary$ instances for ECMAScript 3 abstract+-- syntax.++module Language.ECMAScript3.Syntax.Arbitrary where++import Language.ECMAScript3.Syntax+import Test.QuickCheck hiding (Prop)+import Test.QuickCheck.Arbitrary+import Test.QuickCheck.Property (forAllShrink)+import Data.Map hiding (map,null,filter,foldr)+import Data.List (nub,delete)+import Data.Data+import Data.Char+import Data.Generics.Uniplate.Data+import Data.Generics.Uniplate.Operations+import Data.Generics.Str+import Control.Monad+import Control.Monad.State+import Data.Maybe (maybeToList)++instance Arbitrary (AssignOp) where+  arbitrary = +    elements [OpAssign, OpAssignAdd, OpAssignSub, OpAssignMul, OpAssignDiv, +              OpAssignMod, OpAssignLShift, OpAssignSpRShift, OpAssignZfRShift,+              OpAssignBAnd, OpAssignBXor, OpAssignBOr]++instance Arbitrary (InfixOp) where+  arbitrary = +    elements [OpLT, OpLEq, OpGT, OpGEq , OpIn , OpInstanceof, OpEq, OpNEq, +              OpStrictEq, OpStrictNEq, OpLAnd, OpLOr,+              OpMul, OpDiv, OpMod , OpSub, OpLShift, OpSpRShift,+              OpZfRShift, OpBAnd, OpBXor, OpBOr, OpAdd]+  +instance Arbitrary (UnaryAssignOp) where+  arbitrary = +    elements [PrefixInc, PrefixDec, PostfixInc, PostfixDec]+  +instance Arbitrary (PrefixOp) where+  arbitrary = +    elements [PrefixLNot, PrefixBNot, PrefixPlus, PrefixMinus, +              PrefixTypeof, PrefixVoid, PrefixDelete]+++instance Arbitrary a => Arbitrary (Id a) where+  arbitrary = liftM2 Id arbitrary identifier+  shrink (Id a s) = [Id na ns | ns <- shrink s, na <- shrink a]++instance Arbitrary a => Arbitrary (CaseClause a) where+  arbitrary = oneof [caseclause, casedefault]+    where caseclause = liftM3 CaseClause arbitrary arbitrary arbitrary+          casedefault = liftM2 CaseDefault arbitrary arbitrary+  shrink (CaseClause a expr stmts) = +    [CaseClause na ne ns | na <- shrink a, ne <- shrink expr, ns <- shrink stmts]+  shrink (CaseDefault a stmts) = +    [CaseDefault na ns | na <- shrink a, ns <- shrink stmts]+                         +instance Arbitrary a => Arbitrary (Prop a) where+  arbitrary = oneof [liftM2 PropId arbitrary arbitrary,+                     liftM2 PropString arbitrary nonEmptyString,+                     liftM2 PropNum arbitrary nonNegative+                    ]+  shrink (PropId a id) = [PropId na nid | nid <- shrink id, na <- shrink a] +  shrink (PropString a s) = [PropString na ns | ns <- shrink s, na <- shrink a] +  shrink (PropNum a i) = [PropNum na ni | ni <- shrink i, na <- shrink a] +  +instance Arbitrary a => Arbitrary (LValue a) where  +  arbitrary = oneof [liftM2 LVar arbitrary identifier,+                     liftM3 LDot arbitrary arbitrary identifier,+                     liftM3 LBracket arbitrary arbitrary arbitrary]+  shrink (LVar a s) = [LVar na ns | ns <- shrink s, na <- shrink a]+  shrink (LDot a e s) = [LDot na ne ns | ne <- shrink e, ns <-shrink s, na <-shrink a]+  shrink (LBracket a e1 e2) = [LBracket na ne1 ne2 | ne1 <- shrink e1, ne2 <-shrink e2, na <- shrink a]+  +cshrink :: Arbitrary a => [a] -> [a]+cshrink = concat . shrink++identifier :: Gen String+identifier = sized sizedIdent+    where sizedIdent n = do s <- identStart+                            rest <- identRest (n-1)+                            return (s:rest)+          identStart = arbitrary `suchThat` isIdentStart+          identRest n | n < 1 = return ""+          identRest n = do p <- identPart+                           rest <- identRest (n-1)+                           return (p:rest)+          identPart = do arbitrary `suchThat` isIdentPart+          isIdentStart c = isLetter c || c == '$' || c == '_'+          isIdentPart c = isIdentStart c || isMark c || isNumber c++-- minimum size generator+type MSGen a = (Int, Gen a)++sGen :: [MSGen a] -> Gen a+sGen gens = +  sized f +  where f n | n >= 0 = oneof $ map snd (filter (\(m, _) -> n >= m) gens)+        f _          = f 0++recursive :: Gen a -> Gen a+recursive g = sized (\n -> resize (n-1) g)++rarbitrary :: Arbitrary a => Gen a+rarbitrary = recursive arbitrary++rrarbitrary :: Arbitrary a => Gen a+rrarbitrary = recursive $ recursive arbitrary++atLeastOfSize :: Arbitrary a => Int -> Gen a -> Gen a+atLeastOfSize l gen = sized $ \s -> if s < l then resize l gen else gen++nonEmptyString :: Gen String+nonEmptyString = sized $ \s -> if s < 1 then stringOfLength 1 else stringOfLength s++regexpBody = nonEmptyString++nonNegative :: (Arbitrary a, Num a) => Gen a+nonNegative = liftM abs arbitrary++stringOfLength :: Int -> Gen String+stringOfLength 0 = return ""+stringOfLength n = do c <- arbitrary+                      rs <- stringOfLength (n-1)+                      return (c:rs)++instance Arbitrary a => Arbitrary (Expression a) where+  arbitrary = +    sGen [(0, liftM  ThisRef arbitrary),+          (0, liftM  NullLit arbitrary),+          (0, liftM2 StringLit arbitrary arbitrary),+          (0, liftM2 NumLit arbitrary nonNegative),+          (0, liftM2 IntLit arbitrary nonNegative),+          (0, liftM2 BoolLit arbitrary arbitrary),+          (0, liftM4 RegexpLit arbitrary regexpBody arbitrary arbitrary),+          (1, liftM2 ArrayLit arbitrary rarbitrary),+          (1, liftM2 ObjectLit arbitrary rarbitrary),+          (0, liftM2 VarRef arbitrary arbitrary),+          (1, liftM3 DotRef arbitrary rarbitrary arbitrary),+          (2, liftM3 BracketRef arbitrary rarbitrary rarbitrary),+          (3, liftM3 NewExpr arbitrary rarbitrary rrarbitrary),+          (1, liftM3 PrefixExpr arbitrary arbitrary rarbitrary),+          (2, liftM3 UnaryAssignExpr arbitrary arbitrary rarbitrary),+          (2, liftM4 InfixExpr arbitrary arbitrary rarbitrary rarbitrary),+          (3, liftM4 CondExpr arbitrary rarbitrary rarbitrary rarbitrary),+          (3, liftM4 AssignExpr arbitrary rarbitrary rarbitrary rarbitrary),+          (3, liftM2 ListExpr arbitrary (recursive (atLeastOfSize 2 arbitrary))),+          (3, liftM3 CallExpr arbitrary rarbitrary rrarbitrary),+          (1, liftM4 FuncExpr arbitrary arbitrary arbitrary rarbitrary)]+    +  shrink (StringLit a s) = [StringLit na ns | na <- shrink a, ns <- shrink s]+  shrink (RegexpLit a s b1 b2) = [RegexpLit na ns nb1 nb2 | na <- shrink a, nb1 <- shrink b1, nb2 <- shrink b2, ns <- shrink s]+  shrink (NumLit a d) = [NumLit na nd | na <- shrink a, nd <- shrink d]+  shrink (IntLit a i) = [IntLit na ni | na <- shrink a, ni <- shrink i]+  shrink (BoolLit a b) = [BoolLit na nb | na <- shrink a, nb <- shrink b]+  shrink (NullLit a) = [NullLit na | na <- shrink a]+  shrink (ArrayLit a xs) = (cshrink xs) ++ xs ++ [ArrayLit na nxs | na <- shrink a, nxs <- shrink xs]+  shrink (ObjectLit a xs) =  +    let es = map snd xs in+    (cshrink es) ++ es +++    [ObjectLit na nxs | na <- shrink a, nxs <- shrink xs]+  shrink (ThisRef a) = [ThisRef na | na <- shrink a]+  shrink (VarRef a id) = [VarRef na nid | na <- shrink a, nid <- shrink id]+  shrink (DotRef a e id) = [DotRef na ne nid | na <-shrink a, nid <- shrink id,  ne <- shrink e]+  shrink (BracketRef a o k) = [BracketRef na no nk | na <- shrink a, no <-shrink o, nk <- shrink k]+  shrink (NewExpr a c xs) = (shrink c) ++ [c] ++ (cshrink xs) ++ xs ++ [NewExpr na nc nxs | na <- shrink a, nc <- shrink c,  nxs <- shrink xs]+  shrink (PrefixExpr a op e) = (shrink e) ++ [e] ++ [PrefixExpr na nop ne | na <- shrink a, nop <-shrink op, ne <- shrink e]+  shrink (UnaryAssignExpr a op v) = [UnaryAssignExpr na nop nv | na <- shrink a, nop <- shrink op, nv <- shrink v]+  shrink (InfixExpr a op e1 e2) = (shrink e1) ++ [e1] ++ (shrink e2) ++ [e2] ++ [InfixExpr na nop ne1 ne2 | na <- shrink a, nop <- shrink op, ne1 <- shrink e1, ne2 <- shrink e2]+  shrink (CondExpr a e1 e2 e3) = (shrink e1) ++ [e1] ++ (shrink e2) ++ [e2] ++ (shrink e3) ++ [e3] ++ [CondExpr na ne1 ne2 ne3 | na <- shrink a, ne1 <- shrink e1, ne2 <- shrink e2, ne3 <- shrink e3]+  shrink (AssignExpr a op v e) = (shrink e) ++ [e] ++ [AssignExpr na nop nv ne | na <- shrink a, nop <- shrink op, nv <- shrink v, ne <-shrink e] +  shrink (ListExpr a es) = (cshrink es) ++ es ++ [ListExpr na nes | na <- shrink a, nes <- shrink es]+  shrink (CallExpr a e es) = (shrink e) ++ [e] ++ (cshrink es) ++ es ++ [CallExpr na ne nes | na <- shrink a, ne <- shrink e, nes <- shrink es]+  shrink (FuncExpr a mid ids s) = [FuncExpr na nmid nids ns | na <- shrink a, nmid <-  shrink mid, nids <- shrink ids, ns <- shrink s]++instance Arbitrary a => Arbitrary (ForInInit a) where+  arbitrary = oneof [liftM ForInVar arbitrary,+                     liftM ForInLVal arbitrary]+  shrink (ForInVar id) = [ForInVar nid | nid <- shrink id]+  shrink (ForInLVal id) = [ForInLVal nid | nid <- shrink id]+  +instance Arbitrary a => Arbitrary (ForInit a) where  +  arbitrary = +    frequency [+      (2, return NoInit),+      (1, liftM VarInit arbitrary),+      (1, liftM ExprInit arbitrary)]+  shrink (NoInit) = []+  shrink (VarInit vds) = [VarInit nvds | nvds <- shrink vds]+  shrink (ExprInit e) = [ExprInit ne | ne <- shrink e]++instance Arbitrary a => Arbitrary (CatchClause a) where+  arbitrary = liftM3 CatchClause arbitrary arbitrary arbitrary+  shrink (CatchClause a id s) = [CatchClause na nid ns | na <- shrink a, nid <- shrink id, ns <- shrink s]+  +instance Arbitrary a => Arbitrary (VarDecl a) where+  arbitrary = liftM3 VarDecl arbitrary arbitrary arbitrary+  shrink (VarDecl a id me) = [VarDecl na nid nme | na <- shrink a, nid <- shrink id, nme <- shrink me]++instance Arbitrary a => Arbitrary (Statement a) where+  arbitrary = +    sGen [(2, liftM2 BlockStmt arbitrary rrarbitrary),+          (0, liftM  EmptyStmt arbitrary),+          (1, liftM2 ExprStmt arbitrary rarbitrary),+          (3, liftM4 IfStmt arbitrary rarbitrary rarbitrary rarbitrary),+          (2, liftM3 IfSingleStmt arbitrary rarbitrary rarbitrary),+          (3, liftM3 SwitchStmt arbitrary rarbitrary rrarbitrary),+          (2, liftM3 WhileStmt arbitrary rarbitrary rarbitrary),+          (2, liftM3 DoWhileStmt arbitrary rarbitrary rarbitrary),+          (0, liftM2 BreakStmt arbitrary arbitrary),+          (0, liftM2 ContinueStmt arbitrary arbitrary),+          (1, liftM3 LabelledStmt arbitrary arbitrary rarbitrary),+          (3, liftM4 ForInStmt arbitrary rarbitrary rarbitrary rarbitrary),+          (4, liftM5 ForStmt arbitrary rarbitrary rarbitrary rarbitrary rarbitrary),+          (4, arbtry),+          (1, liftM2 ThrowStmt arbitrary rarbitrary),+          (1, liftM2 ReturnStmt arbitrary rarbitrary),+          (2, liftM3 WithStmt arbitrary rarbitrary rarbitrary),+          (2, liftM2 VarDeclStmt arbitrary rrarbitrary),+          (1, liftM4 FunctionStmt arbitrary arbitrary arbitrary rarbitrary)]+    where arbtry = +            do (mCatch, mFinally) <- oneof [liftM2 (,) (return Nothing) (liftM Just rarbitrary),+                                            liftM2 (,) (liftM Just rarbitrary) (return Nothing),+                                            liftM2 (,) (liftM Just rarbitrary) (liftM Just rarbitrary)]+               a <- arbitrary                      +               body <- rarbitrary+               return $ TryStmt a body mCatch mFinally+    +  shrink (BlockStmt a body) = emptyStmtShrink a ++ +                              [BlockStmt as bs | as <- shrink a, bs <- shrink body]+  shrink (EmptyStmt a) = emptyStmtShrink a+  shrink (ExprStmt a e) = emptyStmtShrink a ++ +                          [ExprStmt as es | as <- shrink a, es <- shrink e]+  shrink (IfStmt a e th el) = emptyStmtShrink a +++                              [IfStmt as es ths els | as <- shrink a, es <- shrink e, ths <- shrink th, els <- shrink el]+  shrink (IfSingleStmt a e th) = emptyStmtShrink a +++                                 [IfSingleStmt as es ths | as <- shrink a, es <- shrink e, ths <- shrink th]+  shrink (SwitchStmt a e cases) = emptyStmtShrink a +++                                  [SwitchStmt as es cs | as <- shrink a, es <-shrink e, cs <- shrink cases] +  shrink (WhileStmt a e b) = emptyStmtShrink a +++                             [WhileStmt as es bs | as <- shrink a, es <- shrink e, bs <- shrink b]+  shrink (DoWhileStmt a b e) = emptyStmtShrink a ++  +                               [DoWhileStmt as bs es | as <- shrink a, es <- shrink e, bs <- shrink b]+  shrink (BreakStmt a l) = emptyStmtShrink a +++                           [BreakStmt as ls | as <- shrink a, ls <- shrink l]+  shrink (ContinueStmt a l) = emptyStmtShrink a +++                              [ContinueStmt as ls | as <- shrink a, ls <- shrink l]+  shrink (LabelledStmt a l s) = emptyStmtShrink a +++                                [LabelledStmt as ls ss | as <- shrink a, ls <- shrink l, ss <- shrink s]+  shrink (ForInStmt a i o s) = emptyStmtShrink a +++                               [ForInStmt as is os ss | as <- shrink a, is <-shrink i, os <-shrink o, ss <- shrink s]+  shrink (ForStmt a i e1 e2 s) = emptyStmtShrink a +++                                 [ForStmt as is e1s e2s ss | as <- shrink a, is <- shrink i, e1s <- shrink e1, e2s <- shrink e2, ss <- shrink s]+  shrink (TryStmt a b cs mf) = emptyStmtShrink a +++                               [TryStmt as bs css mfs | as <- shrink a, bs <- shrink b, css <- shrink cs, mfs <- shrink mf]+  shrink (ThrowStmt a e) = emptyStmtShrink a +++                           [ThrowStmt as es | as <- shrink a, es <- shrink e]+  shrink (ReturnStmt a e) = emptyStmtShrink a +++                            [ReturnStmt as es | as <- shrink a, es <- shrink e]+  shrink (WithStmt a o s) = emptyStmtShrink a +++                            [WithStmt as os ss | as <- shrink a, os <- shrink o, ss <- shrink s]+  shrink (VarDeclStmt a vds) = emptyStmtShrink a +++                               [VarDeclStmt as vdss | as <- shrink a, vdss <- shrink vds]+  shrink (FunctionStmt a n pars b) = emptyStmtShrink a +++                                     [FunctionStmt as ns parss bs | as <- shrink a, ns <- shrink n, parss <- shrink pars, bs <- shrink b]+    +emptyStmtShrink a = [EmptyStmt a2 | a2 <- shrink a]    ++type LabelSubst   = Map (Id ()) (Id ())+emptyConstantPool = Data.Map.empty++instance (Data a, Arbitrary a) => Arbitrary (JavaScript a) where+  arbitrary = do {s <- liftM2 Script arbitrary arbitrary;+                  if isProgramFixable s then fixLabels s+                  else arbitrary}+  shrink (Script a ss) = [Script na nss | na <- shrink a, nss <- shrink ss]+  +-- | Fixes labels so that labeled breaks and continues refer to+-- existing labeled statements, enclosing them; also, reduces the size+-- of the label set. Assumes that the program has a proper syntactic+-- structure, i.e. 'isProgramFixable' s = True.+fixLabels :: (Data a) => JavaScript a -> Gen (JavaScript a)+fixLabels s = +  fixBreakContinueLabels s >>= removeDuplicateLabels+          +-- | choose n elements from a list randomly+rChooseElem :: [a] -> Int -> Gen [a]+rChooseElem xs n | n > 0 && (not $ null xs) = +  if n >= length xs then return xs+  else (vectorOf n $ choose (0, n-1)) >>=+       (\subst -> return $ foldr (\n ys -> (xs!!n):ys) [] subst)+rChooseElem _  _ = return [] ++-- | A predicate that tells us whether a program has a fixable/correct+-- label-break/continue structure.  The predicate imposes syntactic+-- restrictions on the break, continue and labeled statements as in+-- the ECMA spec+isProgramFixable :: (Data a ) => JavaScript a -> Bool+isProgramFixable (Script _ stmts) = +  Prelude.and $ +  Prelude.map +             (\stmt -> isBreakContinueFixable stmt False False False) +             stmts++-- | Imposes relaxed restrictions on break and continue per ECMAScript+-- 5 spec (page 92): any continue without a label should be nested+-- within an iteration stmt, any continue with a label should be+-- nested in a labeled statement (not necessarily with the same+-- label); any break statement without a label should be nested in an+-- iteration or switch stmt, any break statement with a label should+-- be nested in a labeled statement (not necessarily with the same+-- label).+isBreakContinueFixable :: (Data a) => Statement a -> +                                      Bool -> +                                      Bool -> +                                      Bool ->+                                      Bool+isBreakContinueFixable stmt inLabeled inIter inSwitch =+  case stmt of+    ContinueStmt _ Nothing -> inIter+    ContinueStmt _ (Just label) -> inLabeled+    BreakStmt    _ Nothing -> inIter || inSwitch+    BreakStmt    _ (Just label) -> inLabeled+    LabelledStmt _ label _ -> +      continue stmt True inIter inSwitch+    _ -> if isIterationStmt stmt then+             continue stmt inLabeled True inSwitch+         else if isSwitchStmt stmt then+                  continue stmt inLabeled inIter True +              else True+  --  _ -> continue stmt inLabeled inIter inSwitch+  where continue stmt inLabeled inIter inSwitch =+                   and $ map (\s -> isBreakContinueFixable s inLabeled inIter inSwitch) (children stmt)+                   +-- | Removes duplicate labels from nested labeled statements in order+-- to impose restrictions on labeled statements as per ECMAScript 5+-- spec (page 95): nested labeled statements cannot have duplicating+-- labels.+removeDuplicateLabels :: Data a => JavaScript a -> Gen (JavaScript a)+removeDuplicateLabels (Script x stmts) =+    return $ Script x (map (\stmt -> (evalState (transformM removeDL stmt) [])) stmts)+    where+      removeDL :: Statement a -> State [String] (Statement a)+      removeDL stmt@(LabelledStmt x lab s) = +          do {enclosingLabels <- get;+              if Prelude.elem (unId lab) enclosingLabels then return s+              else modify ((:) $ unId lab) >> return stmt}+      removeDL s = return s        +      +-- | Selects a random element of the list+selectRandomElement :: [a] -> Gen a+selectRandomElement xs = +  let l = length xs in+  do n <- arbitrary+     return $ xs !! (n `mod` l - 1)+-- | Changes labels of break/continue so that they refer to one of the+-- enclosing labels+fixBreakContinueLabels :: Data a => JavaScript a -> Gen (JavaScript a)+fixBreakContinueLabels (Script x stmts) =+  do stmts2 <- mapM (\stmt -> (evalStateT (fixBCL stmt) [])) stmts+     return $ Script x stmts2+    where+      fixBCL :: Data a => Statement a -> StateT [String] Gen (Statement a)+      fixBCL stmt@(LabelledStmt _ lab s) =+        do modify ((:) $ unId lab)+           descendM fixBCL stmt+      fixBCL stmt@(BreakStmt x (Just (Id y lab))) =+          do {labels <- get;+              if lab `notElem` labels then+                  do {newLab <- lift $ selectRandomElement labels;+                      return $ BreakStmt x (Just $ Id y newLab)}+              else return stmt}+      fixBCL stmt@(ContinueStmt x (Just (Id y lab))) =+          do {labels <- get;+              if lab `notElem` labels then+                  do {newLab <- lift $ selectRandomElement labels;+                      return $ ContinueStmt x (Just $ Id y newLab)}+              else return stmt}+      fixBCL s = return s++isSwitchStmt :: Statement a    -> Bool+isSwitchStmt (SwitchStmt _ _ _) = True+isSwitchStmt _                  = False
+ src/PrettyTest.hs view
@@ -0,0 +1,30 @@+module Main where++import Language.ECMAScript3.Parser+import Language.ECMAScript3.PrettyPrint+import Language.ECMAScript3.Syntax+import Language.ECMAScript3.Syntax.Arbitrary+import Language.ECMAScript3.Syntax.Annotations+import Test.QuickCheck+import System.Exit++++main = +  let qcArgs = Args {maxSuccess = 50+                    ,maxDiscardRatio = 10+                    ,maxSize = 10+                    ,replay = Nothing+                    ,chatty = True}+  in quickCheckWithResult qcArgs prettyParseEquivalence >>= \res ->+  case res of+    Success {} -> putStrLn "All tests passes"+    GaveUp {} -> putStrLn "Gave up"+    Failure {} -> putStrLn "Test failed" >> exitFailure+    NoExpectedFailure {} -> putStrLn "Unexpected failure" >> exitFailure+        +prettyParseEquivalence :: JavaScript () -> Bool+prettyParseEquivalence js = +  case parseScriptFromString "" $ show $ javaScript js of+    Left _ -> False+    Right parsed -> (reannotate (const ()) parsed) == js
src/UnitTest.hs view
@@ -10,6 +10,8 @@  testDir = "tests/parse-pretty" ++-- | tests the parser with pre-defined test-cases parsePrettyTest filename = TestLabel filename $ TestCase $ do   js <- parseJavaScriptFromFile filename   let str = renderStatements js
tests/parse-pretty/flapjax-fxinternal-22dec2008.js view
@@ -1,8 +1,8 @@ function flapjaxInit(options) {   // compress via http://alex.dojotoolkit.org/shrinksafe/-  // make sure to change final eval call to use exported library renamed +  // make sure to change final eval call to use exported library renamed   // name-  +   var defaultOptions = {     includeSynonyms: true,     exportMisc: true,@@ -12,9 +12,9 @@     exportWS: true,     hide: [ ],     show: [ ],-    redefine: false,+    redefine: false   };-  +   if (options === false) {     options = { hide: [ ], show: [ ] };   }@@ -28,7 +28,7 @@       options[option] = defaultOptions[option];     }   };-  +   // Transform hide and show lists into tables   var hideArray = options.hide;   options.hide = { };@@ -40,26 +40,26 @@   for (var i = 0; i < showArray.length; i++) {     options.show[showArray[i]] = true;   }-  +   var warn = function(s) {     /*if (console && console.warn) {       console.warn(s);     }*/   };-   -  -  var flapjax = {     -    version: 4, +++  var flapjax = {+    version: 4,     base: {}, //pulses     combinators: {}, // combinators yielding nodes 	  behaviours: {},     dom: {} // dom convenience methods and combinators   };-  +   var d = flapjax.dom;-  + 	flapjax.pub = {util:flapjax};-  + 	var annotate = function(fn,names,protoArg,protoObjs,protoNames) { 		for(var i=0; i<names.length;i++) { 			flapjax.pub[names[i]] = fn;@@ -69,15 +69,15 @@ 				var args = slice(arguments,0); 				args.splice(protoArg,0,this); 				return fn.apply(this,args);-			}+			}; 			for(var i=0; i<protoObjs.length; i++) { 				for(var j=0; j<protoNames.length;j++) { 					protoObjs[i][protoNames[j]] = pf; 				} 			} 		}-	}-  +	};+   var exports = { };   var synonyms = { }; @@ -86,7 +86,7 @@   var dom = { }; /* Used as a symbol */   var domMisc = { }; /* Used as a symbol */   var ws = { }; /* Used as a symbol */-  +   var fxExport = function(exportCategory,exportVal,                           exportName /* , synonyms */) {     if (!(exportCategory instanceof Object)) {@@ -95,7 +95,7 @@      if (typeof(exportName) != 'string') {       console.log(exportVal);-      throw 'fxExport: name is ' + exportName;   +      throw 'fxExport: name is ' + exportName;     };      exportVal.__flapjaxCategory = exportCategory;@@ -104,8 +104,8 @@       exports[arguments[i]] = exportVal;       synonyms[arguments[i]] = true;     }-  }-  +  };+   var fxMethodSynonyms = function(obj,method) {     if (options.includeSynonyms === true) {       for (var i = 2; i < arguments.length; i++) {@@ -113,10 +113,10 @@       };     };   };-  +   //////////////////////////////////////////////////////////////////////////////   // Miscellaneous functions-  + 	//credit 4umi 	//slice: Array a * Integer * Integer -> Array a 	var slice = function (arr, start, stop) {@@ -128,7 +128,7 @@ 		for( i = 0; i < stop - start; i++ ) { r[i] = arr[start+i]; } 		return r; 	}-  + 	var isEqual = function (a,b) { 		return (a == b) || 			( (((typeof(a) == 'number') && isNaN(a)) || a == 'NaN') &&@@ -137,22 +137,22 @@  	//member: a * Array b -> Boolean 	var member = function(elt, lst) {-		for (var i = 0; i < lst.length; i++) { -			if (isEqual(lst[i], elt)) {return true;} +		for (var i = 0; i < lst.length; i++) {+			if (isEqual(lst[i], elt)) {return true;} 		} 		return false; 	};-  + 	var zip = function(arrays) { 		if (arrays.length == 0) return []; 		var ret = []; 		for(var i=0; i<arrays[0].length;i++) { 			ret.push([]);-			for(var j=0; j<arrays.length;j++) +			for(var j=0; j<arrays.length;j++) 				ret[i].push(arrays[j][i]); 		} 		return ret;-	}+	};  	//map: (a * ... -> z) * [a] * ... -> [z] 	var map = function (fn) {@@ -170,16 +170,16 @@ 			return ret; 		} 	};-	  + 	//filter: (a -> Boolean) * Array a -> Array a 	var filter = function (predFn, arr) { 		var res = [];-		for (var i = 0; i < arr.length; i++) { +		for (var i = 0; i < arr.length; i++) { 			if (predFn(arr[i])) { res.push(arr[i]); } 		} 		return res; 	};-	  +   //fold: (a * .... * accum -> accum) * accum * [a] * ... -> accum   //fold over list(s), left to right   var fold = function(fn, init /* arrays */) {@@ -195,7 +195,7 @@ 		else { 			var acc = init; 			for (var i = 0; i < lists[0].length; i++) {-				var args = map( function (lst) { return lst[i];}, +				var args = map( function (lst) { return lst[i];}, 		          lists); 				args.push(acc); 				acc = fn.apply({}, args);@@ -203,7 +203,7 @@ 			return acc; 		}   };-	  +   //foldR: (a * .... * accum -> accum) * accum * [a] * ... -> accum 	//fold over list(s), right to left, fold more memory efficient (left to right) 	var foldR = function (fn, init /* arrays */) {@@ -218,22 +218,22 @@ 		else { 			var acc = init; 			for (var i = lists[0].length - 1; i > -1; i--) {-				var args = map( function (lst) { return lst[i];}, +				var args = map( function (lst) { return lst[i];}, 		          lists); 				args.push(acc); 				acc = fn.apply({}, args); 			}-			return acc;     +			return acc; 		} 	};-  +   var pushAll = function(destArray,srcArray) {     for (var i = 0; i < srcArray.length; i++) {       destArray.push(srcArray[i]);     }     return destArray;   };-	  +   fxExport(misc,slice,'slice');   fxExport(misc,member,'member');   fxExport(misc,map,'map');@@ -241,10 +241,10 @@   fxExport(misc,filter,'filter');   fxExport(misc,fold,'fold');   fxExport(misc,foldR,'foldR');-  +   //////////////////////////////////////////////////////////////////////////////   // Flapjax core-  +   //Pulse: Stamp * Path * Obj   var Pulse = function (stamp, value) {     this.stamp = stamp;@@ -266,8 +266,8 @@ 				ctx.val[kvpos] = kv; 			}     };-    this.isEmpty = function () { -      return ctx.val.length === 0; +    this.isEmpty = function () {+      return ctx.val.length === 0;     };     this.pop = function () { 			if(ctx.val.length == 1) {@@ -296,13 +296,13 @@ 			return ret; 		};   };-  +   var lastRank = 0;   var stamp = 1;   var nextStamp = function () { return ++stamp; };-  -  //propagatePulse: Pulse * Array Node -> -  //Send the pulse to each node ++  //propagatePulse: Pulse * Array Node ->+  //Send the pulse to each node   var propagatePulse = function (pulse, node) {     var queue = new PQ(); //topological queue for current timestep 	queue.insert({k:node.rank,n:node,v:pulse});@@ -314,36 +314,36 @@ 		},new Pulse(qv.v.stamp,qv.v.value)); 	}   };-  +   //Event: Array Node b * ( (Pulse a -> Void) * Pulse b -> Void)   var EventStream = function (nodes,updater) {     this.updater = updater;-    +     this.sendsTo = []; //forward link-    +     for (var i = 0; i < nodes.length; i++) {       nodes[i].sendsTo.push(this);     }-    +     this.rank = ++lastRank;   }; 	EventStream.prototype = new Object();-  +   fxExport(core,EventStream,'EventStream');-  -  ++   //createNode: Array Node a * ( (Pulse b ->) * (Pulse a) -> Void) -> Node b   var createNode = function (nodes, updater) { 		return new EventStream(nodes,updater); 	};-  +   //attachListenerNode: Node * Node -> Voids   //flow from node to dependent   //note: does not add flow as counting for rank nor updates parent ranks   var attachListener = function (node, dependent) {     if (!(node instanceof EventStream)) { throw 'attachListenenerNode: expects event as first arg';} //SAFETY     if (!(dependent instanceof EventStream)) { throw 'attachListenenerNode: expects event as second arg';} //SAFETY-    +     node.sendsTo.push(dependent); 		if(node.rank > dependent.rank) { 			var lowest = lastRank+1;@@ -355,7 +355,7 @@ 			} 		}   };-  +   //removeListenerNode: Node * Node -> Boolean   //remove flow from node to dependent   //note: does not remove flow as counting for rank nor updates parent ranks@@ -363,7 +363,7 @@   {     if (!(node instanceof EventStream)) { throw 'removeListenerNode: expects event as first arg';} //SAFETY     if (!(dependent instanceof EventStream)) { throw 'removeListenenerNode: expects event as second arg';} //SAFETY-    +     var foundSending = false;     for (var i = 0; i < node.sendsTo.length && !foundSending; i++) {       if (node.sendsTo[i] == dependent) {@@ -371,23 +371,23 @@         foundSending = true;       }     }-    +     return foundSending;   };-  -  // An internal_e is a node that simply propagates all pulses it receives.  It's used internally by various ++  // An internal_e is a node that simply propagates all pulses it receives.  It's used internally by various   // combinators.   var internal_e = function(dependsOn) {     return createNode(dependsOn || [ ],function(send,pulse) { send(pulse); });   }-  +   var zero_e = function() {     return createNode([],function(send,pulse) {         throw ('zero_e : received a value; zero_e should not receive a value; the value was ' + pulse.value);     });   };   fxExport(core,zero_e,'zero_e');-  +   var one_e = function(val) {     var sent = false;     var evt = createNode([],function(send,pulse) {@@ -401,7 +401,7 @@     return evt;   };   fxExport(core,one_e,'one_e');-  +   // a.k.a. mplus; merge_e(e1,e2) == merge_e(e2,e1)   var merge_e = function() {     if (arguments.length == 0) {@@ -428,10 +428,10 @@     });   };   fxMethodSynonyms(EventStream,'constant_e','constant','replaceValue_e','replaceValue');-  +   var constant_e = function(e) { return e.constant_e(); };   fxExport(core,constant_e,'constant_e','replaceValue_e');-  + 	var createTimeSyncNode = function(nodes) { 		var nqs = map(function(n) { 				var qpulse = [];@@ -445,32 +445,32 @@           s(p);       }}); 	};-  + 	//This is up here so we can add things to its prototype that are in flapjax.combinators   var Behaviour = function (event, init, updater) {-    if (!(event instanceof EventStream)) { -      throw 'Behaviour: expected event as second arg'; +    if (!(event instanceof EventStream)) {+      throw 'Behaviour: expected event as second arg';     }-    +     var behave = this;     this.last = init;-    +     //sendEvent to this might impact other nodes that depend on this event     //sendBehaviour defaults to this one     this.underlyingRaw = event;-    +     //unexposed, sendEvent to this will only impact dependents of this behaviour     this.underlying =     createNode(-      [event], -	  (updater ? -	   function (s, p) {behave.last = updater(p.value); p.value = behave.last; s(p);} : +      [event],+	  (updater ?+	   function (s, p) {behave.last = updater(p.value); p.value = behave.last; s(p);} : 	   function (s, p) {behave.last = p.value;  s(p);}));   }; 	Behaviour.prototype = new Object();   fxExport(core,Behaviour,'Behaviour');   fxExport(core,Behaviour,'Behavior');-  +   var receiver_e = function() {     var evt = internal_e();     evt.sendEvent = function(value) {@@ -479,16 +479,16 @@     return evt;   };   fxExport(core,receiver_e,'receiver_e');-  +   //note that this creates a new timestamp and new event queue   var sendEvent = function (node, value) {     if (!(node instanceof EventStream)) { throw 'sendEvent: expected Event as first arg'; } //SAFETY-    +     propagatePulse(new Pulse(nextStamp(), value),node);   };   fxExport(core,sendEvent,'sendEvent');   synonyms['sendEvent'] = true; // Hack: sendEvent simply should not be exported; calling it a synonym deprecates it.-  +   // bind_e :: EventStream a * (a -> EventStream b) -> EventStream b   EventStream.prototype.bind_e = function(k) {     /* m.sendsTo result_e@@ -497,12 +497,12 @@      */     var m = this;     var prev_e = false;-    +     var out_e = createNode([],function(send,pulse) { send(pulse); });     out_e.name = "bind out_e";-    +     var in_e = createNode([m], function (send,pulse) {-      if (prev_e) { +      if (prev_e) {         removeListener(prev_e,out_e);       }       prev_e = k(pulse.value);@@ -514,7 +514,7 @@       }     });     in_e.name = "bind in_e";-    +     return out_e;   }; @@ -526,7 +526,7 @@     if (!(f instanceof Function)) {       throw ('lift_e : expected a function as the first argument; received ' + f);     };-    +     return createNode([this],function(send,pulse) {       pulse.value = f(pulse.value);       send(pulse);@@ -534,18 +534,18 @@   };   fxMethodSynonyms(EventStream,'lift_e',     'transform_e','map_e','apply_e','lift','transform','map','apply');-  +   EventStream.prototype.not_e = function() { return this.lift_e(function(v) { return !v; }); };   fxMethodSynonyms(EventStream,'not_e','not');-  +   var not_e = function(e) { return e.not_e(); };   fxExport(core,not_e,'not_e','not');-  +   EventStream.prototype.filter_e = function(pred) {     if (!(pred instanceof Function)) {       throw ('filter_e : expected predicate; received ' + pred);     };-    +     // Can be a bind_e     return createNode([this],       function(send,pulse) {@@ -553,10 +553,10 @@     });   };   fxMethodSynonyms(EventStream,'filter_e','filter');-  +   var filter_e = function(e,p) { return e.filter_e(p); };   fxExport(core,filter_e,'filter_e');-  +   // Fires just once.   EventStream.prototype.once_e = function() {     var done = false;@@ -565,11 +565,11 @@       if (!done) { done = true; send(pulse); }     });   };-  fxMethodSynonyms(EventStream,'once_e','once')-  +  fxMethodSynonyms(EventStream,'once_e','once');+   var once_e = function(e) { return e.once_e(); };   fxExport(core,once_e,'once_e');-  +   EventStream.prototype.skipFirst_e = function() {     var skipped = false;     return createNode([this],function(send,pulse) {@@ -580,10 +580,10 @@     });   };   fxMethodSynonyms(EventStream,'skipFirst_e','skipFirst');-  +   var skipFirst_e = function(e) { return e.skipFirst_e(); };   fxExport(core,skipFirst_e,'skipFirst_e');-  +   EventStream.prototype.collect_e = function(init,fold) {     var acc = init;     return this.lift_e(@@ -594,31 +594,31 @@       });   };   fxMethodSynonyms(EventStream,'collect_e','collect','transformWithMemory');-  +   var collect_e = function(e,i,f) { return e.collect_e(i,f); };   fxExport(core,collect_e,'collect_e');-  +   // a.k.a. join   EventStream.prototype.switch_e = function() {     return this.bind_e(function(v) { return v; });   };   fxMethodSynonyms(EventStream,'switch_e','forwardLatest');-  +   var switch_e = function(e) { return e.switch_e(); };   fxExport(core,switch_e,'switch_e');-  +   EventStream.prototype.if_e = function(thenE,elseE) {     var testStamp = -1;     var testValue = false;-    +     createNode([this],function(_,pulse) { testStamp = pulse.stamp; testValue = pulse.value; });-    +     return merge_e(       createNode([thenE],function(send,pulse) { if (testValue && (testStamp == pulse.stamp)) { send(pulse); } }),       createNode([elseE],function(send,pulse) { if (!testValue && (testStamp == pulse.stamp)) { send(pulse); } }));   };   fxMethodSynonyms(EventStream,'if_e','choose_e','choose');-  +   var if_e = function(test,thenE,elseE) {     if (test instanceof EventStream)       { return test.if_e(thenE,elseE); }@@ -626,43 +626,43 @@       { return test ? thenE : elseE; }   };   fxExport(core,if_e,'if_e','choose_e');-      +   var cond_e = function (/*. predValArrays */) {     var predValArrays = slice(arguments, 0);     var acc = zero_e();     for (var i = predValArrays.length - 1; i > -1; i--) {       acc = if_e(predValArrays[i][0],predValArrays[i][1], acc);     }-    return acc; +    return acc;   };   fxExport(core,cond_e,'cond_e');-  +   var and_e = function (/* . nodes */) {     var nodes = slice(arguments, 0);-    -    var acc = (nodes.length > 0)? ++    var acc = (nodes.length > 0)?     nodes[nodes.length - 1] : one_e(true);-    +     for (var i = nodes.length - 2; i > -1; i--) {       acc = if_e(-        nodes[i], -        acc, +        nodes[i],+        acc,         nodes[i].constant_e(false));     }     return acc;   };   fxExport(core,and_e,'and_e');-  +   EventStream.prototype.and_e = function( /* others */ ) {     var deps = [this].concat(slice(arguments,0));     return and_e.apply(this,deps);   };   fxMethodSynonyms(EventStream,'and_e','and');-  +   var or_e = function () {     var nodes = slice(arguments, 0);-    var acc = (nodes.length > 2)? -    nodes[nodes.length - 1] : one_e(false); +    var acc = (nodes.length > 2)?+    nodes[nodes.length - 1] : one_e(false);     for (var i = nodes.length - 2; i > -1; i--) {       acc = if_e(         nodes[i],@@ -672,72 +672,72 @@     return acc;   };   fxExport(core,or_e,'or_e');-  +   EventStream.prototype.or_e = function(/*others*/) {     var deps = [this].concat(slice(arguments,0));     return or_e.apply(this,deps);   };   fxMethodSynonyms(EventStream,'or_e','or');-  +   var delayStatic_e = function (event, time) {-    +     var resE = internal_e();-    +     createNode(       [event],-      function (s, p) { -        setTimeout( -          function () { sendEvent(resE, p.value);}, +      function (s, p) {+        setTimeout(+          function () { sendEvent(resE, p.value);},       time ); });-    +     return resE;   };-  +   //delay_e: Event a * [Behaviour] Number ->  Event a   EventStream.prototype.delay_e = function (time) {     var event = this;-    +     if (time instanceof Behaviour) {-      +       var receiverEE = internal_e();-      var link = +      var link =       {-        from: event, +        from: event,         towards: delayStatic_e(event, valueNow(time))       };-      + 			//TODO: Change semantics such that we are always guaranteed to get an event going out?-      var switcherE = +      var switcherE =       createNode(         [changes(time)],         function (s, p) {-          removeListener(link.from, link.towards); +          removeListener(link.from, link.towards);           link =           {-            from: event, +            from: event,             towards: delayStatic_e(event, p.value)           };           sendEvent(receiverEE, link.towards);         });-      +       var resE = receiverEE.switch_e();-      +       sendEvent(switcherE, valueNow(time));       return resE;-      +         } else { return delayStatic_e(event, time); }   };   fxMethodSynonyms(EventStream,'delay_e','delay');-  +   var delay_e = function(sourceE,interval) {     return sourceE.delay_e(interval);   };   fxExport(core,delay_e,'delay_e');-  +   //lift_e: ([Event] (. Array a -> b)) . Array [Event] a -> [Event] b   var lift_e = function (fn /*, [node0 | val0], ...*/) {     //      if (!(fn instanceof Function)) { throw 'lift_e: expected fn as second arg'; } //SAFETY-    +     var valsOrNodes = slice(arguments, 0);     //selectors[i]() returns either the node or real val, optimize real vals     var selectors = [];@@ -746,26 +746,26 @@     for (var i = 0; i < valsOrNodes.length; i++) {       if (valsOrNodes[i] instanceof EventStream) {         nodes.push(valsOrNodes[i]);-        selectors.push( +        selectors.push(           (function(ii) {-              return function(realArgs) { +              return function(realArgs) {                 return realArgs[ii];               };           })(selectI));         selectI++;       } else {-        selectors.push( -          (function(aa) { +        selectors.push(+          (function(aa) {               return function () {                 return aa;-              }; +              };           })(valsOrNodes[i]));-      } +      }     }-    +     var context = this; 		var nofnodes = slice(selectors,1);-    +     if (nodes.length === 0) {       return one_e(fn.apply(context, valsOrNodes));     } else if ((nodes.length === 1) && (fn instanceof Function)) {@@ -773,7 +773,7 @@         function () {           var args = arguments;           return fn.apply(-            context, +            context,             map(function (s) {return s(args);}, nofnodes));         });     } else if (nodes.length === 1) {@@ -781,9 +781,9 @@         function (v) {           var args = arguments;           return v.apply(-            context, +            context,             map(function (s) {return s(args);}, nofnodes));-        });                +        });     } else if (fn instanceof Function) {       return createTimeSyncNode(nodes).lift_e(         function (arr) {@@ -795,13 +795,13 @@       return createTimeSyncNode(nodes).lift_e(         function (arr) {           return arr[0].apply(-            this, +            this,             map(function (s) {return s(arr); }, nofnodes));         });         } else {throw 'unknown lift_e case';}   };   fxExport(core,lift_e,'lift_e','transform_e','map_e','apply_e');-  +   EventStream.prototype.snapshot_e = function (valueB) {     return createNode(       [this],@@ -809,7 +809,7 @@         p.value = valueNow(valueB);         s(p);       }-      ); +      );   };   fxMethodSynonyms(EventStream,'snapshot_e','snapshot','takeSnapshot'); @@ -821,7 +821,7 @@   EventStream.prototype.filterRepeats_e = function(optStart) {     var hadFirst = optStart === undefined ? false : true;     var prev = optStart;-  +     return this.filter_e(function (v) {       if (!hadFirst || !(isEqual(prev,v))) {         hadFirst = true;@@ -854,7 +854,7 @@       }()); 		return out;   };-  +   //calm_e: Event a * [Behaviour] Number -> Event a   EventStream.prototype.calm_e = function(time) {     if (time instanceof Behaviour) {@@ -865,26 +865,26 @@           var towards = null;           return function (s, p) {             if (towards !== null) { clearTimeout(towards); }-            towards = setTimeout( function () { towards = null; sendEvent(out,p.value) }, valueNow(time));+             towards = setTimeout( function () { towards = null; sendEvent(out,p.value);}, valueNow(time));           };         }()); 			return out;     } else {-      return calmStatic_e(this,time);       +      return calmStatic_e(this,time);     }   };   fxMethodSynonyms(EventStream,'calm_e','calm');-  +   var calm_e = function(sourceE,interval) {     return sourceE.calm_e(interval);   };   fxExport(core,calm_e,'calm_e');-  +   EventStream.prototype.blind_e = function (time) {     return createNode(       [this],       function () {-        var intervalFn = +        var intervalFn =         time instanceof Behaviour?         function () { return valueNow(time); }         : function () { return time; };@@ -899,12 +899,12 @@       }());   };   fxMethodSynonyms(EventStream,'blind_e','blind');-  +   var blind_e = function(sourceE,interval) {     return sourceE.blind_e(interval);   };   fxExport(core,blind_e,'blind_e');- +   EventStream.prototype.hold = function(init) {     return new Behaviour(this,init);   };@@ -914,10 +914,10 @@     if (!(e instanceof EventStream)) {       throw 'hold: expected EventStream; received ' + e;     }-    return e.hold(init); +    return e.hold(init);   };   fxExport(core,hold,'hold');-  +   Behaviour.prototype.valueNow = function() {     return this.last;   };@@ -928,20 +928,20 @@     return this.underlying;   };   fxMethodSynonyms(Behaviour,'changes','toEvent');-  -  var changes = function (behave) { return behave.changes(); }++   var changes = function (behave) { return behave.changes(); };   fxExport(core,changes,'changes');-  +   Behaviour.prototype.switch_b = function() {     var behaviourCreatorsB = this;     var init = valueNow(behaviourCreatorsB);-    +     var prevSourceE = null;-    +     var receiverE = new internal_e();-    + 		//XXX could result in out-of-order propagation! Fix!-    var makerE = +    var makerE =     createNode(       [changes(behaviourCreatorsB)],       function (_, p) {@@ -949,67 +949,67 @@         if (prevSourceE != null) {           removeListener(prevSourceE, receiverE);         }-        +         prevSourceE = changes(p.value);         attachListener(prevSourceE, receiverE);-        +         sendEvent(receiverE, valueNow(p.value));       });-    +     if (init instanceof Behaviour) {       sendEvent(makerE, init);     }-    +     return hold(       receiverE,       init instanceof Behaviour? valueNow(init) : init);   };   fxMethodSynonyms(Behaviour,'switch_b','forwardLatest');-  +   var switch_b = function (b) { return b.switch_b(); };   fxExport(core,switch_b,'switch_b');-  +   //TODO test, signature   var timer_b = function(interval) {     return hold(timer_e(interval), (new Date()).getTime());   };   fxExport(dom,timer_b,'timer_b','asTimer_b');-  +   //TODO test, signature   var delayStatic_b = function (triggerB, time, init) {     return hold(delayStatic_e(changes(triggerB), time), init);   };-  +   //TODO test, signature   Behaviour.prototype.delay_b = function (time, init) {     var triggerB = this;     if (time instanceof Behaviour) {       return hold(         delay_e(-          changes(triggerB), +          changes(triggerB),           time),         arguments.length > 3 ? init : valueNow(triggerB));     } else {       return delayStatic_b(-        triggerB, +        triggerB,         time,         arguments.length > 3 ? init : valueNow(triggerB));     }   };   fxMethodSynonyms(Behaviour,'delay_b','delay');-  -  var delay_b = function(srcB, timeB, init) { -    return srcB.delay_b(timeB,init); ++  var delay_b = function(srcB, timeB, init) {+    return srcB.delay_b(timeB,init);   };   fxExport(core,delay_b,'delay_b');-  +   //artificially send a pulse to underlying event node of a behaviour   //note: in use, might want to use a receiver node as a proxy or an identity map   Behaviour.prototype.sendBehaviour = function(val) {     sendEvent(this.underlyingRaw,val);   };   Behaviour.prototype.sendBehavior = Behaviour.prototype.sendBehaviour;-  +   var sendBehaviour = function (b,v) { b.sendBehaviour(v); };   fxExport(core,sendBehaviour,'sendBehaviour');   fxExport(core,sendBehaviour,'sendBehavior');@@ -1022,15 +1022,15 @@     return lift_b(function(te,t,f) { return te ? t : f; },testB,trueB,falseB);   };   fxMethodSynonyms(Behaviour,'if_b','choose_b','choose');-  +   var if_b = function(test,cons,altr) {     if (!(test instanceof Behaviour)) { test = constant_b(test); };-    +     return test.if_b(cons,altr);   };   fxExport(core,if_b,'if_b','choose_b');-   +   //cond_b: . [Behaviour boolean, Behaviour a] -> Behaviour a   var cond_b = function (/* . pairs */ ) {     var pairs = slice(arguments, 0);@@ -1042,14 +1042,14 @@ 		}].concat(map(function(pair) {return pair[0];},pairs).concat(map(function(pair) {return pair[1];},pairs))));   };   fxExport(core,cond_b,'cond_b');-  +   //TODO optionally append to objects   //createConstantB: a -> Behaviour a   var constant_b = function (val) {     return new Behaviour(internal_e(), val);   };   fxExport(core,constant_b,'constant_b','receiver_b');-  + 	var lift_b = function (fn /* . behaves */) {     var args = slice(arguments, 1); @@ -1058,21 +1058,21 @@       map(changes,       filter(function (v) { return v instanceof Behaviour; },         arguments));-    +     //calculate new vals     var getCur = function (v) {       return v instanceof Behaviour ? v.last : v;     };-    +     var ctx = this;     var getRes = function () {       return getCur(fn).apply(ctx, map(getCur, args));     };-	+     if(constituentsE.length == 1) {       return new Behaviour(constituentsE[0],getRes(),getRes);     }-      +     //gen/send vals @ appropriate time     var prevStamp = -1;     var mid = createNode(constituentsE, function (s, p) {@@ -1083,14 +1083,14 @@     return new Behaviour(mid,getRes(),getRes);   };   fxExport(core,lift_b,'lift_b','transform_b','apply_b');-  +   Behaviour.prototype.lift_b = function(/* args */) {     var args= slice(arguments,0).concat([this]);     return lift_b.apply(this,args);   };   fxMethodSynonyms(Behaviour,'lift_b','transform_b','apply_b','transform',     'lift');-  +   var and_b = function (/* . behaves */) { 	return lift_b.apply({},[function() { 			for(var i=0; i<arguments.length; i++) {if(!arguments[i]) return false;}@@ -1098,12 +1098,12 @@ 	}].concat(slice(arguments,0)));   };   fxExport(core, and_b, 'and_b');-  +   Behaviour.prototype.and_b = function() {     return and_b([this].concat(arguments));   };   fxMethodSynonyms(Behaviour,'and_b','and');-  +   var or_b = function (/* . behaves */ ) { 	return lift_b.apply({},[function() { 			for(var i=0; i<arguments.length; i++) {if(arguments[i]) return true;}@@ -1111,64 +1111,64 @@ 	}].concat(slice(arguments,0)));   };   fxExport(core,or_b,'or_b');-  +   Behaviour.prototype.or_b = function () {     return or_b([this].concat(arguments));   };   fxMethodSynonyms(Behaviour, 'or_b', 'or');-  +   Behaviour.prototype.not_b = function() {     return this.lift_b(function(v) { return !v; });   };   fxMethodSynonyms(Behaviour,'not_b','not');-  +   var not_b = function(b) { return b.not_b(); };   fxExport(core,not_b,'not_b');-  +   Behaviour.prototype.blind_b = function (intervalB) {     return changes(this).blind_e(intervalB).hold(this.valueNow());   };   fxMethodSynonyms(Behaviour,'blind_b','blind');-  +   var blind_b = function(srcB,intervalB) {     return srcB.blind_b(intervalB);   };   fxExport(core,blind_b,'blind_b');-  +   Behaviour.prototype.calm_b = function (intervalB) {     return this.changes().calm_e(intervalB).hold(this.valueNow());   };   fxMethodSynonyms(Behaviour,'calm_b','calm');-  -  var calm_b = function (srcB,intervalB) { ++  var calm_b = function (srcB,intervalB) {     return srcB.calm_b(intervalB);   };   fxExport(core,calm_b,'calm_b');-    +   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////   // DOM Utilities-  + 	//credit Scott Andrew 	//usage: addEvent(myDomObj, "mouseover", event->void ) 	//warning: do not use 'this' as meaning depends on browser (myDomObj vs window) 	//addEvent: Dom * String DomEventEnum * (DomEvent -> a) -> Void 	var addEvent = function (obj, evType, fn) { 		//TODO encode mouseleave evt, formalize new evt interface-    + 		if (obj.addEventListener) {       obj.addEventListener(evType, fn, false); //TODO true fails on Opera       return true; 		} else if (obj.attachEvent) {       //some reason original had code bloat here-      return obj.attachEvent("on"+evType, fn); +      return obj.attachEvent("on"+evType, fn); 		} else {-      return false; +      return false; 		} 	};   fxExport(domMisc,addEvent,'addEvent'); -  // The Flapjax library does not use this function  -	//credit Dustin Diaz +  // The Flapjax library does not use this function+	//credit Dustin Diaz 	//note: node/tag optional 	//getElementsByClass: Regexp CSSSelector * Dom * String DomNodeEnum -> Array Dom 	var getElementsByClass = function (searchClass, node, tag) {@@ -1186,22 +1186,22 @@ 		return classElements; 	};   fxExport(domMisc,getElementsByClass,'getElementsByClass','$$');-  + 	//assumes IDs already preserved 	//swapDom: (Dom a U String) [* (Dom b U String)] -> Dom a 	var swapDom = function(replaceMe, withMe) { 		if ((replaceMe === null) || (replaceMe === undefined)) { throw ('swapDom: expected dom node or id, received: ' + replaceMe); } //SAFETY-    + 		var replaceMeD = getObj(replaceMe); 		if (!(replaceMeD.nodeType > 0)) { throw ('swapDom expected a Dom node as first arg, received ' + replaceMeD); } //SAFETY-    + 		if (withMe) {       var withMeD = getObj(withMe);       if (!(withMeD.nodeType > 0)) { throw 'swapDom: can only swap with a DOM object'; } //SAFETY       try {         if(withMeD != replaceMeD) replaceMeD.parentNode.replaceChild(withMeD, replaceMeD);       } catch (e) {-        throw('swapDom error in replace call: withMeD: ' + withMeD + ', replaceMe Parent: ' + replaceMeD + ', ' + e + ', parent: ' + replaceMeD.parentNode);                    +        throw('swapDom error in replace call: withMeD: ' + withMeD + ', replaceMe Parent: ' + replaceMeD + ', ' + e + ', parent: ' + replaceMeD.parentNode);       } 		} else {       replaceMeD.parentNode.removeChild(replaceMeD); //TODO isolate child and set innerHTML to "" to avoid psuedo-leaks?@@ -1209,9 +1209,9 @@ 		return replaceMeD; 	};   fxExport(domMisc,swapDom,'swapDom');-  + 	//getObj: String U Dom -> Dom-	//throws +	//throws 	//  'getObj: expects a Dom obj or Dom id as first arg' 	//  'getObj: flapjax: cannot access object' 	//  'getObj: no obj to get@@ -1222,21 +1222,21 @@ 		else if ((typeof(name) == 'null') || (typeof(name) == 'undefined')) {       throw 'getObj: expects a Dom obj or Dom id as first arg'; 		} else {-      -      var res = ++      var res = 			document.getElementById ? document.getElementById(name) : 			document.all ? document.all[name] : 			document.layers ? document.layers[name] : 			(function(){ throw 'getObj: flapjax: cannot access object';})();-      if ((res === null) || (res === undefined)) { -        throw ('getObj: no obj to get: ' + name); +      if ((res === null) || (res === undefined)) {+        throw ('getObj: no obj to get: ' + name);       }       return res; 		} 	};   fxExport(domMisc,getObj,'getObj');   fxExport(domMisc,getObj,'$');-  +   //helper to reduce obj look ups   //getDynObj: domNode . Array (id) -> domObj   //obj * [] ->  obj@@ -1251,9 +1251,9 @@         acc = acc[indices[i]];       }       return acc;-    }       +    }   };-  +   var getDomVal = function (domObj, indices) {     var val = getMostDom(domObj, indices);     if (indices && indices.length > 0) {@@ -1261,24 +1261,24 @@     }     return val;   };-  +   //TODO: manual timer management stinks.   // TODO: Name turn off or somethin   var ___timerID = 0;-  var __getTimerId = function () { return ++___timerID; };    +  var __getTimerId = function () { return ++___timerID; };   var timerDisablers = [];-  +   var disableTimerNode = function (node) { timerDisablers[node.__timerId](); };-  +   var disableTimer = function (v) {-    if (v instanceof Behaviour) { -      disableTimerNode(v.underlyingRaw); +    if (v instanceof Behaviour) {+      disableTimerNode(v.underlyingRaw);     } else if (v instanceof EventStream) {       disableTimerNode(v);     }   };   fxExport(dom,disableTimer,'disableTimer');-  +   var createTimerNodeStatic = function (interval) {     var node = internal_e();     node.__timerId = __getTimerId();@@ -1287,35 +1287,35 @@     timerDisablers[node.__timerId] = function () {clearInterval(timer); };     return node;   };-  +   var timer_e = function (interval) {     if (interval instanceof Behaviour) {       var receiverE = internal_e();-      +       //the return       var res = receiverE.switch_e();-      +       //keep track of previous timer to disable it       var prevE = createTimerNodeStatic(valueNow(interval));-      +       //init       sendEvent(receiverE, prevE);-      +       //interval changes: collect old timer       createNode(         [changes(interval)],         function (_, p) {-          disableTimerNode(prevE); +          disableTimerNode(prevE);           prevE = createTimerNodeStatic(p.value);           sendEvent(receiverE, prevE);         });-      +       res.__timerId = __getTimerId();       timerDisablers[res.__timerId] = function () {         disableTimerNode[prevE]();         return;       };-      +       return res;     } else {       return createTimerNodeStatic(interval);@@ -1348,18 +1348,18 @@     // Array [[Behaviour] Object *] [[Behaviour] Array] [Behaviour] Dom U String U undefined     //   --> {attribs: Array [Behaviour] Object, arrs: Array [Behaviour] Array [Behaviour] Dom }     // split an arguments array into:-    //   1. arrs: (coalesced, and possibly time varying) arrays of dom objects +    //   1. arrs: (coalesced, and possibly time varying) arrays of dom objects     //   2. attribs: attribute objects 		extractParameters: function(args) { 			this.arrs = []; 			var attribs = [];-      + 			var curarr = []; 			this.arrs.push(curarr); 			for (var i = 0; i < args.length; i++) { 				if (args[i] instanceof Behaviour) { 					var vn = valueNow(args[i]);-					if (vn instanceof Array) {	        +					if (vn instanceof Array) { 						this.arrs.push(args[i]); 						curarr = []; 						this.arrs.push(curarr);@@ -1392,26 +1392,26 @@ 		}, 		insertChildrenNodes: function() { 			var ctx = this;-      -			function quickNode(e) { ++			function quickNode(e) {         if ((typeof(e) == 'object') && (e.nodeType))-					return e; +					return e;         else if ( e == undefined )-					return document.createTextNode(''); -        else -          return document.createTextNode(e); +					return document.createTextNode('');+        else+          return document.createTextNode(e);       }-      + 			function unBehaviourize(arr) { 				return map(function(n) {return (n instanceof Behaviour) ? valueNow(n) : n;},arr) 			}-      + 			var lnodes = map(function() {return [];},this.arrs); 			var arrLastVals = map(unBehaviourize,unBehaviourize(this.arrs));-      + 			var arrChangesE = internal_e(); 			var nodeChangesE = internal_e();-			+ 			function attachNodes(i,arr) { 				for(var j=0;j<arr.length;j++) { 					var cnode = arr[j];@@ -1425,7 +1425,7 @@ 					} 				} 			}-      + 			var childChangesE = merge_e( 				// Behaviour arrays change 				arrChangesE.lift_e(function(ai) {@@ -1461,7 +1461,7 @@             return ctx.currentTag; 				})); 			childChangesE.lift_e(function(cc) {sendEvent(ctx.resE,cc);});-      + 			for(var i=0; i<this.arrs.length;i++) { 				for(var j=0; j<arrLastVals[i].length; j++) { 					arrLastVals[i][j] = quickNode(arrLastVals[i][j]);@@ -1491,7 +1491,7 @@ 						this.enstyleProperty(obj,valsV, i); 					} 				}-			} +			} 			else { throw 'enstyle: expected object literals'; } //SAFETY 		},     enstyleProperty: function (obj, vals, i) {@@ -1513,11 +1513,11 @@       }     } 	};-  + 	d.createParameterizedTagB = function(tagName) { 		return new d.TagB(tagName,slice(arguments,1)).resB;-	}-  +	};+   d.enstyleStaticProperty = function (obj, props, index) {     if (typeof(props[index]) == 'object') {       for (var i in props[index]) {@@ -1531,16 +1531,16 @@ 			if (index == 'selected') obj['defaultSelected'] = props[index]; /* TODO: this should maybe be elsewhere? */     }   };-  +   d.staticTagMaker = function (tagName) {-    +     return function () {-      +       var tagD = document.createElement(tagName);       if (!(tagD.nodeType > 0)) { throw (tagName + ': invalid tag name'); } //SAFETY-      +       //partition input-      +       //          if (arguments[1] === null || arguments[1] === undefined) { arguments[1] = {}; }       var attribs = [];       for (var i = 0; i < arguments.length; i++) {@@ -1556,91 +1556,91 @@           }         } else if (!arguments[i]) {           //ignore-        } else if ((typeof(arguments[i]) == 'object') && +        } else if ((typeof(arguments[i]) == 'object') &&           (arguments[i].nodeType > 0)) {         tagD.appendChild(arguments[i]);           } else if (typeof(arguments[i]) == 'object') {             attribs.push(arguments[i]);           } else {-            tagD.appendChild(document.createTextNode(arguments[i]));                    +            tagD.appendChild(document.createTextNode(arguments[i]));           }       }-      -      if (attribs.length == 1) { ++      if (attribs.length == 1) {         for (var k in attribs[0]) {           if (!(Object.prototype) || !(Object.prototype[k])) {-            d.enstyleStaticProperty(tagD, attribs[0], k);   +            d.enstyleStaticProperty(tagD, attribs[0], k);           }         }-      } else if (attribs.length >  0) { +      } else if (attribs.length >  0) {         throw 'static enstyle: expected object literals'; //SAFETY       } /* else {       alert('no attribs on: ' + tagName);       } */-      -      ++       return tagD;     };   };-  -  -  -  var generatedTags = -  [ "a", "b", "blockquote", "br", "button", "canvas", "div", "fieldset", -  "form", "font", "h1", "h2", "h3", "h4", "hr", "img", "iframe", "input", -  "label", "legend", "li", "ol", "optgroup", "option", -  "p", "pre", "select", "span", "strong", "table", "tbody", ++++  var generatedTags =+  [ "a", "b", "blockquote", "br", "button", "canvas", "div", "fieldset",+  "form", "font", "h1", "h2", "h3", "h4", "hr", "img", "iframe", "input",+  "label", "legend", "li", "ol", "optgroup", "option",+  "p", "pre", "select", "span", "strong", "table", "tbody",   "td", "textarea", "tfoot", "th", "thead", "tr", "tt", "ul" ];-  +   map(-    function (tagName) { -      +    function (tagName) {+       var upper = tagName.toUpperCase();-      +       //d.<TAG>B-      d[upper + 'B'] = function () { +      d[upper + 'B'] = function () {         return d.createParameterizedTagB.apply(this, [tagName].concat(slice(arguments,0)));-      };          +      }; 			annotate(d[upper+'B'],[upper+'B']);-      +       //d.<TAG>       d[upper] = d.staticTagMaker(tagName);  //faster, simple       /*              function () {       // 8/16/06 - leo - arguments bug       // more forgiving: allows reactive children (just doesn't propagate them)-      var args = [b.maybeEmpty].concat(slice(arguments, 0)); +      var args = [b.maybeEmpty].concat(slice(arguments, 0));       return valueNow(d[upper + 'B'].apply(this, args));       }; */ 			annotate(d[upper],[upper]);     },     generatedTags);-  -  //TEXTB: Behaviour a -> Behaviour Dom TextNode    ++  //TEXTB: Behaviour a -> Behaviour Dom TextNode   d.TEXTB = function (strB) {     //      if (!(strB instanceof Behaviour || typeof(strB) == 'string')) { throw 'TEXTB: expected Behaviour as second arg'; } //SAFETY     if (!(strB instanceof Behaviour)) { strB = constant_b(strB); }-    +     return hold(       changes(strB).lift_e(         function (txt) { return document.createTextNode(txt); }),       document.createTextNode(valueNow(strB)));   }; 	annotate(d.TEXTB,['TEXTB']);-  +   var TEXT = function (str) {     return document.createTextNode(str);   };   fxExport(dom,TEXT,'TEXT');-  +   //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////   // Reactive DOM-  -  //tagRec: Array (EventName a) * ++  //tagRec: Array (EventName a) *   //      ( .Array (Event a) * Array (Event a) -> Behaviour Dom) -> Behaviour Dom   var tagRec = function (eventNames, maker) {     if (!(eventNames instanceof Array)) { throw 'tagRec: expected array of event names as first arg'; } //SAFETY     if (!(maker instanceof Function)) { throw 'tagRec: expected function as second arg'; } //SAFETY-    +     var numEvents = eventNames.length;     var internals = [ ];     var switches = [ ];@@ -1648,33 +1648,33 @@       internals[i] = internal_e();       switches[i] = internals[i].switch_e();     };-    +     var domB = maker.apply(this,switches);-    +     var prevValue;-    +     var interceptE = createNode([domB.changes()],function (_,p) {       if (isEqual(p.value,prevValue)) { return; }-      +       prevValue = p.value;       for (var i = 0; i < numEvents; i++) {         sendEvent(internals[i],extractEvent_e(prevValue,eventNames[i]));       };     });-    +     sendEvent(interceptE,domB.valueNow());-    +     return domB;   };   fxExport(dom,tagRec,'tagRec','nodeWithOwnEvents');-  +   //extractEventStatic_e: Dom * String -> Event   var extractEventStatic_e = function (domObj, eventName) {     if (!eventName) { throw 'extractEvent_e : no event name specified'; }     if (!domObj) { throw 'extractEvent_e : no DOM element specified'; }-    +     domObj = getObj(domObj);-    +     var primEventE = internal_e();     addEvent(domObj,eventName,function(evt) {        sendEvent(primEventE, evt || window.event);@@ -1682,7 +1682,7 @@        // checking.        return true;     });-    +     return primEventE;   }; @@ -1693,47 +1693,47 @@     }     else {       var domE = domB.changes();-      +       var eventEE = domE.lift_e(function(dom) {         return extractEventStatic_e(dom,eventName);       });-      +       var resultE = eventEE.switch_e();-      +       sendEvent(domE,domB.valueNow());-      +       return resultE;     };   };   fxExport(dom,extractEvent_e,'extractEvent_e','$EVT');-  -  //extractEvents_e: -  //      [Behaviour] Dom  ++  //extractEvents_e:+  //      [Behaviour] Dom   //      . Array String   //      -> Event   // ex: extractEvents_e(m, 'body', 'mouseover', 'mouseout')   d.extractEvents_e = function (domObj /* . eventNames */) {     var eventNames = slice(arguments, 1);-    +     var events = map(       function (eventName) {-        return extractEvent_e(domObj, eventName); +        return extractEvent_e(domObj, eventName);       },       eventNames.length === 0 ? [] : eventNames);-    +     return merge_e.apply(this, events);   };   annotate(d.extractEvents_e,['extractEvents_e'],0,[Behaviour.prototype],['extractEvents_e']);-  +   //value of dom form object during trigger   d.extractValueOnEvent_e = function (triggerE, domObj) {     if (!(triggerE instanceof EventStream)) { throw 'extractValueOnEvent_e: expected Event as first arg'; } //SAFETY-    +     return changes(d.extractValueOnEvent_b.apply(this, arguments));-    +   };   annotate(d.extractValueOnEvent_e,['extractValueOnEvent_e']);-  +   //extractDomFieldOnEvent_e: Event * Dom U String . Array String -> Event a   d.extractDomFieldOnEvent_e = function (triggerE, domObj /* . indices */) {     if (!(triggerE instanceof EventStream)) { throw 'extractDomFieldOnEvent_e: expected Event as first arg'; } //SAFETY@@ -1743,23 +1743,23 @@       function () { return getDomVal(domObj, indices); });     return res;   };-  +   d.extractValue_e = function (domObj) {     return changes(d.extractValue_b.apply(this, arguments));   };   annotate(d.extractValue_e,['extractValue_e','$E']);-  +   //extractValueOnEvent_b: Event * DOM -> Behaviour   // value of a dom form object, polled during trigger   d.extractValueOnEvent_b = function (triggerE, domObj) {     return d.extractValueStatic_b(domObj, triggerE);   };   annotate(d.extractValueOnEvent_b,['extractValueOnEvent_b']);-  +   //extractValueStatic_b: DOM [ * Event ] -> Behaviour a   //If no trigger for extraction is specified, guess one   d.extractValueStatic_b = function (domObj, triggerE) {-    +     var objD;     try {       objD = getObj(domObj);@@ -1770,36 +1770,36 @@     } catch (e) {       objD = {type: 'radio-group', name: domObj};     }-    +     var getter; // get value at any current point in time-    -    ++     switch (objD.type)  {-      +       //TODO: checkbox.value instead of status?-    case 'checkbox': -      +    case 'checkbox':+       return hold(         filterRepeats_e(           d.extractDomFieldOnEvent_e(-            triggerE ? triggerE : +            triggerE ? triggerE :             d.extractEvents_e(-              objD, +              objD,               'click', 'keyup', 'change'),             objD,             'checked'),objD.checked),         objD.checked);-      +       case 'select-one':-        -        getter = function (_) {                         -          return objD.selectedIndex > -1 ? ++        getter = function (_) {+          return objD.selectedIndex > -1 ?           (objD.options[objD.selectedIndex].value ?             objD.options[objD.selectedIndex].value :             objD.options[objD.selectedIndex].innerText) 			    : undefined;         };-        +         return hold(           filterRepeats_e(               (triggerE ? triggerE :@@ -1807,10 +1807,10 @@                 objD,                 'click', 'keyup', 'change')).lift_e(getter)),getter(),           getter());-        +         case 'select-multiple':           //TODO ryan's cfilter adapted for equality check-          +           getter = function (_) {             var res = [];             for (var i = 0; i < objD.options.length; i++) {@@ -1820,95 +1820,95 @@             }             return res;           };-          -          ++           return hold(-              (triggerE ? triggerE : +              (triggerE ? triggerE :               d.extractEvents_e(                 objD,                 'click', 'keyup', 'change')).lift_e(getter),             getter());-          +           case 'text':           case 'textarea':           case 'hidden':           case 'password':-            +             return hold(               filterRepeats_e(                 d.extractDomFieldOnEvent_e(                   triggerE ? triggerE :                   d.extractEvents_e(-                    objD, +                    objD,                     'click', 'keyup', 'change'),                   objD,                   'value'),objD.value),               objD.value);-            +             case 'button': //same as above, but don't filter repeats-              +               return hold(                 d.extractDomFieldOnEvent_e(                   triggerE ? triggerE :                   d.extractEvents_e(-                    objD, +                    objD,                     'click', 'keyup', 'change'),                   objD,                   'value'),                 objD.value);-              -              -              case 'radio': +++              case 'radio':               case 'radio-group':-                +                 //TODO returns value of selected button, but if none specified,                 //      returns 'on', which is ambiguous. could return index,                 //      but that is probably more annoying-                +                 var radiosAD = filter(-                  function (elt) { +                  function (elt) {                     return (elt.type == 'radio') &&-                    (elt.getAttribute('name') == objD.name); +                    (elt.getAttribute('name') == objD.name);                   },                   document.getElementsByTagName('input'));-                -                getter = ++                getter =                 objD.type == 'radio' ?-                +                 function (_) {                   return objD.checked;                 } :-                +                 function (_) {                   for (var i = 0; i < radiosAD.length; i++) {                     if (radiosAD[i].checked) {-                      return radiosAD[i].value; +                      return radiosAD[i].value;                     }                   }-                  return undefined; //TODO throw exn? +                  return undefined; //TODO throw exn?                 };-                +                 var actualTriggerE = triggerE ? triggerE :                 merge_e.apply(                   this,                   map(-                    function (radio) { +                    function (radio) {                       return d.extractEvents_e(-                        radio, +                        radio,                     'click', 'keyup', 'change'); },                       radiosAD));-                +                 return hold(                   filterRepeats_e(                       actualTriggerE.lift_e(getter),getter()),                   getter());-                +                 default:-                  +                   throw ('extractValueStatic_b: unknown value type "' + objD.type + '"');     }   };-  +   d.extractValue_b = function (domObj) {     if (domObj instanceof Behaviour) {       return lift_b(function (dom) { return d.extractValueStatic_b(dom); },@@ -1919,7 +1919,7 @@     }   }; 	annotate(d.extractValue_b,['extractValue_b','$B'],0,[Behaviour.prototype],['extractValue_b','$B']);-  +   //into[index] = deepValueNow(from) via descending from object and mutating each field   d.deepStaticUpdate = function (into, from, index) {     var fV = (from instanceof Behaviour)? valueNow(from) : from;@@ -1934,7 +1934,7 @@       into[index] = fV;     }   };-  +   //note: no object may be time varying, just the fields   //into[index] = from   //only updates on changes@@ -1954,7 +1954,7 @@         createNode(           [changes(from)],           function (s, p) {-            if (index) { +            if (index) {               var old = into[index];               into[index] = p.value;             }@@ -1963,70 +1963,70 @@       }     }   };-  -	++   d.insertValue = function (val, domObj /* . indices */) {     var indices = slice(arguments, 2);     var parent = getMostDom(domObj, indices);-    d.deepStaticUpdate(parent, val, indices ? indices[indices.length - 1] : undefined);    	+    d.deepStaticUpdate(parent, val, indices ? indices[indices.length - 1] : undefined);   };   annotate(d.insertValue,['insertValue']);-  -  //TODO convenience method (default to firstChild nodeValue) ++  //TODO convenience method (default to firstChild nodeValue)   d.insertValueE = function (triggerE, domObj /* . indices */) {     if (!(triggerE instanceof EventStream)) { throw 'insertValueE: expected Event as first arg'; } //SAFETY-    +     var indices = slice(arguments, 2);     var parent = getMostDom(domObj, indices);-    +       triggerE.lift_e(function (v) {         d.deepStaticUpdate(parent, v, indices? indices[indices.length - 1] : undefined);       });   };   annotate(d.insertValueE,['insertValueE'],0,[EventStream.prototype],['insertValueE']);-  +   //insertValueB: Behaviour * domeNode . Array (id) -> void   //TODO notify adapter of initial state change?-  d.insertValueB = function (triggerB, domObj /* . indices */) { -    +  d.insertValueB = function (triggerB, domObj /* . indices */) {+     var indices = slice(arguments, 2);     var parent = getMostDom(domObj, indices);-    -    ++     //NOW     d.deepStaticUpdate(parent, triggerB, indices ? indices[indices.length - 1] : undefined);-    +     //LATER     d.deepDynamicUpdate(parent, triggerB, indices? indices[indices.length -1] : undefined);-    +   };   annotate(d.insertValueB,['insertValueB'],0,[Behaviour.prototype],['insertValueB']);-  +   //TODO copy dom event call backs of original to new? i don't thinks so   //  complication though: registration of call backs should be scoped   d.insertDomE = function (triggerE, domObj) {-    +     if (!(triggerE instanceof EventStream)) { throw 'insertDomE: expected Event as first arg'; } //SAFETY-    +     var objD = getObj(domObj);-    +     var res = triggerE.lift_e(       function (newObj) {         //TODO safer check-        if (!((typeof(newObj) == 'object') && (newObj.nodeType == 1))) { +        if (!((typeof(newObj) == 'object') && (newObj.nodeType == 1))) {           newObj = d.SPAN({}, newObj);         }         swapDom(objD, newObj);         objD = newObj;         return newObj; // newObj;       });-    +     return res;   };   annotate(d.insertDomE,['insertDomE'],0,[EventStream.prototype],['insertDomE']);-  -  //insertDom: dom -  //          * dom ++  //insertDom: dom+  //          * dom   //          [* (null | undefined | 'over' | 'before' | 'after' | 'leftMost' | 'rightMost' | 'beginning' | 'end']   //          -> void   // TODO: for consistency, switch replaceWithD, hookD argument order@@ -2038,7 +2038,7 @@     case 'over':       swapDom(hookD,replaceWithD);       break;-    case 'before':  +    case 'before':       hookD.parentNode.insertBefore(replaceWithD, hookD);       break;     case 'after':@@ -2049,9 +2049,9 @@       }       break;     case 'leftMost':-      if (hookD.parentNode.firstChild) { +      if (hookD.parentNode.firstChild) {         hookD.parentNode.insertBefore(-          replaceWithD, +          replaceWithD,           hookD.parentNode.firstChild);                 } else { hookD.parentNode.appendChild(replaceWithD); }                 break;@@ -2059,9 +2059,9 @@                 hookD.parentNode.appendChild(replaceWithD);                 break;               case 'beginning':-                if (hookD.firstChild) { +                if (hookD.firstChild) {                   hookD.insertBefore(-                    replaceWithD, +                    replaceWithD,                     hookD.firstChild);                 } else { hookD.appendChild(replaceWithD); }                 break;@@ -2072,39 +2072,39 @@                 throw ('domInsert: unknown position: ' + optPosition);     }   };-  -  //insertDom: dom -  //          * dom U String domID ++  //insertDom: dom+  //          * dom U String domID   //          [* (null | undefined | 'over' | 'before' | 'after' | 'leftMost' | 'rightMost' | 'beginning' | 'end']   //          -> void   d.insertDomClean = function (replaceWithD, hook, optPosition) {     //TODO span of textnode instead of textnode?     d.insertDom(-	    getObj(hook), +	    getObj(hook), 	    ((typeof(replaceWithD) == 'object') && (replaceWithD.nodeType > 0)) ? replaceWithD :-      document.createTextNode(replaceWithD),	    -	    optPosition);     	    +      document.createTextNode(replaceWithD),+	    optPosition);   };   annotate(d.insertDomClean,['insertDom']);-  +   //TODO test-  //insertDomB: -  //      [Behaviour] String U Dom -  //      [* ( id U null U undefined ) +  //insertDomB:+  //      [Behaviour] String U Dom+  //      [* ( id U null U undefined )   //          [* ('before' U 'after' U 'leftMost' U 'rightMost' U 'over' U 'beginning' U 'end')]]   //      -> Behaviour a   //if optID not specified, id must be set in init val of trigger   //if position is not specified, default to 'over'-  //performs initial swap onload    +  //performs initial swap onload   d.insertDomB = function (initTriggerB, optID, optPosition) {-    -    if (!(initTriggerB instanceof Behaviour)) { ++    if (!(initTriggerB instanceof Behaviour)) {       initTriggerB = constant_b(initTriggerB);     }-    -    var triggerB = ++    var triggerB =     lift_b(-      function (d) { +      function (d) {         if ((typeof(d) == 'object') && (d.nodeType >  0)) {           return d;         } else {@@ -2114,26 +2114,26 @@         }       },       initTriggerB);-    +     var initD = valueNow(triggerB);-    if (!((typeof(initD) == 'object') && (initD.nodeType == 1))) { throw ('insertDomB: initial value conversion failed: ' + initD); } //SAFETY	-    +    if (!((typeof(initD) == 'object') && (initD.nodeType == 1))) { throw ('insertDomB: initial value conversion failed: ' + initD); } //SAFETY+     d.insertDom(-      optID === null || optID === undefined ? getObj(initD.getAttribute('id')) : getObj(optID), -      initD, +      optID === null || optID === undefined ? getObj(initD.getAttribute('id')) : getObj(optID),+      initD,       optPosition);-    +     var resB = hold(       d.insertDomE(         changes(triggerB),-        initD), +        initD),       initD);-    +     return resB;   };   annotate(d.insertDomB,['insertDomB'],0,[Behaviour.prototype],['insertDomB']);-  -  ++   d.extractId_b = function (id, start)   {     return hold(@@ -2146,7 +2146,7 @@       getObj(id));   };   annotate(d.insertDomB,['extractId_b'],1,[Behaviour.prototype],['extractId_b']);-  +   var mouse_e = function(elem) {     return extractEvent_e(elem,'mousemove')     .lift_e(function(evt) {@@ -2162,32 +2162,32 @@         }     });   };-  +   var mouse_b = function(elem) {     return mouse_e(elem).hold({ left: 0, top: 0 });   }   fxExport(dom,mouse_b,'mouse_b');-  +   var mouseLeft_b = function(elem) {     return lift_b(function(v) { return v.left; },mouse_b(elem));   };   fxExport(dom,mouseLeft_b,'mouseLeft_b');-  +   var mouseTop_b = function(elem) {     return mouse_b(elem).lift_b(function(v) { return v.top; });   };-  +   fxExport(dom,mouseTop_b,'mouseTop_b');-  +   var clicks_e = function(elem) {     return extractEvent_e(elem,'click');   };   fxExport(dom,clicks_e,'clicks_e');-  +   //////////////////////////////////////////////////////////////////////////////   // Combinators for web services-  -  ++ 	//credit Matt White 	var getURLParam = function (param) {     var lparam = param.toLowerCase();@@ -2207,7 +2207,7 @@     else return aReturn; 	};   fxExport(domMisc,getURLParam,'getURLParam','$URL');-  + 	//credit Quirksmode 	//readCookie: String -> String U Undefined 	var readCookie = function (name) {@@ -2216,21 +2216,21 @@     for (var i=0; i < ca.length; i++) {       var co = ca[i];       while (co.charAt(0) == ' ') { co = co.substring(1, co.length); }-      if (co.indexOf(nameEQ) === 0) { +      if (co.indexOf(nameEQ) === 0) {         return co.substring(nameEQ.length, co.length);       }     }-    return undefined;       +    return undefined; 	};   fxExport(domMisc,readCookie,'readCookie');-  +   //========== dynamic scripts ==========   var scriptCounter = 0;   var deleteScript = function (scriptID) {     var scriptD = getObj(scriptID);     scriptD.parentNode.removeChild(scriptD); //TODO isolate child and set innerHTML to "" to avoid psuedo-leaks?   };-  +   // optional fn/param that gets polled until parm is defined   var runScript = function (url, fn, param) {     var script = document.createElement("script");@@ -2239,7 +2239,7 @@     script.setAttribute('id', scriptID);     document.getElementsByTagName("head").item(0).appendChild(script);     var timer = {};-    var check = +    var check =     function () {       eval("try { if (" + param + "!== undefined) {var stat = " + param + ";}} catch (e) {}");       if (stat !== undefined) {@@ -2247,35 +2247,35 @@         clearInterval(timer.timer);         clearInterval(timer.timeout);         if (fn instanceof Function) {-          fn(stat); +          fn(stat);         }         deleteScript(scriptID);       }     };     timer.timer = setInterval(check, 3500);-    timer.timeout = -    setTimeout( -      function () { +    timer.timeout =+    setTimeout(+      function () {         try { clearInterval(timer.timer); }         catch (e) {}       },       5000); //TODO make parameter?   };-  +   // Node {url, globalArg} -> Node a   //load script @ url and poll until param is set, then pass it along   var evalForeignScriptVal_e = function(urlArg_e) {     var result = receiver_e();     urlArg_e.lift_e(function(urlArg) {         runScript(urlArg.url,-          function(val) { result.sendEvent(val); }, +          function(val) { result.sendEvent(val); },           urlArg.globalArg);     });-    +     return result;   };   fxExport(ws,evalForeignScriptVal_e,'evalForeignScriptVal_e');-  +   var ajaxRequest = function(method,url,body,async,useFlash,callback) {     var xhr;     if (useFlash) {@@ -2289,18 +2289,18 @@     else if (window.ActiveXObject) {       try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); }       catch(e) { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }-      +       xhr.onreadystatechange = function() {         if (xhr.readyState == 4) { callback(xhr); }       };     };-    +     xhr.open(method,url,async);-    +     if (method == 'POST') {       xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');     }-    +     xhr.send(body);     return xhr;   };@@ -2413,22 +2413,22 @@       else { throw 'parseJSON: unknown object type: ' + (typeof val); }     };   })();-   +   var serverRequest_e = function(useFlash,requestE) {     var response_e = receiver_e();-    +     requestE.lift_e(function (obj) {         var body = '';         var method = 'GET';         var url = obj.url;-        +         var reqType = obj.request ? obj.request : (obj.fields ? 'post' : 'get');         if (obj.request == 'get') {           url += "?" + encodeREST(obj.fields);           body = '';           method = 'GET';         } else if (obj.request == 'post') {-          body = toJSONString(obj.fields); +          body = toJSONString(obj.fields);           method = 'POST';         } else if (obj.request == 'rawPost') {           body = obj.body;@@ -2441,16 +2441,16 @@         else {           raise ("Invalid request type: " + obj.request);         }-        +         var async = obj.async;-        +         var xhr;-        +         // Branch on the response type to determine how to parse it         if (obj.response == 'json') {           xhr = ajaxRequest(method,url,body,async,useFlash,             function(xhr) {-              response_e.sendEvent(parseJSON(xhr.responseText)); +              response_e.sendEvent(parseJSON(xhr.responseText));             });         }         else if (obj.response == 'xml') {@@ -2469,15 +2469,15 @@           raise('Unknown response format: ' + obj.response);         }     });-    +     return response_e;   };-  +   var getWebServiceObject_e = function(requestE) {     return serverRequest_e(false,requestE);   };   fxExport(ws,getWebServiceObject_e,'getWebServiceObject_e');-  +   var getForeignWebServiceObject_e = function(requestE) {     return serverRequest_e(true,requestE);   };@@ -2502,7 +2502,7 @@       }     }   }-  +   for (var id in exports) {     if (window[id]) {       if (options.redefine === false) {@@ -2517,9 +2517,9 @@     if (window[id] && options.redefine === false) {       // Don't redefine id     }-    else if (options.show && options.hide && options.show[id] === true && +    else if (options.show && options.hide && options.show[id] === true &&         options.hide[id] === true) {-      throw('flapjaxInit: invalid options: ' + id + " specified as 'show' and 'hide'"); +      throw('flapjaxInit: invalid options: ' + id + " specified as 'show' and 'hide'");     }     else if (options.show && options.show[id]) {       window[id] = exports[id];@@ -2547,6 +2547,6 @@       }     }   }-  +   return exports; }