on master help sign in
Merge branch 'dev' into webgl
9efd173John P Mayer Jr
Elm.cabal+1−1
@@ -1,5 +1,5 @@
1Name: Elm
1Name: Elm
2−Version: 0.10.1
2+Version: 0.11
3Synopsis: The Elm language module.
3Synopsis: The Elm language module.
4Description: Elm aims to make client-side web-development more pleasant.
4Description: Elm aims to make client-side web-development more pleasant.
5 It is a statically/strongly typed, functional reactive
5 It is a statically/strongly typed, functional reactive
README.md+1−1
@@ -7,7 +7,7 @@ Learn about the Elm programming language at [elm-lang.org](http://elm-lang.org/)
7**Arch Linux** — follow [these directions](https://github.com/evancz/Elm/wiki/Installing-Elm#arch-linux) and then
7**Arch Linux** — follow [these directions](https://github.com/evancz/Elm/wiki/Installing-Elm#arch-linux) and then
8jump to the [My First Project](#my-first-project) section.
8jump to the [My First Project](#my-first-project) section.
9<br/>
9<br/>
10−**OS X 10.9** &mdash; follow
10+**OS X 10.9 or XCode 5** &mdash; follow
11[these directions](http://justtesting.org/post/64947952690/the-glasgow-haskell-compiler-ghc-on-os-x-10-9)
11[these directions](http://justtesting.org/post/64947952690/the-glasgow-haskell-compiler-ghc-on-os-x-10-9)
12before continuing with the platform agnostic directions below.
12before continuing with the platform agnostic directions below.
13
13
compiler/Build/Dependencies.hs+30−22
@@ -29,10 +29,7 @@ getSortedDependencies srcDirs builtIns root =
29 result <- runErrorT $ readAllDeps allSrcDirs builtIns root
29 result <- runErrorT $ readAllDeps allSrcDirs builtIns root
30 case result of
30 case result of
31 Right deps -> sortDeps deps
31 Right deps -> sortDeps deps
32− Left err -> failure $ err ++ if Maybe.isJust extras then "" else msg
32+ Left err -> failure err
33− where msg = "\nYou may need to create a " ++
34− Path.dependencyFile ++
35− " file if you\nare trying to use a 3rd party library."
36
33
37extraDependencies :: IO (Maybe [FilePath])
34extraDependencies :: IO (Maybe [FilePath])
38extraDependencies =
35extraDependencies =
@@ -75,20 +72,22 @@ sortDeps depends =
75 msg = "A cyclical module dependency or was detected in:\n"
72 msg = "A cyclical module dependency or was detected in:\n"
76
73
77readAllDeps :: [FilePath] -> Module.Interfaces -> FilePath -> ErrorT String IO [Deps]
74readAllDeps :: [FilePath] -> Module.Interfaces -> FilePath -> ErrorT String IO [Deps]
78−readAllDeps srcDirs builtIns root =
75+readAllDeps srcDirs rawBuiltIns filePath =
79− do let ifaces = (Set.fromList . Map.keys) builtIns
80− State.evalStateT (go ifaces root) Set.empty
76+ State.evalStateT (go Nothing filePath) Set.empty
81 where
77 where
78+ builtIns :: Set.Set String
79+ builtIns = Set.fromList $ Map.keys rawBuiltIns
80+
82− go :: Set.Set String -> FilePath -> State.StateT (Set.Set String) (ErrorT String IO) [Deps]
81+ go :: Maybe String -> FilePath -> State.StateT (Set.Set String) (ErrorT String IO) [Deps]
83− go builtIns root = do
82+ go parentModuleName filePath = do
84− root' <- lift $ findSrcFile srcDirs root
83+ filePath' <- lift $ findSrcFile parentModuleName srcDirs filePath
85− (name, deps) <- lift $ readDeps root'
84+ (moduleName, deps) <- lift $ readDeps filePath'
86 seen <- State.get
85 seen <- State.get
87 let realDeps = Set.difference (Set.fromList deps) builtIns
86 let realDeps = Set.difference (Set.fromList deps) builtIns
88 newDeps = Set.difference (Set.filter (not . isNative) realDeps) seen
87 newDeps = Set.difference (Set.filter (not . isNative) realDeps) seen
89− State.put (Set.insert name (Set.union newDeps seen))
88+ State.put (Set.insert moduleName (Set.union newDeps seen))
90− rest <- mapM (go builtIns . toFilePath) (Set.toList newDeps)
89+ rest <- mapM (go (Just moduleName) . toFilePath) (Set.toList newDeps)
91− return ((makeRelative "." root', name, Set.toList realDeps) : concat rest)
90+ return ((makeRelative "." filePath', moduleName, Set.toList realDeps) : concat rest)
92
91
93readDeps :: FilePath -> ErrorT String IO (String, [String])
92readDeps :: FilePath -> ErrorT String IO (String, [String])
94readDeps path = do
93readDeps path = do
@@ -98,15 +97,10 @@ readDeps path = do
98 where msg = "Error resolving dependencies in " ++ path ++ ":\n"
97 where msg = "Error resolving dependencies in " ++ path ++ ":\n"
99 Right o -> return o
98 Right o -> return o
100
99
101−findSrcFile :: [FilePath] -> FilePath -> ErrorT String IO FilePath
100+findSrcFile :: Maybe String -> [FilePath] -> FilePath -> ErrorT String IO FilePath
101+findSrcFile parentModuleName dirs path =
102−findSrcFile dirs path = foldr tryDir notFound dirs
102+ foldr tryDir notFound dirs
103 where
103 where
104− notFound = throwError $ unlines
105− [ "Could not find file: " ++ path
106− , " If it is not in the root directory of your project, use"
107− , " --src-dir to declare additional locations for source files."
108− , " If it is part of a 3rd party library, it needs to be declared"
109− , " as a dependency in the " ++ Path.dependencyFile ++ " file." ]
110 tryDir dir next = do
104 tryDir dir next = do
111 let path' = dir </> path
105 let path' = dir </> path
112 exists <- liftIO $ doesFileExist path'
106 exists <- liftIO $ doesFileExist path'
@@ -114,6 +108,20 @@ findSrcFile dirs path = foldr tryDir notFound dirs
114 then return path'
108 then return path'
115 else next
109 else next
116
110
111+ parentModuleName' =
112+ case parentModuleName of
113+ Just name -> "module '" ++ name ++ "'"
114+ Nothing -> "the main module"
115+
116+ notFound = throwError $ unlines
117+ [ "When finding the imports declared in " ++ parentModuleName' ++ ", could not find file: " ++ path
118+ , " If you created this module, but it is in a subdirectory that does not"
119+ , " exactly match the module name, you may need to use the --src-dir flag."
120+ , ""
121+ , " If it is part of a 3rd party library, it needs to be declared"
122+ , " as a dependency in your project's " ++ Path.dependencyFile ++ " file."
123+ ]
124+
117isNative :: String -> Bool
125isNative :: String -> Bool
118isNative name = List.isPrefixOf "Native." name
126isNative name = List.isPrefixOf "Native." name
119
127
compiler/Generate/JavaScript.hs+2−2
@@ -314,7 +314,7 @@ generate unsafeModule =
314
314
315 jsImport modul = setup Nothing path ++ [ include ]
315 jsImport modul = setup Nothing path ++ [ include ]
316 where
316 where
317− path = split modul
317+ path = Help.splitDots modul
318 include = assign path $ dotSep ("Elm" : path ++ ["make"]) <| ref "_elm"
318 include = assign path $ dotSep ("Elm" : path ++ ["make"]) <| ref "_elm"
319
319
320 setup namespace path = map create paths
320 setup namespace path = map create paths
@@ -354,7 +354,7 @@ binop span op e1 e2 =
354 func | Help.isOp operator = BracketRef () (dotSep (init parts ++ ["_op"])) (string operator)
354 func | Help.isOp operator = BracketRef () (dotSep (init parts ++ ["_op"])) (string operator)
355 | otherwise = dotSep parts
355 | otherwise = dotSep parts
356 where
356 where
357− parts = split op
357+ parts = Help.splitDots op
358 operator = last parts
358 operator = last parts
359
359
360 opDict = Map.fromList (infixOps ++ specialOps)
360 opDict = Map.fromList (infixOps ++ specialOps)
compiler/SourceSyntax/Expression.hs+2−2
@@ -1,12 +1,12 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2−module SourceSyntax.Expression where
2+
3{-| The Abstract Syntax Tree (AST) for expressions comes in a couple formats.
3{-| The Abstract Syntax Tree (AST) for expressions comes in a couple formats.
4The first is the fully general version and is labeled with a prime (Expr').
4The first is the fully general version and is labeled with a prime (Expr').
5The others are specialized versions of the AST that represent specific phases
5The others are specialized versions of the AST that represent specific phases
6of the compilation process. I expect there to be more phases as we begin to
6of the compilation process. I expect there to be more phases as we begin to
7enrich the AST with more information.
7enrich the AST with more information.
8-}
8-}
9−
9+module SourceSyntax.Expression where
10
10
11import SourceSyntax.PrettyPrint
11import SourceSyntax.PrettyPrint
12import Text.PrettyPrint as P
12import Text.PrettyPrint as P
compiler/SourceSyntax/Helpers.hs+9
@@ -3,6 +3,15 @@ module SourceSyntax.Helpers where
3
3
4import qualified Data.Char as Char
4import qualified Data.Char as Char
5
5
6+splitDots :: String -> [String]
7+splitDots = go []
8+ where
9+ go vars str =
10+ case break (=='.') str of
11+ (x,_:rest) | isOp x -> vars ++ [x ++ '.' : rest]
12+ | otherwise -> go (vars ++ [x]) rest
13+ (x,[]) -> vars ++ [x]
14+
6brkt :: String -> String
15brkt :: String -> String
7brkt s = "{ " ++ s ++ " }"
16brkt s = "{ " ++ s ++ " }"
8
17
compiler/Transform/Canonicalize.hs+3−1
@@ -55,7 +55,9 @@ metadataModule :: Interfaces -> MetadataModule -> Either [Doc] MetadataModule
55metadataModule ifaces modul =
55metadataModule ifaces modul =
56 do case filter (\m -> Map.notMember m ifaces) (map fst realImports) of
56 do case filter (\m -> Map.notMember m ifaces) (map fst realImports) of
57 [] -> Right ()
57 [] -> Right ()
58− missings -> Left [ P.text $ "The following imports were not found: " ++ List.intercalate ", " missings ]
58+ missings -> Left [ P.text $ "The following imports were not found: " ++ List.intercalate ", " missings ++
59+ "\n You may need to compile with the --make flag to detect modules you have written."
60+ ]
59 program' <- rename initialEnv (program modul)
61 program' <- rename initialEnv (program modul)
60 aliases' <- mapM (three3 renameType') (aliases modul)
62 aliases' <- mapM (three3 renameType') (aliases modul)
61 datatypes' <- mapM (three3 (mapM (two2 (mapM renameType')))) (datatypes modul)
63 datatypes' <- mapM (three3 (mapM (two2 (mapM renameType')))) (datatypes modul)
compiler/Transform/SafeNames.hs+8−4
@@ -1,16 +1,20 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2module Transform.SafeNames (metadataModule) where
2module Transform.SafeNames (metadataModule) where
3
3
4−import Control.Arrow (first, (***))
4+import Control.Arrow (first, (***))
5+import Data.List (intercalate)
6+
7+import qualified Data.Set as Set
8+
9+import qualified Parse.Helpers as PHelp
5import SourceSyntax.Expression
10import SourceSyntax.Expression
11+import qualified SourceSyntax.Helpers as SHelp
6import SourceSyntax.Location
12import SourceSyntax.Location
7import SourceSyntax.Module
13import SourceSyntax.Module
8import SourceSyntax.Pattern
14import SourceSyntax.Pattern
9−import qualified Data.Set as Set
10−import qualified Parse.Helpers as PHelp
11
15
12var :: String -> String
16var :: String -> String
13−var = dereserve . deprime
17+var = intercalate "." . map (dereserve . deprime) . SHelp.splitDots
14 where
18 where
15 deprime = map (\c -> if c == '\'' then '$' else c)
19 deprime = map (\c -> if c == '\'' then '$' else c)
16 dereserve x = case Set.member x PHelp.jsReserveds of
20 dereserve x = case Set.member x PHelp.jsReserveds of
libraries/Basics.elm+1−1
@@ -320,7 +320,7 @@ It is defined as:
320 always a b = a
320 always a b = a
321
321
322It totally ignores the second argument, so `always 42` is a function that always
322It totally ignores the second argument, so `always 42` is a function that always
323−returns in 42. When you are dealing with higher-order functions, this comes in
323+returns 42. When you are dealing with higher-order functions, this comes in
324handy more often than you might expect. For example, creating a zeroed out list
324handy more often than you might expect. For example, creating a zeroed out list
325of length ten would be:
325of length ten would be:
326
326
libraries/Date.elm+5−1
@@ -5,7 +5,7 @@ module Date where
5issues with internationalization or locale formatting.
5issues with internationalization or locale formatting.
6
6
7# Conversions
7# Conversions
8−@docs read, toTime
8+@docs read, toTime, fromTime
9
9
10# Extractions
10# Extractions
11@docs year, month, Month, day, dayOfWeek, Day, hour, minute, second
11@docs year, month, Month, day, dayOfWeek, Day, hour, minute, second
@@ -36,6 +36,10 @@ read = Native.Date.read
36toTime : Date -> Time
36toTime : Date -> Time
37toTime = Native.Date.toTime
37toTime = Native.Date.toTime
38
38
39+{-| Take a UNIX time and convert it to a `Date` -}
40+fromTime : Time -> Date
41+fromTime = Native.Date.fromTime
42+
39{-| Extract the year of a given date. Given the date 23 June 1990 at 11:45AM
43{-| Extract the year of a given date. Given the date 23 June 1990 at 11:45AM
40this returns the integer `1990`. -}
44this returns the integer `1990`. -}
41year : Date -> Int
45year : Date -> Int
libraries/Mouse.elm+1−6
@@ -7,7 +7,7 @@ module Mouse where
7@docs position, x, y
7@docs position, x, y
8
8
9# Button Status
9# Button Status
10−@docs isDown, clicks, isClicked
10+@docs isDown, clicks
11
11
12-}
12-}
13
13
@@ -31,11 +31,6 @@ True when the button is down, and false otherwise. -}
31isDown : Signal Bool
31isDown : Signal Bool
32isDown = Native.Mouse.isDown
32isDown = Native.Mouse.isDown
33
33
34−{-| True immediately after the left mouse-button has been clicked,
35−and false otherwise. -}
36−isClicked : Signal Bool
37−isClicked = Native.Mouse.isClicked
38−
39{-| Always equal to unit. Event triggers on every mouse click. -}
34{-| Always equal to unit. Event triggers on every mouse click. -}
40clicks : Signal ()
35clicks : Signal ()
41clicks = Native.Mouse.clicks
36clicks = Native.Mouse.clicks
libraries/Native/Date.js+1
@@ -27,6 +27,7 @@ Elm.Native.Date.make = function(elm) {
27 minute : function(d) { return d.getMinutes(); },
27 minute : function(d) { return d.getMinutes(); },
28 second : function(d) { return d.getSeconds(); },
28 second : function(d) { return d.getSeconds(); },
29 toTime : function(d) { return d.getTime(); },
29 toTime : function(d) { return d.getTime(); },
30+ fromTime: function(t) { return new window.Date(t); },
30 dayOfWeek : function(d) { return { ctor:dayTable[d.getDay()] }; }
31 dayOfWeek : function(d) { return { ctor:dayTable[d.getDay()] }; }
31 };
32 };
32
33
libraries/Native/Signal/Mouse.js+2−6
@@ -20,15 +20,12 @@ Elm.Native.Mouse.make = function(elm) {
20 y.defaultNumberOfKids = 0;
20 y.defaultNumberOfKids = 0;
21
21
22 var isDown = Signal.constant(false);
22 var isDown = Signal.constant(false);
23− var isClicked = Signal.constant(false);
24 var clicks = Signal.constant(Utils.Tuple0);
23 var clicks = Signal.constant(Utils.Tuple0);
25
24
26 var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
25 var node = elm.display === ElmRuntime.Display.FULLSCREEN ? document : elm.node;
27
26
28− elm.addListener([isClicked.id, clicks.id], node, 'click', function click() {
27+ elm.addListener([clicks.id], node, 'click', function click() {
29− elm.notify(isClicked.id, true);
30 elm.notify(clicks.id, Utils.Tuple0);
28 elm.notify(clicks.id, Utils.Tuple0);
31− elm.notify(isClicked.id, false);
32 });
29 });
33 elm.addListener([isDown.id], node, 'mousedown', function down() {
30 elm.addListener([isDown.id], node, 'mousedown', function down() {
34 elm.notify(isDown.id, true);
31 elm.notify(isDown.id, true);
@@ -44,8 +41,7 @@ Elm.Native.Mouse.make = function(elm) {
44 position: position,
41 position: position,
45 x:x,
42 x:x,
46 y:y,
43 y:y,
47− isClicked: isClicked,
48 isDown: isDown,
44 isDown: isDown,
49 clicks: clicks
45 clicks: clicks
50 };
46 };
51−};
47+};
libraries/Native/Signal/Signal.js−9
@@ -127,12 +127,6 @@ Elm.Native.Signal.make = function(elm) {
127 input.kids.push(this);
127 input.kids.push(this);
128 }
128 }
129
129
130− function dropWhen(s1,b,s2) {
131− var pairs = lift2( F2(function(x,y){return {x:x,y:y};}), s1, s2 );
132− var dropped = new DropIf(function(p){return p.x;},{x:true,y:b},pairs);
133− return lift(function(p){return p.y;}, dropped);
134− }
135−
136 function timestamp(a) {
130 function timestamp(a) {
137 function update() { return Utils.Tuple2(Date.now(), a.value); }
131 function update() { return Utils.Tuple2(Date.now(), a.value); }
138 return new LiftN(update, [a]);
132 return new LiftN(update, [a]);
@@ -225,9 +219,6 @@ Elm.Native.Signal.make = function(elm) {
225 keepIf : F3(function(pred,base,sig) {
219 keepIf : F3(function(pred,base,sig) {
226 return new DropIf(function(x) {return !pred(x);},base,sig); }),
220 return new DropIf(function(x) {return !pred(x);},base,sig); }),
227 dropIf : F3(function(pred,base,sig) { return new DropIf(pred,base,sig); }),
221 dropIf : F3(function(pred,base,sig) { return new DropIf(pred,base,sig); }),
228− keepWhen : F3(function(s1,b,s2) {
229− return dropWhen(lift(function(b){return !b;},s1), b, s2); }),
230− dropWhen : F3(dropWhen),
231 dropRepeats : function(s) { return new DropRepeats(s);},
222 dropRepeats : function(s) { return new DropRepeats(s);},
232 sampleOn : F2(sampleOn),
223 sampleOn : F2(sampleOn),
233 timestamp : timestamp
224 timestamp : timestamp
libraries/Native/Trampoline.jsnew file+22
@@ -0,0 +1,22 @@
1+Elm.Native.Trampoline = {};
2+Elm.Native.Trampoline.make = function(elm) {
3+ elm.Native = elm.Native || {};
4+ elm.Native.Trampoline = elm.Native.Trampoline || {};
5+ if (elm.Native.Trampoline.values) return elm.Native.Trampoline.values;
6+
7+ // trampoline : Trampoline a -> a
8+ trampoline = function(t) {
9+ var tramp = t;
10+ while(true) {
11+ switch(tramp.ctor) {
12+ case "Done":
13+ return tramp._0;
14+ case "Continue":
15+ tramp = tramp._0({ctor: "_Tuple0"});
16+ continue;
17+ }
18+ }
19+ }
20+
21+ return elm.Native.Trampoline.values = { trampoline: trampoline };
22+};
libraries/Signal.elm+7−2
@@ -32,6 +32,10 @@ the [`Time`](/docs/Signal/Time.elm) library.
32import Native.Signal
32import Native.Signal
33import List (foldr)
33import List (foldr)
34
34
35+import Basics (fst, snd, not)
36+import Native.Error
37+import Maybe as M
38+
35data Signal a = Signal
39data Signal a = Signal
36
40
37{-| Create a constant signal that never changes. -}
41{-| Create a constant signal that never changes. -}
@@ -122,7 +126,8 @@ Until the first signal becomes false again, all events will be propagated. Elm
122does not allow undefined signals, so a base case must be provided in case the
126does not allow undefined signals, so a base case must be provided in case the
123first signal is not true initially. -}
127first signal is not true initially. -}
124keepWhen : Signal Bool -> a -> Signal a -> Signal a
128keepWhen : Signal Bool -> a -> Signal a -> Signal a
125−keepWhen = Native.Signal.keepWhen
129+keepWhen bs def sig =
130+ snd <~ (keepIf fst (False, def) ((,) <~ (sampleOn sig bs) ~ sig))
126
131
127{-| Drop events when the first signal is true. When the first signal becomes
132{-| Drop events when the first signal is true. When the first signal becomes
128false, the most recent value of the second signal will be propagated. Until the
133false, the most recent value of the second signal will be propagated. Until the
@@ -130,7 +135,7 @@ first signal becomes true again, all events will be propagated. Elm does not
130allow undefined signals, s oa base case must be provided in case the first
135allow undefined signals, s oa base case must be provided in case the first
131signal is true initially. -}
136signal is true initially. -}
132dropWhen : Signal Bool -> a -> Signal a -> Signal a
137dropWhen : Signal Bool -> a -> Signal a -> Signal a
133−dropWhen = Native.Signal.dropWhen
138+dropWhen bs = keepWhen (not <~ bs)
134
139
135{-| Drop updates that repeat the current value of the signal.
140{-| Drop updates that repeat the current value of the signal.
136
141
libraries/Trampoline.elmnew file+49
@@ -0,0 +1,49 @@
1+module Trampoline where
2+{-| A [trampoline](http://en.wikipedia.org/wiki/Tail-recursive_function#Through_trampolining)
3+makes it possible to recursively call a function without growing the stack.
4+
5+Popular JavaScript implementations do not perform any tail-call elimination, so
6+recursive functions can cause a stack overflow if they go to deep. Trampolines
7+permit unbounded recursion despite limitations in JavaScript.
8+
9+This strategy may create many intermediate closures, which is very expensive in
10+JavaScript, so use this library only when it is essential that you recurse deeply.
11+
12+# Trampolines
13+@docs trampoline, Trampoline
14+-}
15+
16+import Native.Trampoline
17+
18+{-| A way to build computations that may be deeply recursive. We will take an
19+example of a tail-recursive function and rewrite it in a way that lets us use
20+a trampoline:
21+
22+ length : [a] -> Int
23+ length list = length' 0 list
24+
25+ length' : Int -> [a] -> Int
26+ length' accum list =
27+ case list of
28+ [] -> accum
29+ hd::tl -> length' (accum+1) tl
30+
31+This finds the length of a list, but if the list is too long, it may cause a
32+stack overflow. We can rewrite it as follows:
33+
34+ length : [a] -> Int
35+ length list = trampoline (length' 0 list)
36+
37+ length' : Int -> [a] -> Trampoline Int
38+ length' accum list =
39+ case list of
40+ [] -> Done accum
41+ hd::tl -> Continue (\() -> length' (accum+1) tl)
42+
43+Now it uses a trampoline and can recurse without growing the stack!
44+-}
45+data Trampoline a = Done a | Continue (() -> Trampoline a)
46+
47+{-| Evaluate a trampolined value in constant space. -}
48+trampoline : Trampoline a -> a
49+trampoline = Native.Trampoline.trampoline
libraries/elm_dependencies.json+3−3
@@ -1,9 +1,9 @@
1−{ "version": "0.10.1"
1+{ "version": "0.11"
2, "summary": "Elm's standard libraries"
2, "summary": "Elm's standard libraries"
3−, "description": "The full set of standard libraries for Elm. This library is pegged to the version number of the compiler, so if you are using Elm 0.10.1, you should be using version 0.10.1 of the standard libraries."
3+, "description": "The full set of standard libraries for Elm. This library is pegged to the version number of the compiler, so if you are using Elm 0.11, you should be using version 0.11 of the standard libraries."
4, "license": "BSD3"
4, "license": "BSD3"
5, "repository": "http://github.com/evancz/Elm.git"
5, "repository": "http://github.com/evancz/Elm.git"
6−, "elm-version": "0.10.1"
6+, "elm-version": "0.11"
7, "dependencies": {}
7, "dependencies": {}
8, "exposed-modules":
8, "exposed-modules":
9 [ "Basics"
9 [ "Basics"
runtime/Utils.js+1−1
@@ -34,7 +34,7 @@ ElmRuntime.filterDeadInputs = function(inputs) {
34
34
35// define the draw function
35// define the draw function
36var vendors = ['ms', 'moz', 'webkit', 'o'];
36var vendors = ['ms', 'moz', 'webkit', 'o'];
37−var win = window || {};
37+var win = typeof window !== 'undefined' ? window : {};
38for (var i = 0; i < vendors.length && !win.requestAnimationFrame; ++i) {
38for (var i = 0; i < vendors.length && !win.requestAnimationFrame; ++i) {
39 win.requestAnimationFrame = win[vendors[i]+'RequestAnimationFrame'];
39 win.requestAnimationFrame = win[vendors[i]+'RequestAnimationFrame'];
40 win.cancelAnimationFrame = win[vendors[i]+'CancelAnimationFrame'] ||
40 win.cancelAnimationFrame = win[vendors[i]+'CancelAnimationFrame'] ||