packages feed

javascript-extras 0.2.0.2 → 0.3.0.0

raw patch · 7 files changed

+296/−281 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- JavaScript.Extras.Recast: class FromJS a
- JavaScript.Extras.Recast: class ToJS a where toJS = jsval
- JavaScript.Extras.Recast: fromJS :: FromJS a => JSVal -> IO (Maybe a)
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS (JavaScript.Array.Internal.SomeJSArray m)
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS Data.JSString.Internal.Type.JSString
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS Data.Text.Internal.Text
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Int.Int16
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Int.Int32
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Int.Int8
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Types.Bool
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Types.Char
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Types.Double
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Types.Float
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Types.Int
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Types.Word
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Word.Word16
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Word.Word32
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHC.Word.Word8
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS GHCJS.Prim.JSVal
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS JavaScript.Object.Internal.Object
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.FromJS [GHC.Types.Char]
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS (GHCJS.Foreign.Callback.Internal.Callback a)
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS (GHCJS.Foreign.Export.Export a)
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS (GHCJS.Nullable.Nullable a)
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS (JavaScript.Array.Internal.SomeJSArray m)
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS Data.JSString.Internal.Type.JSString
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS Data.Text.Internal.Text
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Int.Int16
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Int.Int32
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Int.Int8
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Types.Bool
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Types.Char
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Types.Double
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Types.Float
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Types.Int
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Types.Word
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Word.Word16
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Word.Word32
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHC.Word.Word8
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS GHCJS.Prim.JSVal
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS JavaScript.Object.Internal.Object
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS [GHC.Types.Char]
- JavaScript.Extras.Recast: instance JavaScript.Extras.Recast.ToJS a => JavaScript.Extras.Recast.ToJS (GHC.Base.Maybe a)
- JavaScript.Extras.Recast: toJS :: (ToJS a, IsJSVal a) => a -> JSVal
- JavaScript.Extras.String: strJS :: JSString -> JSVal
- JavaScript.Extras.String: strJS' :: [Char] -> JSVal
- JavaScript.Extras.String: txtJS :: Text -> JSVal
+ JavaScript.Extras.Cast: class FromJS a
+ JavaScript.Extras.Cast: class ToJS a where toJS = jsval
+ JavaScript.Extras.Cast: fromJS :: FromJS a => JSVal -> Maybe a
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS (JavaScript.Array.Internal.SomeJSArray m)
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS Data.JSString.Internal.Type.JSString
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS Data.Text.Internal.Text
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Base.String
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Int.Int16
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Int.Int32
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Int.Int8
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Types.Bool
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Types.Char
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Types.Double
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Types.Float
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Types.Int
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Types.Word
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Word.Word16
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Word.Word32
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHC.Word.Word8
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS GHCJS.Prim.JSVal
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.FromJS JavaScript.Object.Internal.Object
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS (GHCJS.Foreign.Callback.Internal.Callback a)
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS (GHCJS.Foreign.Export.Export a)
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS (GHCJS.Nullable.Nullable a)
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS (JavaScript.Array.Internal.SomeJSArray m)
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS Data.JSString.Internal.Type.JSString
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS Data.Text.Internal.Text
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Base.String
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Int.Int16
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Int.Int32
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Int.Int8
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Types.Bool
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Types.Char
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Types.Double
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Types.Float
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Types.Int
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Types.Word
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Word.Word16
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Word.Word32
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHC.Word.Word8
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS GHCJS.Prim.JSVal
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS JavaScript.Object.Internal.Object
+ JavaScript.Extras.Cast: instance JavaScript.Extras.Cast.ToJS a => JavaScript.Extras.Cast.ToJS (GHC.Base.Maybe a)
+ JavaScript.Extras.Cast: toJS :: (ToJS a, IsJSVal a) => a -> JSVal
+ JavaScript.Extras.JSVar: JSVar :: JSVal -> JSVar
+ JavaScript.Extras.JSVar: fromJS' :: FromJS a => JSVar -> Maybe a
+ JavaScript.Extras.JSVar: instance Control.DeepSeq.NFData JavaScript.Extras.JSVar.JSVar
+ JavaScript.Extras.JSVar: instance Data.String.IsString JavaScript.Extras.JSVar.JSVar
+ JavaScript.Extras.JSVar: instance GHCJS.Internal.Types.IsJSVal JavaScript.Extras.JSVar.JSVar
+ JavaScript.Extras.JSVar: instance GHCJS.Marshal.Internal.PToJSVal JavaScript.Extras.JSVar.JSVar
+ JavaScript.Extras.JSVar: instance JavaScript.Extras.Cast.FromJS JavaScript.Extras.JSVar.JSVar
+ JavaScript.Extras.JSVar: instance JavaScript.Extras.Cast.ToJS JavaScript.Extras.JSVar.JSVar
+ JavaScript.Extras.JSVar: newtype JSVar
+ JavaScript.Extras.JSVar: toJS' :: ToJS a => a -> JSVar
- JavaScript.Extras.Property: getProperty :: JSString -> JSVal -> IO JSVal
+ JavaScript.Extras.Property: getProperty :: JSString -> JSVal -> IO JSVar
- JavaScript.Extras.Property: type Property = (JSString, JSVal)
+ JavaScript.Extras.Property: type Property = (JSString, JSVar)

