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

Commit 8e6d69c

Browse files
authored
Merge pull request #18 from nsaunders/safe
Add safe versions of various functions from Global.Unsafe.
2 parents 3c6251d + c4da4ba commit 8e6d69c

File tree

5 files changed

+167
-2
lines changed

5 files changed

+167
-2
lines changed

bower.json

+4
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,9 @@
1919
"devDependencies": {
2020
"purescript-assert": "^4.0.0",
2121
"purescript-console": "^4.0.0"
22+
},
23+
"dependencies": {
24+
"purescript-maybe": "^4.0.1",
25+
"purescript-functions": "^4.0.0"
2226
}
2327
}

src/Global.js

+31
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,34 @@ exports.readInt = function (radix) {
1616
};
1717

1818
exports.readFloat = parseFloat;
19+
20+
var formatNumber = function (format) {
21+
return function (fail, succ, digits, n) {
22+
try {
23+
return succ(n[format](digits));
24+
}
25+
catch (e) {
26+
return fail(e.message);
27+
}
28+
};
29+
};
30+
31+
exports._toFixed = formatNumber("toFixed");
32+
exports._toExponential = formatNumber("toExponential");
33+
exports._toPrecision = formatNumber("toPrecision");
34+
35+
var encdecURI = function (encdec) {
36+
return function (fail, succ, s) {
37+
try {
38+
return succ(encdec(s));
39+
}
40+
catch (e) {
41+
return fail(e.message);
42+
}
43+
};
44+
};
45+
46+
exports._decodeURI = encdecURI(decodeURI);
47+
exports._encodeURI = encdecURI(encodeURI);
48+
exports._decodeURIComponent = encdecURI(decodeURIComponent);
49+
exports._encodeURIComponent = encdecURI(encodeURIComponent);

src/Global.purs

+73-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,24 @@
11
-- | This module defines types for some global Javascript functions
22
-- | and values.
3-
module Global where
3+
module Global
4+
( nan
5+
, isNaN
6+
, infinity
7+
, isFinite
8+
, readInt
9+
, readFloat
10+
, toFixed
11+
, toExponential
12+
, toPrecision
13+
, decodeURI
14+
, encodeURI
15+
, decodeURIComponent
16+
, encodeURIComponent
17+
) where
18+
19+
import Prelude
20+
import Data.Function.Uncurried (Fn3, Fn4, runFn3, runFn4)
21+
import Data.Maybe (Maybe(..))
422

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

2038
-- | Parse a floating point value from a `String`
2139
foreign import readFloat :: String -> Number
40+
41+
foreign import _toFixed :: forall a. Fn4 (String -> a) (String -> a) Int Number a
42+
43+
foreign import _toExponential :: forall a. Fn4 (String -> a) (String -> a) Int Number a
44+
45+
foreign import _toPrecision :: forall a. Fn4 (String -> a) (String -> a) Int Number a
46+
47+
-- | Formats Number as a String with limited number of digits after the dot.
48+
-- | May return `Nothing` when specified number of digits is less than 0 or
49+
-- | greater than 20. See ECMA-262 for more information.
50+
toFixed :: Int -> Number -> Maybe String
51+
toFixed digits n = runFn4 _toFixed (const Nothing) Just digits n
52+
53+
-- | Formats Number as String in exponential notation limiting number of digits
54+
-- | after the decimal dot. May return `Nothing` when specified number of
55+
-- | digits is less than 0 or greater than 20 depending on the implementation.
56+
-- | See ECMA-262 for more information.
57+
toExponential :: Int -> Number -> Maybe String
58+
toExponential digits n = runFn4 _toExponential (const Nothing) Just digits n
59+
60+
-- | Formats Number as String in fixed-point or exponential notation rounded
61+
-- | to specified number of significant digits. May return `Nothing` when
62+
-- | precision is less than 1 or greater than 21 depending on the
63+
-- | implementation. See ECMA-262 for more information.
64+
toPrecision :: Int -> Number -> Maybe String
65+
toPrecision digits n = runFn4 _toPrecision (const Nothing) Just digits n
66+
67+
foreign import _decodeURI :: forall a. Fn3 (String -> a) (String -> a) String a
68+
69+
foreign import _encodeURI :: forall a. Fn3 (String -> a) (String -> a) String a
70+
71+
foreign import _decodeURIComponent :: forall a. Fn3 (String -> a) (String -> a) String a
72+
73+
foreign import _encodeURIComponent :: forall a. Fn3 (String -> a) (String -> a) String a
74+
75+
-- | URI decoding. Returns `Nothing` when given a value with undecodeable
76+
-- | escape sequences.
77+
decodeURI :: String -> Maybe String
78+
decodeURI s = runFn3 _decodeURI (const Nothing) Just s
79+
80+
-- | URI encoding. Returns `Nothing` when given a value with unencodeable
81+
-- | characters.
82+
encodeURI :: String -> Maybe String
83+
encodeURI s = runFn3 _encodeURI (const Nothing) Just s
84+
85+
-- | URI component decoding. Returns `Nothing` when given a value with
86+
-- | undecodeable escape sequences.
87+
decodeURIComponent :: String -> Maybe String
88+
decodeURIComponent s = runFn3 _decodeURIComponent (const Nothing) Just s
89+
90+
-- | URI component encoding. Returns `Nothing` when given a value with
91+
-- | unencodeable characters.
92+
encodeURIComponent :: String -> Maybe String
93+
encodeURIComponent s = runFn3 _encodeURIComponent (const Nothing) Just s

