on master help sign in
Merge branch 'json' into dev
a862b89Evan Czaplicki
compiler/Generate/JavaScript.hs+1−2
@@ -39,7 +39,6 @@ internalImports name =
39 , include "_U" "_N.Utils"
39 , include "_U" "_N.Utils"
40 , include "_L" "_N.List"
40 , include "_L" "_N.List"
41 , include "_E" "_N.Error"
41 , include "_E" "_N.Error"
42− , include "_J" "_N.JavaScript"
43 , varDecl "$moduleName" (string name)
42 , varDecl "$moduleName" (string name)
44 ]
43 ]
45
44
@@ -163,7 +162,7 @@ expression (A region expr) =
163
162
164 ExplicitList es ->
163 ExplicitList es ->
165 do es' <- mapM expression es
164 do es' <- mapM expression es
166− return $ obj "_J.toList" <| ArrayLit () es'
165+ return $ obj "_L.fromArray" <| ArrayLit () es'
167
166
168 Data name es ->
167 Data name es ->
169 do es' <- mapM expression es
168 do es' <- mapM expression es
compiler/Generate/JavaScript/Ports.hs+14−15
@@ -35,17 +35,17 @@ inc tipe x =
35 case tipe of
35 case tipe of
36 Lambda _ _ -> error "functions should not be allowed through input ports"
36 Lambda _ _ -> error "functions should not be allowed through input ports"
37 Var _ -> error "type variables should not be allowed through input ports"
37 Var _ -> error "type variables should not be allowed through input ports"
38+
39+ Data "Json.Value" [] ->
40+ obj "Native.Json.fromJS" <| x
41+
38 Data ctor []
42 Data ctor []
39− | ctor == "Int" -> elm JSNumber
43+ | ctor == "Int" -> from JSNumber
40− | ctor == "Float" -> elm JSNumber
44+ | ctor == "Float" -> from JSNumber
41− | ctor == "Bool" -> elm JSBoolean
45+ | ctor == "Bool" -> from JSBoolean
42− | ctor == "String" -> elm JSString
46+ | ctor == "String" -> from JSString
43− | ctor == "JavaScript.JSNumber" -> js JSNumber
44− | ctor == "JavaScript.JSBool" -> js JSBoolean
45− | ctor == "JavaScript.JSString" -> js JSString
46 where
47 where
47− elm checks = check x checks (obj ("_J.to" ++ ctor) <| x)
48− js checks = check x checks x
48+ from checks = check x checks x
49
49
50 Data ctor [t]
50 Data ctor [t]
51 | ctor == "Maybe.Maybe" ->
51 | ctor == "Maybe.Maybe" ->
@@ -54,7 +54,7 @@ inc tipe x =
54 (obj "Maybe.Just" <| inc t x)
54 (obj "Maybe.Just" <| inc t x)
55
55
56 | ctor == "_List" ->
56 | ctor == "_List" ->
57− check x JSArray (obj "_J.toList" <| array)
57+ check x JSArray (obj "_L.fromArray" <| array)
58 where
58 where
59 array = DotRef () x (var "map") <| incoming t
59 array = DotRef () x (var "map") <| incoming t
60
60
@@ -104,10 +104,9 @@ out tipe x =
104
104
105 Var _ -> error "type variables should not be allowed through input ports"
105 Var _ -> error "type variables should not be allowed through input ports"
106 Data ctor []
106 Data ctor []
107− | ctor `elem` ["Int","Float","Bool","String"] -> obj ("_J.from" ++ ctor) <| x
107+ | ctor `elem` ["Int","Float","Bool","String"] -> x
108− | ctor `elem` jsPrims -> x
108+ | ctor == "Json.Value" ->
109− where
109+ obj "Native.Json.toJS" <| x
110− jsPrims = map ("JavaScript.JS"++) ["Number","Bool","String"]
111
110
112 Data ctor [t]
111 Data ctor [t]
113 | ctor == "Maybe.Maybe" ->
112 | ctor == "Maybe.Maybe" ->
@@ -116,7 +115,7 @@ out tipe x =
116 (out t (DotRef () x (var "_0")))
115 (out t (DotRef () x (var "_0")))
117
116
118 | ctor == "_List" ->
117 | ctor == "_List" ->
119− DotRef () (obj "_J.fromList" <| x) (var "map") <| outgoing t
118+ DotRef () (obj "_L.toArray" <| x) (var "map") <| outgoing t
120
119
121 Data ctor ts
120 Data ctor ts
122 | Help.isTuple ctor ->
121 | Help.isTuple ctor ->
compiler/Metadata/Prelude.hs+3−1
@@ -25,7 +25,9 @@ prelude = string ++ text ++ map (\n -> (n, Hiding [])) modules
25 text = map ((,) "Text") [ As "Text", Hiding ["link", "color", "height"] ]
25 text = map ((,) "Text") [ As "Text", Hiding ["link", "color", "height"] ]
26 string = map ((,) "String") [ As "String", Importing ["show"] ]
26 string = map ((,) "String") [ As "String", Importing ["show"] ]
27 modules = [ "Basics", "Signal", "List", "Maybe", "Time", "Color"
27 modules = [ "Basics", "Signal", "List", "Maybe", "Time", "Color"
28− , "Graphics.Element", "Graphics.Collage", "Native.Ports" ]
28+ , "Graphics.Element", "Graphics.Collage"
29+ , "Native.Ports", "Native.Json"
30+ ]
29
31
30interfaces :: Bool -> IO Interfaces
32interfaces :: Bool -> IO Interfaces
31interfaces noPrelude =
33interfaces noPrelude =
compiler/Type/ExtraChecks.hs+7−10
@@ -8,7 +8,6 @@ module Type.ExtraChecks (mainType, occurs, portTypes) where
8
8
9import Control.Applicative ((<$>),(<*>))
9import Control.Applicative ((<$>),(<*>))
10import Control.Monad.State
10import Control.Monad.State
11−import qualified Data.List as List
12import qualified Data.Map as Map
11import qualified Data.Map as Map
13import qualified Data.Traversable as Traverse
12import qualified Data.Traversable as Traverse
14import qualified Data.UnionFind.IO as UF
13import qualified Data.UnionFind.IO as UF
@@ -56,9 +55,15 @@ portTypes rules expr =
56 isValid isTopLevel seenFunc seenSignal direction name tipe =
55 isValid isTopLevel seenFunc seenSignal direction name tipe =
57 case tipe of
56 case tipe of
58 ST.Data ctor ts
57 ST.Data ctor ts
59− | isJs ctor || isElm ctor -> mapM_ valid ts
58+ | validConstructor -> mapM_ valid ts
60 | ctor == "Signal.Signal" -> handleSignal ts
59 | ctor == "Signal.Signal" -> handleSignal ts
61 | otherwise -> err' True "an unsupported type"
60 | otherwise -> err' True "an unsupported type"
61+ where
62+ primitives =
63+ ["Int","Float","String","Bool","Maybe.Maybe","_List","Json.Value"]
64+
65+ validConstructor =
66+ ctor `elem` primitives || Help.isTuple ctor
62
67
63 ST.Var _ -> err "free type variables"
68 ST.Var _ -> err "free type variables"
64
69
@@ -80,14 +85,6 @@ portTypes rules expr =
80 isValid' = isValid False
85 isValid' = isValid False
81 valid = isValid' seenFunc seenSignal direction name
86 valid = isValid' seenFunc seenSignal direction name
82
87
83− isJs ctor =
84− List.isPrefixOf "JavaScript." ctor
85− && length (filter (=='.') ctor) == 1
86−
87− isElm ctor =
88− ctor `elem` ["Int","Float","String","Bool","Maybe.Maybe","_List"]
89− || Help.isTuple ctor
90−
91 handleSignal ts
88 handleSignal ts
92 | seenFunc = err "functions that involve signals"
89 | seenFunc = err "functions that involve signals"
93 | seenSignal = err "signals-of-signals"
90 | seenSignal = err "signals-of-signals"
libraries/Graphics/Collage.elm−1
@@ -38,7 +38,6 @@ import Native.Graphics.Collage
38import Graphics.Element (Element)
38import Graphics.Element (Element)
39import Color (Color, black, Gradient)
39import Color (Color, black, Gradient)
40import Maybe (Maybe)
40import Maybe (Maybe)
41−import JavaScript (JSString)
42
41
43type Form = {
42type Form = {
44 theta : Float,
43 theta : Float,
libraries/Graphics/Element.elm+10−13
@@ -39,8 +39,6 @@ If you need more precision, you can create custom positions.
39
39
40import Basics (..)
40import Basics (..)
41import Native.Utils
41import Native.Utils
42−import JavaScript as JS
43−import JavaScript (JSString)
44import List as List
42import List as List
45import Color (..)
43import Color (..)
46import Maybe (Maybe, Just, Nothing)
44import Maybe (Maybe, Just, Nothing)
@@ -51,8 +49,8 @@ type Properties = {
51 height : Int,
49 height : Int,
52 opacity : Float,
50 opacity : Float,
53 color : Maybe Color,
51 color : Maybe Color,
54− href : JSString,
52+ href : String,
55− tag : JSString,
53+ tag : String,
56 hover : (),
54 hover : (),
57 click : ()
55 click : ()
58 }
56 }
@@ -120,21 +118,20 @@ with a link like this: `/facts-about-animals.elm#all-about-badgers`
120-}
118-}
121tag : String -> Element -> Element
119tag : String -> Element -> Element
122tag name e = let p = e.props in
120tag name e = let p = e.props in
123− { element=e.element, props={p | tag <- JS.fromString name} }
121+ { element=e.element, props={p | tag <- name} }
124
122
125{-| Create an `Element` that is a hyper-link. -}
123{-| Create an `Element` that is a hyper-link. -}
126link : String -> Element -> Element
124link : String -> Element -> Element
127link href e = let p = e.props in
125link href e = let p = e.props in
128− { element=e.element, props={p | href <- JS.fromString href} }
126+ { element=e.element, props={p | href <- href} }
129
127
130−emptyStr = JS.fromString ""
131newElement w h e =
128newElement w h e =
132− { props = Properties (Native.Utils.guid ()) w h 1 Nothing emptyStr emptyStr () ()
129+ { props = Properties (Native.Utils.guid ()) w h 1 Nothing "" "" () ()
133 , element = e
130 , element = e
134 }
131 }
135
132
136data ElementPrim
133data ElementPrim
137− = Image ImageStyle Int Int JSString
134+ = Image ImageStyle Int Int String
138 | Container Position Element
135 | Container Position Element
139 | Flow Direction [Element]
136 | Flow Direction [Element]
140 | Spacer
137 | Spacer
@@ -145,13 +142,13 @@ data ImageStyle = Plain | Fitted | Cropped (Int,Int) | Tiled
145
142
146{-| Create an image given a width, height, and image source. -}
143{-| Create an image given a width, height, and image source. -}
147image : Int -> Int -> String -> Element
144image : Int -> Int -> String -> Element
148−image w h src = newElement w h (Image Plain w h (JS.fromString src))
145+image w h src = newElement w h (Image Plain w h src)
149
146
150{-| Create a fitted image given a width, height, and image source.
147{-| Create a fitted image given a width, height, and image source.
151This will crop the picture to best fill the given dimensions.
148This will crop the picture to best fill the given dimensions.
152-}
149-}
153fittedImage : Int -> Int -> String -> Element
150fittedImage : Int -> Int -> String -> Element
154−fittedImage w h src = newElement w h (Image Fitted w h (JS.fromString src))
151+fittedImage w h src = newElement w h (Image Fitted w h src)
155
152
156{-| Create a cropped image. Take a rectangle out of the picture starting
153{-| Create a cropped image. Take a rectangle out of the picture starting
157at the given top left coordinate. If you have a 140-by-140 image,
154at the given top left coordinate. If you have a 140-by-140 image,
@@ -161,11 +158,11 @@ the following will cut a 100-by-100 square out of the middle of it.
161-}
158-}
162croppedImage : (Int,Int) -> Int -> Int -> String -> Element
159croppedImage : (Int,Int) -> Int -> Int -> String -> Element
163croppedImage pos w h src =
160croppedImage pos w h src =
164− newElement w h (Image (Cropped pos) w h (JS.fromString src))
161+ newElement w h (Image (Cropped pos) w h src)
165
162
166tiledImage : Int -> Int -> String -> Element
163tiledImage : Int -> Int -> String -> Element
167tiledImage w h src =
164tiledImage w h src =
168− newElement w h (Image Tiled w h (JS.fromString src))
165+ newElement w h (Image Tiled w h src)
169
166
170data Three = P | Z | N
167data Three = P | Z | N
171data Pos = Absolute Int | Relative Float
168data Pos = Absolute Int | Relative Float
libraries/JavaScript.elmdeleted−74
@@ -1,74 +0,0 @@
1−
2−module JavaScript where
3−
4−{-|This library does basic conversions between Elm and JS values. This allows
5−the internal data structures of Elm to change and improve with no impact on JS
6−integration.
7−
8−It is intended to be imported as `import JavaScript as JS`. That way functions
9−like `JS.toInt` convert JavaScript *to* Elm integers and functions like
10−`JS.fromString` gets JavaScript *from* Elm strings.
11−
12−# Javascript to Elm
13−@docs toString, toInt, toFloat, toBool, toList
14−
15−# JavaScript from Elm
16−@docs fromString, fromInt, fromFloat, fromBool, fromList
17−-}
18−{-
19−# DOM Nodes and Elements
20−@docs toElement, fromElement
21−-}
22−
23−import Native.JavaScript
24−
25−data JSNumber = JSNumber
26−data JSBool = JSBool
27−data JSString = JSString
28−data JSArray a = JSArray a
29−data JSDomNode = JSDomNode
30−data JSObject = JSObject
31−
32−{-| Requires that the input array be uniform (all members have the same type) -}
33−toList : JSArray a -> [a]
34−toList = Native.JavaScript.toList
35−
36−toInt : JSNumber -> Int
37−toInt = Native.JavaScript.toInt
38−
39−toFloat : JSNumber -> Float
40−toFloat = Native.JavaScript.toFloat
41−
42−toBool : JSBool -> Bool
43−toBool = Native.JavaScript.toBool
44−
45−toString : JSString -> String
46−toString = Native.JavaScript.toString
47−
48−
49−{-| Produces a uniform JavaScript array with all members of the same type. -}
50−fromList : [a] -> JSArray a
51−fromList = Native.JavaScript.fromList
52−
53−fromInt : Int -> JSNumber
54−fromInt = Native.JavaScript.fromInt
55−
56−fromFloat : Float -> JSNumber
57−fromFloat = Native.JavaScript.fromFloat
58−
59−fromBool : Bool -> JSBool
60−fromBool = Native.JavaScript.fromBool
61−
62−fromString : String -> JSString
63−fromString = Native.JavaScript.fromString
64−
65−{-
66−{-| Turn an `Element` into a DOM node. -}
67−fromElement : Element -> JSDomNode
68−fromElement = Native.JavaScript.fromElement
69−
70−{-| Turn a DOM node into an `Element`. You can resize the node
71−using the normal `width` and `height` functions. -}
72−toElement : Int -> Int -> JSDomNode -> Element
73−toElement = Native.JavaScript.toElement
74−-}
libraries/JavaScript/Experimental.elm+30−16
@@ -8,34 +8,48 @@ improve as we find its key failings.
8@docs toRecord, fromRecord
8@docs toRecord, fromRecord
9-}
9-}
10
10
11−import JavaScript (JSObject)
12import Native.JavaScript
11import Native.JavaScript
12+import Json
13+
14+data RawObject = RawObject
13
15
14{-| Turn arbitrary JavaScript objects into Elm records.
16{-| Turn arbitrary JavaScript objects into Elm records.
15Arrays are converted into lists, nested objects are allowed.
17Arrays are converted into lists, nested objects are allowed.
16No `null` values or non-homogeneous arrays.
18No `null` values or non-homogeneous arrays.
17
19
18− -- OK objects
20+ -- OK objects
19− { student:"Steve", scores:[83,94,99,72] }
21+ { student:"Steve", scores:[83,94,99,72] }
20− { errorLevel:10, critical:true }
22+ { errorLevel:10, critical:true }
21
23
22− -- BAD objects
24+ -- BAD objects
23− { answer:null }
25+ { answer:null }
24− { info:[true,42,'what'] }
26+ { info:[true,42,'what'] }
25-}
27-}
26−toRecord : JSObject -> a
28+toRecord : RawObject -> a
27toRecord = Native.JavaScript.toRecord
29toRecord = Native.JavaScript.toRecord
28
30
29{-| Turn arbitrary Elm records into JavaScript objects.
31{-| Turn arbitrary Elm records into JavaScript objects.
30Lists become arrays, nested records are allowed. No ADTs.
32Lists become arrays, nested records are allowed. No ADTs.
31
33
32− -- OK records
34+ -- OK records
33− { student="Steve", scores=[83,94,99,72] }
35+ { student="Steve", scores=[83,94,99,72] }
34− { errorLevel=10, critical=True }
36+ { errorLevel=10, critical=True }
37+
38+ -- BAD records
39+ { answer = Nothing }
40+ { result = Left "An error occurred" }
41+-}
42+fromRecord : a -> RawObject
43+fromRecord = Native.JavaScript.fromRecord
44+
45+{-| Turn a raw JavaScript object into a `Json.Value` as described in the
46+`Json` library.
47+-}
48+toJson : RawObject -> Json.Value
49+toJson = Native.Json.fromJS
35
50
36− -- BAD records
51+{-| Turn a `Json.Value` (as described in the `Json` library) into a raw
37− { answer = Nothing }
52+JavaScript object.
38− { result = Left "An error occurred" }
39-}
53-}
40−fromRecord : a -> JSObject
54+fromJson : Json.Value -> RawObject
41−fromRecord = Native.JavaScript.fromRecord
55+fromJson = Native.Json.toJS
libraries/Json.elm+25−110
@@ -3,132 +3,47 @@ module Json where
3
3
4{-| Library for working with [JSON](https://en.wikipedia.org/wiki/JSON) values.
4{-| Library for working with [JSON](https://en.wikipedia.org/wiki/JSON) values.
5
5
6−# Json Values
7−@docs JsonValue
8−
9−# Strings
10−@docs fromString, toString
6+@docs Value, fromString, toString
11−
12−# JS Strings
13−@docs fromJSString, toJSString
14−
15−# JS Objects
16−@docs fromJSObject, toJSObject
17
7
18-}
8-}
19
9
20−import Basics (..)
21import Dict
10import Dict
22import Maybe (Maybe)
11import Maybe (Maybe)
23−import JavaScript as JS
24import Native.Json
12import Native.Json
25−import JavaScript (JSObject, JSString)
26
13
27−{-| This datatype can represent all valid values that can be held in a JSON
14+{-| This datatype can represent all valid JSON values. A `Value` can be sent
28−object. In Elm, a proper JSON object is represented as a (Dict String JsonValue)
15+through ports, and the runtime will do a conversion like this:
29−which is a mapping from strings to Json Values. -}
16+
30−data JsonValue
17+ [2,'abc',null] == Array [Number 2, String "abc", Null]
18+
19+JSON is an intentional subset of JavaScript values which excludes functions.
20+This ensures that impure functions cannot sneak into Elm through ports.
21+-}
22+data Value
31 = String String
23 = String String
32 | Number Float
24 | Number Float
33 | Boolean Bool
25 | Boolean Bool
34 | Null
26 | Null
35− | Array [JsonValue]
27+ | Array [Value]
36− | Object (Dict.Dict String JsonValue)
28+ | Object (Dict.Dict String Value)
37−
38
29
39−-- String Converters
40
30
41−{-| Convert a `JsonValue` into a prettified string.
31+{-| Convert a `Value` into a prettified string.
42The first argument is a separator token (e.g. \" \", \"\\n\", etc.) that will
32The first argument is a separator token (e.g. \" \", \"\\n\", etc.) that will
43−be used for indentation in the prettified string version of the JSON. -}
33+be used for indentation in the prettified string version of the JSON.
44−toString : String -> JsonValue -> String
45−toString sep v = JS.toString (Native.Json.toJSString sep v)
46
34
47−{-| Convert a proper JSON object into a JavaScript string.
35+ toString "" Null == "null"
48−Note that the type JSString seen here is not the same as the type constructor
36+ toString "" (Number 4.0) == "4.0"
49−JsonString used elsewhere in this module. -}
37+-}
50−toJSString : String -> JsonValue -> JSString
38+toString : String -> Value -> String
51−toJSString = Native.Json.toJSString
39+toString sep value = Native.Json.toString sep value
52
40
53{-| Parse a string representation of a proper JSON object into
41{-| Parse a string representation of a proper JSON object into
54−its Elm representation. -}
42+its Elm representation.
55−fromString : String -> Maybe JsonValue
56−fromString s = Native.Json.fromJSString (JS.fromString s)
57−
58−{-| Parse a JavaScript string representation of a proper JSON object into
59−its Elm representation. -}
60−fromJSString : JSString -> Maybe JsonValue
61−fromJSString = Native.Json.fromJSString
62−
63−{-| Convert a JS object into a `JsonValue`. -}
64−fromJSObject : JSObject -> JsonValue
65−fromJSObject = Native.Json.fromJSObject
66
43
67−{-| Convert a `JsonValue` into a `JSObject`. Paired with the
44+ fromString "null" == Just Null
68−[`JavaScript.Experimental` library](/docs/JavaScript/Experimental.elm),
45+ fromString "[true,3]" == Just (Array [Boolean True, Number 3])
69−This lets you convert strings into Elm records:
46+ fromString "{'abc':4}" == Just (Object (Dict.fromList [("abc", Number 4)]))
70−
71− import JavaScript.Experimental as JS
72−
73− stringToRecord str =
74− case fromString str of
75− Just jsonValue -> Just (JS.toRecord (toJSObject jsonValue))
76− Nothing -> Nothing
77-}
47-}
78−toJSObject : JsonValue -> JSObject
48+fromString : String -> Maybe Value
79−toJSObject = Native.Json.toJSObject
49+fromString str = Native.Json.fromString str
80−
81− {-- Extract Elm values from Json values
82−
83− string : JsonValue -> String
84− string v = case v of { String s -> s ; _ -> "" }
85−
86− number : JsonValue -> Float
87− number v = case v of { Number n -> n ; _ -> 0 }
88−
89− boolean : JsonValue -> Bool
90− boolean v = case v of { Boolean b -> b ; _ -> False }
91−
92− array : JsonValue -> [JsonValue]
93− array v = case v of { Array a -> a ; _ -> [] }
94−
95− object : JsonValue -> Dict String JsonValue
96− object v = case v of { Object o -> o ; _ -> Dict.empty }
97−
98−
99− -- Extract Elm values from dictionaries of Json values
100−
101− {-| Find a value in a Json Object using the passed get function. If the key is
102− not found, this returns the given default/base value. -}
103− find get base =
104− let f key dict =
105− case Dict.lookup key dict of
106− Nothing -> base
107− Just v -> get v
108− in f
109−
110− {-| Find a string value in an Elm Json object. If the key is not found or the
111− value found is not a string, this returns the empty string. -}
112− findString : String -> Object -> String
113− findString = find string ""
114−
115− {-| Find a number value in an Elm Json object. If the key is not found or the
116− value found is not a number, this returns 0 -}
117− findNumber : String -> Object -> Float
118− findNumber = find number 0
119−
120− {-| Find a boolean value in an Elm Json object. If the key is not found or the
121− value found is not a boolean, this returns the False. -}
122− findBoolean : String -> Object -> Bool
123− findBoolean = find boolean False
124−
125− {-| Find an array value in an Elm Json object. If the key is not found or the
126− value found is not an array, this returns an empty list. -}
127− findArray : String -> Object -> [JsonValue]
128− findArray = find array []
129−
130− {-| Find an object value in an Elm Json object. If the key is not found or the
131− value found is not an object, this returns an empty object. -}
132− findObject : String -> Object -> Object
133− findObject = find object Dict.empty
134− --}
libraries/Native/Date.js+1−2
@@ -4,12 +4,11 @@ Elm.Native.Date.make = function(elm) {
4 elm.Native.Date = elm.Native.Date || {};
4 elm.Native.Date = elm.Native.Date || {};
5 if (elm.Native.Date.values) return elm.Native.Date.values;
5 if (elm.Native.Date.values) return elm.Native.Date.values;
6
6
7− var JS = Elm.JavaScript.make(elm);
8 var Maybe = Elm.Maybe.make(elm);
7 var Maybe = Elm.Maybe.make(elm);
9
8
10 function dateNow() { return new window.Date; }
9 function dateNow() { return new window.Date; }
11 function readDate(str) {
10 function readDate(str) {
12− var d = new window.Date(JS.fromString(str));
11+ var d = new window.Date(str);
13 if (isNaN(d.getTime())) return Maybe.Nothing;
12 if (isNaN(d.getTime())) return Maybe.Nothing;
14 return Maybe.Just(d);
13 return Maybe.Just(d);
15 }
14 }
libraries/Native/JavaScript.js+59−91
@@ -1,100 +1,68 @@
1Elm.Native.JavaScript = {};
1Elm.Native.JavaScript = {};
2Elm.Native.JavaScript.make = function(elm) {
2Elm.Native.JavaScript.make = function(elm) {
3− elm.Native = elm.Native || {};
3+ elm.Native = elm.Native || {};
4− elm.Native.JavaScript = elm.Native.JavaScript || {};
4+ elm.Native.JavaScript = elm.Native.JavaScript || {};
5− if (elm.Native.JavaScript.values) return elm.Native.JavaScript.values;
5+ if (elm.Native.JavaScript.values) return elm.Native.JavaScript.values;
6
6
7− var List = Elm.Native.List.make(elm);
7+ var List = Elm.Native.List.make(elm);
8− var Render = ElmRuntime.use(ElmRuntime.Render.Element);
8+ var Render = ElmRuntime.use(ElmRuntime.Render.Element);
9
9
10− function fromJS(v) {
10+ function fromJS(v) {
11− var type = typeof v;
11+ var type = typeof v;
12− if (type === 'number' ) return v;
12+ if (type === 'number' ) return v;
13− if (type === 'boolean') return v;
13+ if (type === 'boolean') return v;
14− if (type === 'string' ) return v;
14+ if (type === 'string' ) return v;
15− if (v instanceof Array) {
15+ if (v instanceof Array) {
16− var arr = [];
16+ var arr = [];
17− var len = v.length;
17+ var len = v.length;
18− for (var i = 0; i < len; ++i) {
18+ for (var i = 0; i < len; ++i) {
19− var x = fromJS(v[i]);
19+ var x = fromJS(v[i]);
20− if (x !== null) arr.push(x);
20+ if (x !== null) arr.push(x);
21− }
21+ }
22− return List.fromArray(arr);
22+ return List.fromArray(arr);
23− }
23+ }
24− if (type === 'object') {
24+ if (type === 'object') {
25− var rec = { _:{} };
25+ var rec = { _:{} };
26− for (var f in v) {
26+ for (var f in v) {
27− var x = fromJS(v[f]);
27+ var x = fromJS(v[f]);
28− if (x !== null) rec[f] = x;
28+ if (x !== null) rec[f] = x;
29− }
29+ }
30− return rec;
30+ return rec;
31− }
31+ }
32− return null;
32+ return null;
33− }
33+ }
34
34
35− function toJS(v) {
35+ function toJS(v) {
36− var type = typeof v;
36+ var type = typeof v;
37− if (type === 'number' || type === 'boolean' || type === 'string') return v;
37+ if (type === 'number' || type === 'boolean' || type === 'string') return v;
38− if (type === 'object' && '_' in v) {
38+ if (type === 'object' && '_' in v) {
39− var obj = {};
39+ var obj = {};
40− for (var k in v) {
40+ for (var k in v) {
41− var x = toJS(v[k]);
41+ var x = toJS(v[k]);
42− if (x !== null) obj[k] = x;
42+ if (x !== null) obj[k] = x;
43− }
43+ }
44− return obj;
44+ return obj;
45− }
45+ }
46− if (type === 'object' && (v.ctor === '::' || v.ctor === '[]')) {
46+ if (type === 'object' && (v.ctor === '::' || v.ctor === '[]')) {
47− var array = List.toArray(v);
47+ var array = List.toArray(v);
48− for (var i = array.length; i--; ) {
48+ for (var i = array.length; i--; ) {
49− array[i] = toJS(array[i]);
49+ array[i] = toJS(array[i]);
50− }
50+ }
51− return array;
51+ return array;
52− }
52+ }
53− return null;
53+ return null;
54− }
54+ }
55
55
56− function fromRecord(r) {
56+ function fromRecord(r) {
57− if (typeof r === 'object' && '_' in r) {
57+ if (typeof r === 'object' && '_' in r) {
58− return toJS(r);
58+ return toJS(r);
59− }
59+ }
60− throw new Error("'fromRecord' must be called on a record.");
60+ throw new Error("'fromRecord' must be called on a record.");
61− }
61+ }
62
62
63− function id(n) { return n; }
64−
65− function toElement(w,h,domNode) {
66− return A3( newElement, w, h, {
67− ctor: 'Custom',
68− type: 'DomNode',
69− render: function(node) { return node; },
70− update: function(node,oldNode,newNode) {
71− if (node === newNode) return;
72− node.parentNode.replaceChild(newNode, node);
73− },
74− model: domNode
75− });
76− }
77−
78− function fromElement(element) {
79− return Render.render(element);
80− }
81−
82− return elm.Native.JavaScript.values = {
63+ return elm.Native.JavaScript.values = {
83− toInt : function(n) { return n|0; },
84− toFloat : function(n) { return +n; },
85− toBool : id,
86− toString : id,
87− toList : List.fromArray,
88− fromString : id,
89− fromList : List.toArray,
90− fromInt : id,
91− fromFloat : id,
92− fromBool : id,
93−
94− toElement : toElement,
95− fromElement : fromElement,
96− toRecord : fromJS,
64+ toRecord : fromJS,
97− fromRecord : fromRecord
65+ fromRecord : fromRecord
98− };
66+ };
99
67
100};
68};
libraries/Native/Json.js+71−58
@@ -1,72 +1,85 @@
1Elm.Native.Json = {};
1Elm.Native.Json = {};
2Elm.Native.Json.make = function(elm) {
2Elm.Native.Json.make = function(elm) {
3
3
4− elm.Native = elm.Native || {};
4+ elm.Native = elm.Native || {};
5− elm.Native.Json = elm.Native.Json || {};
5+ elm.Native.Json = elm.Native.Json || {};
6− if (elm.Native.Json.values) return elm.Native.Json.values;
6+ if (elm.Native.Json.values) return elm.Native.Json.values;
7
7
8− var Maybe = Elm.Maybe.make(elm);
8+ var Maybe = Elm.Maybe.make(elm);
9− var Dict = Elm.Dict.make(elm);
9+ var Dict = Elm.Dict.make(elm);
10− var List = Elm.List.make(elm);
10+ var List = Elm.Native.List.make(elm);
11− var JS = Elm.JavaScript.make(elm);
12− var Utils = Elm.Native.Utils.make(elm);
11+ var Utils = Elm.Native.Utils.make(elm);
13
12
14− function fromValue(v) {
13+ function toJS(v) {
15− switch (v.ctor) {
14+ switch (v.ctor) {
16− case 'Null' : return null;
15+ case 'Null' : return null;
17− case 'String' : return JS.fromString(v._0);
16+ case 'String' : return v._0;
17+ case 'Number' : return v._0;
18+ case 'Boolean': return v._0;
18− case 'Object' :
19+ case 'Object' :
19− var obj = {};
20+ var obj = {};
20− var array = JS.fromList(Dict.toList(v._0));
21+ var array = List.toArray(Dict.toList(v._0));
21− for (var i = array.length; i--; ) {
22+ for (var i = array.length; i--; ) {
22− obj[JS.fromString(array[i]._0)] = fromValue(array[i]._1);
23+ var entry = array[i];
24+ obj[entry._0] = toJS(entry._1);
23− }
25+ }
24− return obj;
26+ return obj;
25− case 'Array' :
27+ case 'Array' :
26− var array = JS.fromList(v._0);
28+ var array = List.toArray(v._0);
27− for (var i = array.length; i--; ) {
29+ for (var i = array.length; i--; ) {
28− array[i] = fromValue(array[i]);
30+ array[i] = toJS(array[i]);
29− }
31+ }
30− return array;
32+ return array;
31− default :
33+ }
32− return v._0;
33 }
34 }
34− }
35
35
36− function toPrettyJSString(sep, obj) {
36+ function toString(sep, value) {
37− return JSON.stringify(fromValue(obj), null, JS.fromString(sep));
37+ return JSON.stringify(toJS(value), null, sep);
38− }
38+ }
39
39
40− function toValue(v) {
40+ function fromJS(v) {
41− switch (typeof v) {
41+ switch (typeof v) {
42− case 'string' : return { ctor:"String", _0: JS.toString(v) };
42+ case 'string' : return { ctor:"String" , _0: v };
43− case 'number' : return { ctor:"Number", _0: JS.toFloat(v) };
43+ case 'number' : return { ctor:"Number" , _0: v };
44− case 'boolean': return { ctor:"Boolean" , _0: JS.toBool(v) };
44+ case 'boolean': return { ctor:"Boolean", _0: v };
45− case 'object' :
45+ case 'object' :
46− if (v === null) return { ctor:"Null" };
46+ if (v === null) return { ctor:"Null" };
47− if (v instanceof Array) {
47+ if (v instanceof Array) {
48+ var array = new Array(v.length);
48− for (var i = v.length; i--; ) { v[i] = toValue(v[i]); }
49+ for (var i = v.length; i--; ) {
50+ array[i] = fromJS(v[i]);
51+ }
52+ return {
49− return { ctor:"Array", _0: JS.toList(v) };
53+ ctor:"Array",
54+ _0: List.fromArray(array)
55+ };
50− }
56+ }
51− var array = [];
57+ var array = [];
58+ for (var key in v) {
59+ var value = fromJS(v[key]);
52− for (var k in v) array.push(Utils.Tuple2(JS.toString(k), toValue(v[k])));
60+ array.push(Utils.Tuple2(key, value));
61+ }
62+ var list = List.fromArray(array);
63+ return {
64+ ctor:"Object",
53− return { ctor:"Object", _0: Dict.fromList(JS.toList(array)) };
65+ _0: Dict.fromList(list)
66+ };
67+ }
54 }
68 }
55− }
56
69
57− function fromJSString(str) {
70+ function fromString(str) {
58− try {
71+ try {
59− return Maybe.Just(toValue(JSON.parse(str)));
72+ return Maybe.Just(fromJS(JSON.parse(str)));
60− } catch (e) {
73+ } catch (e) {
61− return Maybe.Nothing;
74+ return Maybe.Nothing;
75+ }
62 }
76 }
63− }
64
77
65− return elm.Native.Json.values = {
78+ return elm.Native.Json.values = {
66− toJSString : F2(toPrettyJSString),
79+ toString : F2(toString),
67− fromJSString : fromJSString,
80+ fromString : fromString,
68− toJSObject : fromValue,
81+ fromJS : fromJS,
69− fromJSObject : toValue
82+ toJS : toJS,
70− };
83+ };
71
84
72};
85};
libraries/Native/Regex.js+14−14
@@ -6,8 +6,8 @@ Elm.Native.Regex.make = function(elm) {
6 if ('values' in Elm.Native.Regex)
6 if ('values' in Elm.Native.Regex)
7 return elm.Native.Regex.values = Elm.Native.Regex.values;
7 return elm.Native.Regex.values = Elm.Native.Regex.values;
8
8
9+ var List = Elm.Native.List.make(elm);
9 var Maybe = Elm.Maybe.make(elm);
10 var Maybe = Elm.Maybe.make(elm);
10− var JS = Elm.JavaScript.make(elm);
11
11
12 function escape(str) {
12 function escape(str) {
13 return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
13 return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
@@ -20,14 +20,14 @@ Elm.Native.Regex.make = function(elm) {
20 }
20 }
21
21
22 function contains(re, string) {
22 function contains(re, string) {
23− return JS.fromString(string).match(re) !== null;
23+ return string.match(re) !== null;
24 }
24 }
25
25
26 function find(n, re, str) {
26 function find(n, re, str) {
27 n = n.ctor === "All" ? Infinity : n._0;
27 n = n.ctor === "All" ? Infinity : n._0;
28 var out = [];
28 var out = [];
29 var number = 0;
29 var number = 0;
30− var string = JS.fromString(str);
30+ var string = str;
31 var result;
31 var result;
32 while (number++ < n && (result = re.exec(string))) {
32 while (number++ < n && (result = re.exec(string))) {
33 var i = result.length - 1;
33 var i = result.length - 1;
@@ -36,17 +36,17 @@ Elm.Native.Regex.make = function(elm) {
36 var submatch = result[i];
36 var submatch = result[i];
37 subs[--i] = submatch === undefined
37 subs[--i] = submatch === undefined
38 ? Maybe.Nothing
38 ? Maybe.Nothing
39− : Maybe.Just(JS.toString(submatch));
39+ : Maybe.Just(submatch);
40 }
40 }
41 out.push({
41 out.push({
42 _:{},
42 _:{},
43− match: JS.toString(result[0]),
43+ match: result[0],
44− submatches: JS.toList(subs),
44+ submatches: List.fromArray(subs),
45 index: result.index,
45 index: result.index,
46 number: number,
46 number: number,
47 });
47 });
48 }
48 }
49− return JS.toList(out);
49+ return List.fromArray(out);
50 }
50 }
51
51
52 function replace(n, re, replacer, string) {
52 function replace(n, re, replacer, string) {
@@ -60,24 +60,24 @@ Elm.Native.Regex.make = function(elm) {
60 var submatch = arguments[i];
60 var submatch = arguments[i];
61 submatches[--i] = submatch === undefined
61 submatches[--i] = submatch === undefined
62 ? Maybe.Nothing
62 ? Maybe.Nothing
63− : Maybe.Just(JS.toString(submatch));
63+ : Maybe.Just(submatch);
64 }
64 }
65− return JS.fromString(replacer({
65+ return replacer({
66 _:{},
66 _:{},
67 match:match,
67 match:match,
68− submatches:JS.toList(submatches),
68+ submatches:List.fromArray(submatches),
69 index:arguments[i-1],
69 index:arguments[i-1],
70 number:count
70 number:count
71− }));
71+ });
72 }
72 }
73 return string.replace(re, jsReplacer);
73 return string.replace(re, jsReplacer);
74 }
74 }
75
75
76 function split(n, re, str) {
76 function split(n, re, str) {
77 if (n === Infinity) {
77 if (n === Infinity) {
78− return JS.toList(JS.fromString(string).split(re));
78+ return List.fromArray(string.split(re));
79 }
79 }
80− var string = JS.fromString(str);
80+ var string = str;
81 var result;
81 var result;
82 var out = [];
82 var out = [];
83 var start = re.lastIndex;
83 var start = re.lastIndex;
@@ -87,7 +87,7 @@ Elm.Native.Regex.make = function(elm) {
87 start = re.lastIndex;
87 start = re.lastIndex;
88 }
88 }
89 out.push(string.slice(start));
89 out.push(string.slice(start));
90− return JS.toList(out);
90+ return List.fromArray(out);
91 }
91 }
92
92
93 return Elm.Native.Regex.values = {
93 return Elm.Native.Regex.values = {
libraries/Native/Signal/Http.js+6−7
@@ -5,7 +5,6 @@ Elm.Native.Http.make = function(elm) {
5 elm.Native.Http = elm.Native.Http || {};
5 elm.Native.Http = elm.Native.Http || {};
6 if (elm.Native.Http.values) return elm.Native.Http.values;
6 if (elm.Native.Http.values) return elm.Native.Http.values;
7
7
8− var JS = Elm.JavaScript.make(elm);
9 var List = Elm.List.make(elm);
8 var List = Elm.List.make(elm);
10 var Signal = Elm.Signal.make(elm);
9 var Signal = Elm.Signal.make(elm);
11
10
@@ -38,17 +37,17 @@ Elm.Native.Http.make = function(elm) {
38 request.onreadystatechange = function(e) {
37 request.onreadystatechange = function(e) {
39 if (request.readyState === 4) {
38 if (request.readyState === 4) {
40 response.value = (request.status >= 200 && request.status < 300 ?
39 response.value = (request.status >= 200 && request.status < 300 ?
41− { ctor:'Success', _0:JS.toString(request.responseText) } :
40+ { ctor:'Success', _0:request.responseText } :
42− { ctor:'Failure', _0:request.status, _1:JS.toString(request.statusText) });
41+ { ctor:'Failure', _0:request.status, _1:request.statusText });
43 setTimeout(function() { updateQueue(queue,responses); }, 0);
42 setTimeout(function() { updateQueue(queue,responses); }, 0);
44 }
43 }
45 };
44 };
46− request.open(JS.fromString(req.verb), JS.fromString(req.url), true);
45+ request.open(req.verb, req.url, true);
47 function setHeader(pair) {
46 function setHeader(pair) {
48− request.setRequestHeader( JS.fromString(pair._0), JS.fromString(pair._1) );
47+ request.setRequestHeader( pair._0, pair._1 );
49 }
48 }
50− List.map(setHeader)(req.headers);
49+ A2( List.map, setHeader, req.headers );
51− request.send(JS.fromString(req.body));
50+ request.send(req.body);
52 }
51 }
53
52
54 function send(requests) {
53 function send(requests) {
libraries/Native/Signal/Touch.js+3−3
@@ -6,7 +6,7 @@ Elm.Native.Touch.make = function(elm) {
6 if (elm.Native.Touch.values) return elm.Native.Touch.values;
6 if (elm.Native.Touch.values) return elm.Native.Touch.values;
7
7
8 var Signal = Elm.Signal.make(elm);
8 var Signal = Elm.Signal.make(elm);
9− var JS = Elm.JavaScript.make(elm);
9+ var List = Elm.Native.List.make(elm);
10 var Utils = Elm.Native.Utils.make(elm);
10 var Utils = Elm.Native.Utils.make(elm);
11
11
12 function Dict() {
12 function Dict() {
@@ -136,7 +136,7 @@ Elm.Native.Touch.make = function(elm) {
136 return sig;
136 return sig;
137 }
137 }
138
138
139− var touches = dependency(JS.toList);
139+ var touches = dependency(List.fromArray);
140
140
141 var taps = function() {
141 var taps = function() {
142 var sig = dependency(function(_) { return tap; });
142 var sig = dependency(function(_) { return tap; });
@@ -149,4 +149,4 @@ Elm.Native.Touch.make = function(elm) {
149
149
150 return elm.Native.Touch.values = { touches: touches, taps: taps };
150 return elm.Native.Touch.values = { touches: touches, taps: taps };
151
151
152−};
152+};
libraries/Native/Signal/WebSocket.js+3−5
@@ -6,12 +6,11 @@ Elm.Native.WebSocket.make = function(elm) {
6 if (elm.Native.WebSocket.values) return elm.Native.WebSocket.values;
6 if (elm.Native.WebSocket.values) return elm.Native.WebSocket.values;
7
7
8 var Signal = Elm.Signal.make(elm);
8 var Signal = Elm.Signal.make(elm);
9− var JS = Elm.JavaScript.make(elm);
10 var List = Elm.Native.List.make(elm);
9 var List = Elm.Native.List.make(elm);
11
10
12 function open(url, outgoing) {
11 function open(url, outgoing) {
13 var incoming = Signal.constant(List.Nil);
12 var incoming = Signal.constant(List.Nil);
14− var ws = new WebSocket(JS.fromString(url));
13+ var ws = new WebSocket(url);
15
14
16 var pending = [];
15 var pending = [];
17 var ready = false;
16 var ready = false;
@@ -22,12 +21,11 @@ Elm.Native.WebSocket.make = function(elm) {
22 ready = true;
21 ready = true;
23 };
22 };
24 ws.onmessage = function(event) {
23 ws.onmessage = function(event) {
25− elm.notify(incoming.id, JS.toString(event.data));
24+ elm.notify(incoming.id, event.data);
26 };
25 };
27
26
28 function send(msg) {
27 function send(msg) {
29− var s = JS.fromString(msg);
30− ready ? ws.send(s) : pending.push(s);
28+ ready ? ws.send(msg) : pending.push(msg);
31 }
29 }
32
30
33 function take1(x,y) { return x }
31 function take1(x,y) { return x }
libraries/Native/String.js+9−9
@@ -8,7 +8,7 @@ Elm.Native.String.make = function(elm) {
8
8
9 var Char = Elm.Char.make(elm);
9 var Char = Elm.Char.make(elm);
10 var Maybe = Elm.Maybe.make(elm);
10 var Maybe = Elm.Maybe.make(elm);
11− var JS = Elm.JavaScript.make(elm);
11+ var List = Elm.Native.List.make(elm);
12 var Utils = Elm.Native.Utils.make(elm);
12 var Utils = Elm.Native.Utils.make(elm);
13
13
14 function isEmpty(str) {
14 function isEmpty(str) {
@@ -26,7 +26,7 @@ Elm.Native.String.make = function(elm) {
26 return a + b;
26 return a + b;
27 }
27 }
28 function concat(strs) {
28 function concat(strs) {
29− return JS.fromList(strs).join('');
29+ return List.toArray(strs).join('');
30 }
30 }
31 function length(str) {
31 function length(str) {
32 return str.length;
32 return str.length;
@@ -59,10 +59,10 @@ Elm.Native.String.make = function(elm) {
59 }
59 }
60
60
61 function split(sep, str) {
61 function split(sep, str) {
62− return JS.toList(str.split(sep));
62+ return List.fromArray(str.split(sep));
63 }
63 }
64 function join(sep, strs) {
64 function join(sep, strs) {
65− return JS.fromList(strs).join(sep);
65+ return List.toArray(strs).join(sep);
66 }
66 }
67 function repeat(n, str) {
67 function repeat(n, str) {
68 var result = '';
68 var result = '';
@@ -111,10 +111,10 @@ Elm.Native.String.make = function(elm) {
111 }
111 }
112
112
113 function words(str) {
113 function words(str) {
114− return JS.toList(str.split(/\s+/g));
114+ return List.fromArray(str.split(/\s+/g));
115 }
115 }
116 function lines(str) {
116 function lines(str) {
117− return JS.toList(str.split(/\r\n|\r|\n/g));
117+ return List.fromArray(str.split(/\r\n|\r|\n/g));
118 }
118 }
119
119
120 function toUpper(str) {
120 function toUpper(str) {
@@ -155,7 +155,7 @@ Elm.Native.String.make = function(elm) {
155 is.push(i);
155 is.push(i);
156 i = i + subLen;
156 i = i + subLen;
157 }
157 }
158− return JS.toList(is);
158+ return List.fromArray(is);
159 }
159 }
160
160
161 function toInt(s) {
161 function toInt(s) {
@@ -193,10 +193,10 @@ Elm.Native.String.make = function(elm) {
193 }
193 }
194
194
195 function toList(str) {
195 function toList(str) {
196− return JS.toList(str.split('').map(Utils.chr));
196+ return List.fromArray(str.split('').map(Utils.chr));
197 }
197 }
198 function fromList(chars) {
198 function fromList(chars) {
199− return JS.fromList(chars).join('');
199+ return List.toArray(chars).join('');
200 }
200 }
201
201
202 return Elm.Native.String.values = {
202 return Elm.Native.String.values = {
libraries/Text.elm−1
@@ -35,7 +35,6 @@ import String
35import Color (Color, black)
35import Color (Color, black)
36import Graphics.Element (Element, Three, Pos, ElementPrim, Properties)
36import Graphics.Element (Element, Three, Pos, ElementPrim, Properties)
37import Maybe (Maybe, Nothing)
37import Maybe (Maybe, Nothing)
38−import JavaScript (JSString)
39import Native.Show
38import Native.Show
40import Native.Text
39import Native.Text
41
40
libraries/elm_dependencies.json−1
@@ -19,7 +19,6 @@
19 , "Graphics.Input"
19 , "Graphics.Input"
20 , "Graphics.Input.Field"
20 , "Graphics.Input.Field"
21 , "Http"
21 , "Http"
22− , "JavaScript"
23 , "JavaScript.Experimental"
22 , "JavaScript.Experimental"
24 , "Json"
23 , "Json"
25 , "Keyboard"
24 , "Keyboard"