Skip to content
This repository has been archived by the owner on Dec 18, 2020. It is now read-only.

Commit

Permalink
Merge pull request #18 from nsaunders/safe
Browse files Browse the repository at this point in the history
Add safe versions of various functions from Global.Unsafe.
  • Loading branch information
garyb committed Aug 11, 2019
2 parents 3c6251d + c4da4ba commit 8e6d69c
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 2 deletions.
4 changes: 4 additions & 0 deletions bower.json
Expand Up @@ -19,5 +19,9 @@
"devDependencies": {
"purescript-assert": "^4.0.0",
"purescript-console": "^4.0.0"
},
"dependencies": {
"purescript-maybe": "^4.0.1",
"purescript-functions": "^4.0.0"
}
}
31 changes: 31 additions & 0 deletions src/Global.js
Expand Up @@ -16,3 +16,34 @@ exports.readInt = function (radix) {
};

exports.readFloat = parseFloat;

var formatNumber = function (format) {
return function (fail, succ, digits, n) {
try {
return succ(n[format](digits));
}
catch (e) {
return fail(e.message);
}
};
};

exports._toFixed = formatNumber("toFixed");
exports._toExponential = formatNumber("toExponential");
exports._toPrecision = formatNumber("toPrecision");

var encdecURI = function (encdec) {
return function (fail, succ, s) {
try {
return succ(encdec(s));
}
catch (e) {
return fail(e.message);
}
};
};

exports._decodeURI = encdecURI(decodeURI);
exports._encodeURI = encdecURI(encodeURI);
exports._decodeURIComponent = encdecURI(decodeURIComponent);
exports._encodeURIComponent = encdecURI(encodeURIComponent);
74 changes: 73 additions & 1 deletion src/Global.purs
@@ -1,6 +1,24 @@
-- | This module defines types for some global Javascript functions
-- | and values.
module Global where
module Global
( nan
, isNaN
, infinity
, isFinite
, readInt
, readFloat
, toFixed
, toExponential
, toPrecision
, decodeURI
, encodeURI
, decodeURIComponent
, encodeURIComponent
) where

import Prelude
import Data.Function.Uncurried (Fn3, Fn4, runFn3, runFn4)
import Data.Maybe (Maybe(..))

-- | Not a number (NaN)
foreign import nan :: Number
Expand All @@ -19,3 +37,57 @@ foreign import readInt :: Int -> String -> Number

-- | Parse a floating point value from a `String`
foreign import readFloat :: String -> Number

foreign import _toFixed :: forall a. Fn4 (String -> a) (String -> a) Int Number a

foreign import _toExponential :: forall a. Fn4 (String -> a) (String -> a) Int Number a

foreign import _toPrecision :: forall a. Fn4 (String -> a) (String -> a) Int Number a

-- | Formats Number as a String with limited number of digits after the dot.
-- | May return `Nothing` when specified number of digits is less than 0 or
-- | greater than 20. See ECMA-262 for more information.
toFixed :: Int -> Number -> Maybe String
toFixed digits n = runFn4 _toFixed (const Nothing) Just digits n

-- | Formats Number as String in exponential notation limiting number of digits
-- | after the decimal dot. May return `Nothing` when specified number of
-- | digits is less than 0 or greater than 20 depending on the implementation.
-- | See ECMA-262 for more information.
toExponential :: Int -> Number -> Maybe String
toExponential digits n = runFn4 _toExponential (const Nothing) Just digits n

-- | Formats Number as String in fixed-point or exponential notation rounded
-- | to specified number of significant digits. May return `Nothing` when
-- | precision is less than 1 or greater than 21 depending on the
-- | implementation. See ECMA-262 for more information.
toPrecision :: Int -> Number -> Maybe String
toPrecision digits n = runFn4 _toPrecision (const Nothing) Just digits n

foreign import _decodeURI :: forall a. Fn3 (String -> a) (String -> a) String a

foreign import _encodeURI :: forall a. Fn3 (String -> a) (String -> a) String a

foreign import _decodeURIComponent :: forall a. Fn3 (String -> a) (String -> a) String a