Files

javascript-extras.cabal view
@@ -1,5 +1,5 @@ name:                javascript-extras-version:             0.2.0.2+version:             0.3.0.0 synopsis:            Extra javascript functions when using GHCJS description:         Extra javascript functions when using GHCJS homepage:            https://github.com/louispan/javascript-extras#readme@@ -17,10 +17,10 @@   hs-source-dirs:      src   js-sources:          jsbits/extras.js   exposed-modules:     JavaScript.Extras+                       JavaScript.Extras.Cast                        JavaScript.Extras.Number                        JavaScript.Extras.Property-                       JavaScript.Extras.Recast-                       JavaScript.Extras.String+                       JavaScript.Extras.JSVar   build-depends:       base >= 4.7 && < 5                      , deepseq >= 1.4 && < 2                      , parallel >= 3.2 && < 4
src/JavaScript/Extras.hs view
@@ -1,11 +1,11 @@ module JavaScript.Extras-    ( module JavaScript.Extras.Number+    ( module JavaScript.Extras.Cast+    , module JavaScript.Extras.JSVar+    , module JavaScript.Extras.Number     , module JavaScript.Extras.Property-    , module JavaScript.Extras.Recast-    , module JavaScript.Extras.String     ) where +import JavaScript.Extras.Cast+import JavaScript.Extras.JSVar import JavaScript.Extras.Number import JavaScript.Extras.Property-import JavaScript.Extras.Recast-import JavaScript.Extras.String
+ src/JavaScript/Extras/Cast.hs view
@@ -0,0 +1,243 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleInstances #-}++module JavaScript.Extras.Cast+    ( ToJS(..)+    , FromJS(..)+    ) where++import qualified Data.JSString as JS+import qualified Data.Text as T+import GHC.Int+import GHC.Word+import qualified GHCJS.Foreign.Callback as J+import qualified GHCJS.Foreign.Export as J+import qualified GHCJS.Foreign.Internal as JFI+import qualified GHCJS.Marshal.Pure as J+import qualified GHCJS.Nullable as J+import qualified GHCJS.Types as J+import qualified JavaScript.Array.Internal as JAI+import qualified JavaScript.Object.Internal as JOI++-- | This provides a consistent way to convert to JSVal, with different semantics for Char.+-- In the Char's instance of ToJS, it converts to a string instead of integer - IMHO this is less surprising.+--+-- The other reason for this class is while GHCJS base provide both IsJSVal and PToJSVal to convert to jsval,+-- some types are instances of one or the other class.+-- This means you can't use the "Maybe a" instance of PToJSVal if it contains IsISJVal but not pToJSVal.+class ToJS a where+    -- | This is a pure conversion, so instances must be able to convert+    -- the same or equivalent JSVal each time.+    toJS :: a -> J.JSVal+    default toJS :: J.IsJSVal a => a -> J.JSVal+    toJS = J.jsval++instance ToJS J.JSVal where+    toJS = id+instance ToJS (J.Callback a)+instance ToJS (J.Export a)+instance ToJS (J.Nullable a) where+    toJS (J.Nullable a) = a+instance ToJS (JAI.SomeJSArray m)+instance ToJS JOI.Object+instance ToJS Bool where+    toJS = J.pToJSVal+-- | Char instance converts to string+instance ToJS Char where+    toJS a = J.pToJSVal [a]+instance ToJS Double where+    toJS = J.pToJSVal+instance ToJS Float where+    toJS = J.pToJSVal+instance ToJS Int where+    toJS = J.pToJSVal+instance ToJS Int8 where+    toJS = J.pToJSVal+instance ToJS Int16 where+    toJS = J.pToJSVal+instance ToJS Int32 where+    toJS = J.pToJSVal+instance ToJS Word where+    toJS = J.pToJSVal+instance ToJS Word8 where+    toJS = J.pToJSVal+instance ToJS Word16 where+    toJS = J.pToJSVal+instance ToJS Word32 where+    toJS = J.pToJSVal+instance ToJS T.Text where+    toJS = J.pToJSVal+instance ToJS String where+    toJS = J.pToJSVal+instance ToJS J.JSString+instance ToJS a => ToJS (Maybe a) where+    toJS Nothing  = J.nullRef+    toJS (Just a) = toJS a++-- | This provides a consistent way to safely convert from JSVal.+-- The semantics is that if the return value is a Just, then the JSVal is not a null value.+-- Also, Nothing is also returned for values out of range. They are not silently truncated.+-- (Except for Float where there may be loss of precision) during conversion.+--+-- The reason for this class is because GHCJS.Marshal.fromJSVal and GHCJS.Marshal.pFromJSVal+-- are not safe to use as it assumes that the JSVal are of the correct type and not null.+-- (https://github.com/ghcjs/ghcjs-base/issues/87).+-- The safe way to convert from JSVal is to use JavaScript.Cast or to use the 'Maybe a' instance of FromJSVal,+-- ie @fromJSVal :: JSVal -> IO (Maybe (Maybe a))@, which is a bit more awkward to use, and requires IO.+-- Also, Javascript.Cast doesn't have much instances, and it hardcodes the instance detection method+-- to javascript `isinstance` which is not sufficient for complex types (https://github.com/ghcjs/ghcjs-base/issues/86).+--+-- It is actually safe to convert from JSVal without IO because every JSVal is a copy of a value or reference.+-- The copy never change, so the conversion will always convert to the same result/object every time.+class FromJS a where+    fromJS :: J.JSVal -> Maybe a++instance FromJS J.JSVal where+    fromJS a | J.isUndefined a || J.isNull a = Nothing+    fromJS a = Just a++instance FromJS (JAI.SomeJSArray m) where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONArray = Just $ JAI.SomeJSArray a+    fromJS _ = Nothing++instance FromJS JOI.Object where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONObject = Just $ JOI.Object a+    fromJS _ = Nothing++instance FromJS Bool where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONBool = J.pFromJSVal a+    fromJS _ = Nothing++-- | This will only succeed on a single character string+instance FromJS Char where+    fromJS a =+        case JFI.jsonTypeOf a of+            JFI.JSONString ->+                let a' = J.pFromJSVal a -- convert to JSString+                    mb = JS.uncons a'+                in case mb of+                       Nothing -> Nothing+                       Just (h, t) ->+                           if JS.null t+                               then Just h+                               else Nothing+            _ -> Nothing++instance FromJS Double where+    fromJS a = let t = JFI.jsonTypeOf a+               in if t == JFI.JSONInteger || t == JFI.JSONFloat+                      then J.pFromJSVal a+                      else Nothing++instance FromJS Float where+    fromJS a = let t = JFI.jsonTypeOf a+               in if t == JFI.JSONInteger || t == JFI.JSONFloat+                      then J.pFromJSVal a+                      else Nothing++instance FromJS Int where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinIntBounds a minBound maxBound = J.pFromJSVal a+    fromJS _ = Nothing++instance FromJS Int8 where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinInt8Bounds a minBound maxBound = J.pFromJSVal a+    fromJS _ = Nothing++instance FromJS Int16 where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinInt16Bounds a minBound maxBound = J.pFromJSVal a+    fromJS _ = Nothing++instance FromJS Int32 where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinInt32Bounds a minBound maxBound = J.pFromJSVal a+    fromJS _ = Nothing++instance FromJS Word where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinWordBounds a minBound maxBound = J.pFromJSVal a+    fromJS _ = Nothing++instance FromJS Word8 where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinWord8Bounds a minBound maxBound = J.pFromJSVal a+    fromJS _ = Nothing++instance FromJS Word16 where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinWord16Bounds a minBound maxBound = J.pFromJSVal a+    fromJS _ = Nothing++instance FromJS Word32 where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinWord32Bounds a minBound maxBound = J.pFromJSVal a+    fromJS _ = Nothing++instance FromJS T.Text where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONString = J.pFromJSVal a+    fromJS _ = Nothing++instance FromJS String where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONString = J.pFromJSVal a+    fromJS _ = Nothing++instance FromJS J.JSString where+    fromJS a | JFI.jsonTypeOf a == JFI.JSONString = J.pFromJSVal a+    fromJS _ = Nothing++#ifdef __GHCJS__++foreign import javascript unsafe+  "($1 >= $2) || ($1 <= $3)"+  js_withinIntBounds :: J.JSVal -> Int -> Int -> Bool++foreign import javascript unsafe+  "($1 >= $2) || ($1 <= $3)"+  js_withinInt8Bounds :: J.JSVal -> Int8 -> Int8 -> Bool++foreign import javascript unsafe+  "($1 >= $2) || ($1 <= $3)"+  js_withinInt16Bounds :: J.JSVal -> Int16 -> Int16 -> Bool++foreign import javascript unsafe+  "($1 >= $2) || ($1 <= $3)"+  js_withinInt32Bounds :: J.JSVal -> Int32 -> Int32 -> Bool++foreign import javascript unsafe+  "($1 >= $2) || ($1 <= $3)"+  js_withinWordBounds :: J.JSVal -> Word -> Word -> Bool++foreign import javascript unsafe+  "($1 >= $2) || ($1 <= $3)"+  js_withinWord8Bounds :: J.JSVal -> Word8 -> Word8 -> Bool++foreign import javascript unsafe+  "($1 >= $2) || ($1 <= $3)"+  js_withinWord16Bounds :: J.JSVal -> Word16 -> Word16 -> Bool++foreign import javascript unsafe+  "($1 >= $2) || ($1 <= $3)"+  js_withinWord32Bounds :: J.JSVal -> Word32 -> Word32 -> Bool++#else++js_withinIntBounds :: J.JSVal -> Int -> Int -> Bool+js_withinIntBounds _ _ _ = False++js_withinInt8Bounds :: J.JSVal -> Int8 -> Int8 -> Bool+js_withinInt8Bounds _ _ _ = False++js_withinInt16Bounds :: J.JSVal -> Int8 -> Int8 -> Bool+js_withinInt16Bounds _ _ _ = False++js_withinInt32Bounds :: J.JSVal -> Int8 -> Int8 -> Bool+js_withinInt32Bounds _ _ _ = False++js_withinWordBounds :: J.JSVal -> Word -> Word -> Bool+js_withinWordBounds _ _ _ = False++js_withinWord8Bounds :: J.JSVal -> Word8 -> Word8 -> Bool+js_withinWord8Bounds _ _ _ = False++js_withinWord16Bounds :: J.JSVal -> Word16 -> Word16 -> Bool+js_withinWord16Bounds _ _ _ = False++js_withinWord32Bounds :: J.JSVal -> Word32 -> Word32 -> Bool+js_withinWord32Bounds _ _ _ = False++#endif
+ src/JavaScript/Extras/JSVar.hs view
@@ -0,0 +1,35 @@+module JavaScript.Extras.JSVar where++import Control.DeepSeq+import Data.Coerce+import Data.JSString as JS+import Data.String+import qualified GHCJS.Marshal.Pure as J+import qualified GHCJS.Types as J+import JavaScript.Extras.Cast as JE++-- | Wrapper to have a JSVal that also have an IString instance+-- This is helpful when using OverloadedStrings+newtype JSVar = JSVar J.JSVal++instance J.IsJSVal JSVar++instance J.PToJSVal JSVar where+    pToJSVal = J.jsval++instance JE.ToJS JSVar++instance JE.FromJS JSVar where+    fromJS v = coerce (fromJS v :: Maybe J.JSVal)++instance IsString JSVar where+    fromString = JSVar . J.jsval . JS.pack++instance NFData JSVar where+    rnf (JSVar v) = rnf v++toJS' :: JE.ToJS a => a -> JSVar+toJS' = JSVar . toJS++fromJS' :: JE.FromJS a => JSVar -> Maybe a+fromJS' (JSVar v) = fromJS v
src/JavaScript/Extras/Property.hs view
@@ -16,16 +16,17 @@ import qualified GHCJS.Types as J import qualified JavaScript.Object as JO import qualified JavaScript.Object.Internal as JOI+import qualified JavaScript.Extras.JSVar as JE import Unsafe.Coerce -type Property = (J.JSString, J.JSVal)+type Property = (J.JSString, JE.JSVar)  -- | get a property of any JSVal. If a null or undefined is queried, the result will also be null-getProperty :: J.JSString -> J.JSVal -> IO J.JSVal+getProperty :: J.JSString -> J.JSVal -> IO JE.JSVar getProperty k x = let k' = J.pToJSVal k                   in if J.isUndefined x || J.isNull x                          || J.isUndefined k' || J.isNull k'-                     then pure J.nullRef+                     then pure $ JE.JSVar J.nullRef                      else js_unsafeGetProperty k x  -- | set a property of any JSVal@@ -45,19 +46,19 @@ toProperties :: JO.Object -> IO [Property] toProperties obj = do    props <- JO.listProps obj-   traverse (\k -> (\v -> (k, v)) <$> JO.unsafeGetProp k obj) props+   traverse (\k -> (\v -> (k, JE.JSVar v)) <$> JO.unsafeGetProp k obj) props  #ifdef __GHCJS__  -- | throws an exception if undefined or null foreign import javascript unsafe   "$2[$1]"-  js_unsafeGetProperty :: J.JSString -> J.JSVal -> IO J.JSVal+  js_unsafeGetProperty :: J.JSString -> J.JSVal -> IO JE.JSVar  -- | throws an exception if undefined or null foreign import javascript unsafe   "$3[$1] = $2;"-  js_unsafeSetProperty :: J.JSString -> J.JSVal -> J.JSVal -> IO ()+  js_unsafeSetProperty :: J.JSString -> JE.JSVar -> J.JSVal -> IO ()  -- | zip list of string and JSVal to object, lists must have been completely forced first -- Using the idea from JavaScript.Array.Internal.fromList h$fromHsListJSVal@@ -67,11 +68,11 @@ #else  -- | throws an exception if undefined or null-js_unsafeGetProperty :: J.JSString -> J.JSVal -> IO J.JSVal-js_unsafeGetProperty _ _ = pure J.nullRef+js_unsafeGetProperty :: J.JSString -> J.JSVal -> IO JE.JSVar+js_unsafeGetProperty _ _ = pure $ JE.JSVar J.nullRef  -- | throws an exception if undefined or null-js_unsafeSetProperty :: J.JSString -> J.JSVal -> J.JSVal -> IO ()+js_unsafeSetProperty :: J.JSString -> JE.JSVar -> J.JSVal -> IO () js_unsafeSetProperty _ _ _ = pure ()  -- | zip list of string and JSVal to object, lists must have been completely forced first
− src/JavaScript/Extras/Recast.hs
@@ -1,244 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DefaultSignatures #-}-{-# LANGUAGE FlexibleInstances #-}--module JavaScript.Extras.Recast-    ( ToJS(..)-    , FromJS(..)-    ) where--import qualified Data.JSString as JS-import qualified Data.Text as T-import GHC.Int-import GHC.Word-import qualified GHCJS.Foreign.Callback as J-import qualified GHCJS.Foreign.Export as J-import qualified GHCJS.Foreign.Internal as JFI-import qualified GHCJS.Marshal as J-import qualified GHCJS.Marshal.Pure as J-import qualified GHCJS.Nullable as J-import qualified GHCJS.Types as J-import qualified JavaScript.Array.Internal as JAI-import qualified JavaScript.Object.Internal as JOI---- | This provides a consistent way to convert to JSVal, with different semantics for Char.--- In the Char's instance of ToJS, it converts to a string instead of integer - IMHO this is less surprising.------ The other reason for this class is while GHCJS base provide both IsJSVal and PToJSVal to convert to jsval,--- some types are instances of one or the other class.--- This means you can't use the "Maybe a" instance of PToJSVal if it contains IsISJVal but not pToJSVal.-class ToJS a where-    -- | This is a pure conversion, so instances must be able to convert-    -- the same or equivalent JSVal each time.-    toJS :: a -> J.JSVal-    default toJS :: J.IsJSVal a => a -> J.JSVal-    toJS = J.jsval--instance ToJS J.JSVal where-    toJS = id-instance ToJS (J.Callback a)-instance ToJS (J.Export a)-instance ToJS (J.Nullable a) where-    toJS (J.Nullable a) = a-instance ToJS (JAI.SomeJSArray m)-instance ToJS JOI.Object-instance ToJS Bool where-    toJS = J.pToJSVal--- | Char instance converts to string-instance ToJS Char where-    toJS a = J.pToJSVal [a]-instance ToJS Double where-    toJS = J.pToJSVal-instance ToJS Float where-    toJS = J.pToJSVal-instance ToJS Int where-    toJS = J.pToJSVal-instance ToJS Int8 where-    toJS = J.pToJSVal-instance ToJS Int16 where-    toJS = J.pToJSVal-instance ToJS Int32 where-    toJS = J.pToJSVal-instance ToJS Word where-    toJS = J.pToJSVal-instance ToJS Word8 where-    toJS = J.pToJSVal-instance ToJS Word16 where-    toJS = J.pToJSVal-instance ToJS Word32 where-    toJS = J.pToJSVal-instance ToJS T.Text where-    toJS = J.pToJSVal-instance ToJS [Char] where-    toJS = J.pToJSVal-instance ToJS J.JSString-instance ToJS a => ToJS (Maybe a) where-    toJS Nothing  = J.nullRef-    toJS (Just a) = toJS a---- | This provides a consistent way to safely convert from JSVal.--- The semantics is that if the return value is a Just, then the JSVal is not a null value.--- Also, Nothing is also returned for values out of range. They are not silently truncated.--- (Except for Float where there may be loss of precision) during conversion.------ The reason for this class is because GHCJS.Marshal.fromJSVal and GHCJS.Marshal.pFromJSVal--- are not safe to use as it assumes that the JSVal are of the correct type and not null.--- (https://github.com/ghcjs/ghcjs-base/issues/87).--- The safe way to convert from JSVal is to use JavaScript.Cast or to use the 'Maybe a' instance of FromJSVal,--- ie @fromJSVal :: JSVal -> IO (Maybe (Maybe a))@, which is a bit more awkward to use.--- Also, Javascript.Cast doesn't have much instances, and it hardcodes the instance detection method--- to javascript `isinstance` which is not sufficient for complex--- types (https://github.com/ghcjs/ghcjs-base/issues/86).-class FromJS a where-    -- | This is an IO because since JSVal is mutable, this function may different results-    -- for the same JSVal at later points in time.-    fromJS :: J.JSVal -> IO (Maybe a)--instance FromJS J.JSVal where-    fromJS a | J.isUndefined a || J.isNull a = pure Nothing-    fromJS a = pure $ Just a--instance FromJS (JAI.SomeJSArray m) where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONArray = pure . Just $ JAI.SomeJSArray a-    fromJS _ = pure Nothing--instance FromJS JOI.Object where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONObject = pure . Just $ JOI.Object a-    fromJS _ = pure Nothing--instance FromJS Bool where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONBool = J.fromJSVal a-    fromJS _ = pure Nothing---- | This will only succeed on a single character string-instance FromJS Char where-    fromJS a =-        case JFI.jsonTypeOf a of-            JFI.JSONString ->-                let a' = J.pFromJSVal a -- convert to JSString-                    mb = JS.uncons a'-                in case mb of-                       Nothing -> pure Nothing-                       Just (h, t) ->-                           if JS.null t-                               then pure $ Just h-                               else pure Nothing-            _ -> pure Nothing--instance FromJS Double where-    fromJS a = let t = JFI.jsonTypeOf a-               in if t == JFI.JSONInteger || t == JFI.JSONFloat-                      then J.fromJSVal a-                      else pure Nothing--instance FromJS Float where-    fromJS a = let t = JFI.jsonTypeOf a-               in if t == JFI.JSONInteger || t == JFI.JSONFloat-                      then J.fromJSVal a-                      else pure Nothing--instance FromJS Int where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinIntBounds a minBound maxBound = J.fromJSVal a-    fromJS _ = pure Nothing--instance FromJS Int8 where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinInt8Bounds a minBound maxBound = J.fromJSVal a-    fromJS _ = pure Nothing--instance FromJS Int16 where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinInt16Bounds a minBound maxBound = J.fromJSVal a-    fromJS _ = pure Nothing--instance FromJS Int32 where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinInt32Bounds a minBound maxBound = J.fromJSVal a-    fromJS _ = pure Nothing--instance FromJS Word where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinWordBounds a minBound maxBound = J.fromJSVal a-    fromJS _ = pure Nothing--instance FromJS Word8 where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinWord8Bounds a minBound maxBound = J.fromJSVal a-    fromJS _ = pure Nothing--instance FromJS Word16 where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinWord16Bounds a minBound maxBound = J.fromJSVal a-    fromJS _ = pure Nothing--instance FromJS Word32 where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONInteger && js_withinWord32Bounds a minBound maxBound = J.fromJSVal a-    fromJS _ = pure Nothing--instance FromJS T.Text where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONString = J.fromJSVal a-    fromJS _ = pure Nothing--instance FromJS [Char] where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONString = J.fromJSVal a-    fromJS _ = pure Nothing--instance FromJS J.JSString where-    fromJS a | JFI.jsonTypeOf a == JFI.JSONString = J.fromJSVal a-    fromJS _ = pure Nothing--#ifdef __GHCJS__--foreign import javascript unsafe-  "($1 >= $2) || ($1 <= $3)"-  js_withinIntBounds :: J.JSVal -> Int -> Int -> Bool--foreign import javascript unsafe-  "($1 >= $2) || ($1 <= $3)"-  js_withinInt8Bounds :: J.JSVal -> Int8 -> Int8 -> Bool--foreign import javascript unsafe-  "($1 >= $2) || ($1 <= $3)"-  js_withinInt16Bounds :: J.JSVal -> Int16 -> Int16 -> Bool--foreign import javascript unsafe-  "($1 >= $2) || ($1 <= $3)"-  js_withinInt32Bounds :: J.JSVal -> Int32 -> Int32 -> Bool--foreign import javascript unsafe-  "($1 >= $2) || ($1 <= $3)"-  js_withinWordBounds :: J.JSVal -> Word -> Word -> Bool--foreign import javascript unsafe-  "($1 >= $2) || ($1 <= $3)"-  js_withinWord8Bounds :: J.JSVal -> Word8 -> Word8 -> Bool--foreign import javascript unsafe-  "($1 >= $2) || ($1 <= $3)"-  js_withinWord16Bounds :: J.JSVal -> Word16 -> Word16 -> Bool--foreign import javascript unsafe-  "($1 >= $2) || ($1 <= $3)"-  js_withinWord32Bounds :: J.JSVal -> Word32 -> Word32 -> Bool--#else--js_withinIntBounds :: J.JSVal -> Int -> Int -> Bool-js_withinIntBounds _ _ _ = False--js_withinInt8Bounds :: J.JSVal -> Int8 -> Int8 -> Bool-js_withinInt8Bounds _ _ _ = False--js_withinInt16Bounds :: J.JSVal -> Int8 -> Int8 -> Bool-js_withinInt16Bounds _ _ _ = False--js_withinInt32Bounds :: J.JSVal -> Int8 -> Int8 -> Bool-js_withinInt32Bounds _ _ _ = False--js_withinWordBounds :: J.JSVal -> Word -> Word -> Bool-js_withinWordBounds _ _ _ = False--js_withinWord8Bounds :: J.JSVal -> Word8 -> Word8 -> Bool-js_withinWord8Bounds _ _ _ = False--js_withinWord16Bounds :: J.JSVal -> Word16 -> Word16 -> Bool-js_withinWord16Bounds _ _ _ = False--js_withinWord32Bounds :: J.JSVal -> Word32 -> Word32 -> Bool-js_withinWord32Bounds _ _ _ = False--#endif
− src/JavaScript/Extras/String.hs
@@ -1,20 +0,0 @@-module JavaScript.Extras.String where--import JavaScript.Extras.Recast as JE-import Data.Text as T-import qualified GHCJS.Types as J---- | This makes it easier to use OverloadedStrings with inputs that accept a JSVal that could be a JSString--- Less verbose version of'toJS @JSString'-strJS :: J.JSString -> J.JSVal-strJS = JE.toJS---- | This makes it easier to use OverloadedStrings with inputs that accept a JSVal that could be a Data.Text--- Less verbose version of'toJS @Text'-txtJS :: T.Text -> J.JSVal-txtJS = JE.toJS---- | This makes it easier to use OverloadedStrings with inputs that accept a JSVal that could be a [String]--- Less verbose version of'toJS @Jtring'-strJS' :: [Char] -> J.JSVal-strJS' = JE.toJS