test/Test/Main.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
exports.unencodable = "\uDFFF";

test/Test/Main.purs

+58-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,25 @@ module Test.Main where
22

33
import Prelude
44

5+
import Data.Maybe (Maybe(..))
56
import Effect (Effect)
67
import Effect.Console (log)
78

8-
import Global (readFloat, readInt, isFinite, infinity, nan, isNaN)
9+
import Global
10+
( readFloat
11+
, readInt
12+
, isFinite
13+
, infinity
14+
, nan
15+
, isNaN
16+
, toPrecision
17+
, toExponential
18+
, toFixed
19+
, decodeURI
20+
, encodeURI
21+
, decodeURIComponent
22+
, encodeURIComponent
23+
)
924
import Global.Unsafe (unsafeToPrecision, unsafeToExponential, unsafeToFixed)
1025

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

79+
-- note the rounding
80+
log $ "toFixed 1" <> (show num) <> " == (Just \"12345.7\")"
81+
assert $ toFixed 1 num == Just "12345.7"
82+
83+
-- padded with zeros
84+
log $ "toFixed 6" <> (show num) <> " == (Just \"12345.678900\")"
85+
assert $ toFixed 6 num == Just "12345.678900"
86+
87+
log $ "toExponential 4" <> (show num) <> " == (Just \"1.2346e+4\")"
88+
assert $ toExponential 4 num == Just "1.2346e+4"
89+
90+
log $ "toPrecision 3" <> (show num) <> " == (Just \"1.23e+4\")"
91+
assert $ toPrecision 3 num == Just "1.23e+4"
92+
93+
log $ "toPrecision 6" <> (show num) <> " == (Just \"12345.7\")"
94+
assert $ toPrecision 6 num == Just "12345.7"
95+
96+
log $ "decodeURI \"http://test/api?q=hello%20world\" == Just \"http://test/api?q=hello world\""
97+
assert $ decodeURI "http://test/api?q=hello%20world" == Just "http://test/api?q=hello world"
98+
99+
log $ "decodeURI \"http://test/api?q=hello%8\" == Nothing\""
100+
assert $ decodeURI "http://test/api?q=hello%8" == Nothing
101+
102+
log $ "encodeURI \"http://test/api?q=hello world\" == Just \"http://test/api?q=hello%20world\""
103+
assert $ encodeURI "http://test/api?q=hello world" == Just "http://test/api?q=hello%20world"
104+
105+
log $ "encodeURI \"http://test/api?q=" <> unencodable <> "\" == Nothing"
106+
assert $ encodeURI ("http://test/api?q=" <> unencodable) == Nothing
107+
108+
log $ "decodeURIComponent \"hello%20world\" == Just \"hello world\""
109+
assert $ decodeURIComponent "hello%20world" == Just "hello world"
110+
111+
log $ "decodeURIComponent \"hello%8\" == Nothing"
112+
assert $ decodeURIComponent "hello%8" == Nothing
113+
114+
log $ "encodeURIComponent \"hello world\" == Just \"hello%20world\""
115+
assert $ encodeURIComponent "hello world" == Just "hello%20world"
116+
117+
log $ "encodeURIComponent \"" <> unencodable <> "\" == Nothing"
118+
assert $ encodeURIComponent unencodable == Nothing
119+
120+
foreign import unencodable :: String

0 commit comments

Comments
 (0)