foreign import _encodeURIComponent :: forall a. Fn3 (String -> a) (String -> a) String a

-- | URI decoding. Returns `Nothing` when given a value with undecodeable
-- | escape sequences.
decodeURI :: String -> Maybe String
decodeURI s = runFn3 _decodeURI (const Nothing) Just s

-- | URI encoding. Returns `Nothing` when given a value with unencodeable
-- | characters.
encodeURI :: String -> Maybe String
encodeURI s = runFn3 _encodeURI (const Nothing) Just s

-- | URI component decoding. Returns `Nothing` when given a value with
-- | undecodeable escape sequences.
decodeURIComponent :: String -> Maybe String
decodeURIComponent s = runFn3 _decodeURIComponent (const Nothing) Just s

-- | URI component encoding. Returns `Nothing` when given a value with
-- | unencodeable characters.
encodeURIComponent :: String -> Maybe String
encodeURIComponent s = runFn3 _encodeURIComponent (const Nothing) Just s
1 change: 1 addition & 0 deletions test/Test/Main.js
@@ -0,0 +1 @@
exports.unencodable = "\uDFFF";
59 changes: 58 additions & 1 deletion test/Test/Main.purs
Expand Up @@ -2,10 +2,25 @@ module Test.Main where

import Prelude

import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Console (log)

import Global (readFloat, readInt, isFinite, infinity, nan, isNaN)
import Global
( readFloat
, readInt
, isFinite
, infinity
, nan
, isNaN
, toPrecision
, toExponential
, toFixed
, decodeURI
, encodeURI
, decodeURIComponent
, encodeURIComponent
)
import Global.Unsafe (unsafeToPrecision, unsafeToExponential, unsafeToFixed)

import Test.Assert (assert)
Expand Down Expand Up @@ -61,3 +76,45 @@ main = do
log $ "unsafeToPrecision 6" <> (show num) <> " == \"12345.7\""
assert $ unsafeToPrecision 6 num == "12345.7"

-- note the rounding
log $ "toFixed 1" <> (show num) <> " == (Just \"12345.7\")"
assert $ toFixed 1 num == Just "12345.7"

-- padded with zeros
log $ "toFixed 6" <> (show num) <> " == (Just \"12345.678900\")"
assert $ toFixed 6 num == Just "12345.678900"

log $ "toExponential 4" <> (show num) <> " == (Just \"1.2346e+4\")"
assert $ toExponential 4 num == Just "1.2346e+4"

log $ "toPrecision 3" <> (show num) <> " == (Just \"1.23e+4\")"
assert $ toPrecision 3 num == Just "1.23e+4"

log $ "toPrecision 6" <> (show num) <> " == (Just \"12345.7\")"
assert $ toPrecision 6 num == Just "12345.7"

log $ "decodeURI \"http://test/api?q=hello%20world\" == Just \"http://test/api?q=hello world\""
assert $ decodeURI "http://test/api?q=hello%20world" == Just "http://test/api?q=hello world"

log $ "decodeURI \"http://test/api?q=hello%8\" == Nothing\""
assert $ decodeURI "http://test/api?q=hello%8" == Nothing

log $ "encodeURI \"http://test/api?q=hello world\" == Just \"http://test/api?q=hello%20world\""
assert $ encodeURI "http://test/api?q=hello world" == Just "http://test/api?q=hello%20world"

log $ "encodeURI \"http://test/api?q=" <> unencodable <> "\" == Nothing"
assert $ encodeURI ("http://test/api?q=" <> unencodable) == Nothing

log $ "decodeURIComponent \"hello%20world\" == Just \"hello world\""
assert $ decodeURIComponent "hello%20world" == Just "hello world"

log $ "decodeURIComponent \"hello%8\" == Nothing"
assert $ decodeURIComponent "hello%8" == Nothing

log $ "encodeURIComponent \"hello world\" == Just \"hello%20world\""
assert $ encodeURIComponent "hello world" == Just "hello%20world"

log $ "encodeURIComponent \"" <> unencodable <> "\" == Nothing"
assert $ encodeURIComponent unencodable == Nothing

foreign import unencodable :: String

0 comments on commit 8e6d69c

Please sign in to comment.