@@ -358,10 +358,9 @@ codegenJS_all target definitions includes filename outputType = do
358358 let js = concatMap (translateDecl info) bytecode
359359 let code = concatMap ((map compileJS) . collectSplitFunctions . (\x -> evalRWS (splitFunction x) () 0)) js
360360 let (header, rt) = case target of
361− Node ->
362− ("#!/usr/bin/env node\n", "-node")
363− JavaScript ->
364− ("", "-browser")
361+ Node -> ("#!/usr/bin/env node\n", "-node")
362+ JavaScript -> ("", "-browser")
363+
365364 included <- concat <$> getIncludes includes
366365 path <- (++) <$> getDataDir <*> (pure "/jsrts/")
367366 idrRuntime <- readFile $ path ++ "Runtime-common.js"
@@ -378,22 +377,59 @@ codegenJS_all target definitions includes filename outputType = do
378377 getIncludes = mapM readFile
379378
380379 main :: String
381− main = compileJS $
382− JSAlloc "main" $ Just $ JSFunction [] (
383− JSSeq [ JSAlloc "vm" (Just $ JSNew "i$VM" [])
384− , JSApp (JSIdent "i$SCHED") [JSIdent "vm"]
385− , JSApp (
386− JSIdent (translateName (sMN 0 "runMain"))
387− ) [JSNum (JSInt 0)]
388− , JSWhile (JSProj jsCALLSTACK "length") (
389− JSSeq [ JSAlloc "func" (Just jsPOP)
390− , JSAlloc "args" (Just jsPOP)
391− , JSApp (JSProj (JSIdent "func") "apply") [JSThis, JSIdent "args"]
392− ]
393− )
394− ]
380+ main =
381+ compileJS $ JSAlloc "main" (Just $
382+ JSFunction [] (
383+ case target of
384+ Node -> mainFun
385+ JavaScript -> jsMain
386+ )
395387 )
396388
389+ jsMain :: JS
390+ jsMain =
391+ JSCond [ (exists document `jsAnd` isReady, mainFun)
392+ , (exists window, windowMainFun)
393+ , (JSTrue, mainFun)
394+ ]
395+ where
396+ exists :: JS -> JS
397+ exists js = jsTypeOf js `jsNotEq` JSString "undefined"
398+
399+ window :: JS
400+ window = JSIdent "window"
401+
402+ document :: JS
403+ document = JSIdent "document"
404+
405+ windowMainFun :: JS
406+ windowMainFun =
407+ jsMeth window "addEventListener" [ JSString "DOMContentLoaded"
408+ , JSFunction [] ( mainFun )
409+ , JSFalse
410+ ]
411+
412+ isReady :: JS
413+ isReady = JSParens $ readyState `jsEq` JSString "complete" `jsOr` readyState `jsEq` JSString "loaded"
414+
415+ readyState :: JS
416+ readyState = JSProj (JSIdent "document") "readyState"
417+
418+ mainFun :: JS
419+ mainFun =
420+ JSSeq [ JSAlloc "vm" (Just $ JSNew "i$VM" [])
421+ , JSApp (JSIdent "i$SCHED") [JSIdent "vm"]
422+ , JSApp (
423+ JSIdent (translateName (sMN 0 "runMain"))
424+ ) [JSNum (JSInt 0)]
425+ , JSWhile (JSProj jsCALLSTACK "length") (
426+ JSSeq [ JSAlloc "func" (Just jsPOP)
427+ , JSAlloc "args" (Just jsPOP)
428+ , JSApp (JSProj (JSIdent "func") "apply") [JSThis, JSIdent "args"]
429+ ]
430+ )
431+ ]
432+
397433 invokeMain :: String
398434 invokeMain = compileJS $ JSApp (JSIdent "main") []
399435
@@ -421,8 +457,6 @@ splitFunction (JSAlloc name (Just (JSFunction args body@(JSSeq _)))) = do
421457 processBranches =
422458 traverse (runKleisli (arr id *** (Kleisli splitSequence)))
423459
424− splitCondition js = return js
425−
426460 splitSequence :: JS -> RWS () [(Int, JS)] Int JS
427461 splitSequence js@(JSSeq seq) = do
428462 let (pre,post) = break isCall seq in
@@ -716,6 +750,12 @@ jsOr lhs rhs = JSBinOp "||" lhs rhs
716750jsAnd :: JS -> JS -> JS
717751jsAnd lhs rhs = JSBinOp "&&" lhs rhs
718752
753+jsMeth :: JS -> String -> [JS] -> JS
754+jsMeth obj meth args = JSApp (JSProj obj meth) args
755+
756+jsCall :: String -> [JS] -> JS
757+jsCall fun args = JSApp (JSIdent fun) args
758+
719759jsTypeOf :: JS -> JS
720760jsTypeOf js = JSPreOp "typeof " js
721761
@@ -1398,12 +1438,6 @@ jsOP _ reg op args = JSAssign (translateReg reg) jsOP'
13981438 invokeMeth obj meth args =
13991439 JSApp (JSProj (translateReg obj) meth) $ map translateReg args
14001440
1401− jsMeth :: JS -> String -> [JS] -> JS
1402− jsMeth obj meth args = JSApp (JSProj obj meth) args
1403−
1404−
1405− jsCall :: String -> [JS] -> JS
1406− jsCall fun args = JSApp (JSIdent fun) args
14071441
14081442jsRESERVE :: CompileInfo -> Int -> JS
14091443jsRESERVE _ _ = JSNoop