From a0c63937edf94a0e30f001bbc557632af8cd7858 Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 18 Feb 2021 23:30:50 +0800 Subject: [PATCH 01/10] fix js unsigned integer --- lib/system/dollars.nim | 47 ++++++++++++++++++++++++--------------- tests/system/tdollars.nim | 25 +++++++++++++++++++++ 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/lib/system/dollars.nim b/lib/system/dollars.nim index 4c72c2901da4..238c5983705c 100644 --- a/lib/system/dollars.nim +++ b/lib/system/dollars.nim @@ -3,6 +3,26 @@ proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.} ## converted to a decimal string. ``$`` is Nim's general way of ## spelling `toString`:idx:. +template dollarImpl(x: uint | uint64, result: var string) = + type destTyp = typeof(x) + if x == 0: + result = "0" + else: + result = newString(60) + var i = 0 + var n = x + while n != 0: + let nn = n div destTyp(10) + result[i] = char(n - destTyp(10) * nn + ord('0')) + inc i + n = nn + result.setLen i + + let half = i div 2 + # Reverse + for t in 0 .. half-1: swap(result[t], result[i-t-1]) + + when defined(js): import std/private/since since (1, 3): @@ -10,34 +30,25 @@ when defined(js): ## Caveat: currently implemented as $(cast[int](x)), tied to current ## semantics of js' Number type. # for c, see strmantle.`$` - $(cast[int](x)) + when nimvm: + dollarImpl(x, result) + else: + result = $(int(x)) proc `$`*(x: uint64): string = ## Compatibility note: ## the results may change in future releases if/when js target implements ## 64bit ints. # pending https://github.com/nim-lang/RFCs/issues/187 - $(cast[int](x)) + when nimvm: + dollarImpl(x, result) + else: + result = $(cast[int](x)) else: proc `$`*(x: uint64): string {.noSideEffect, raises: [].} = ## The stringify operator for an unsigned integer argument. Returns `x` ## converted to a decimal string. - if x == 0: - result = "0" - else: - result = newString(60) - var i = 0 - var n = x - while n != 0: - let nn = n div 10'u64 - result[i] = char(n - 10'u64 * nn + ord('0')) - inc i - n = nn - result.setLen i - - let half = i div 2 - # Reverse - for t in 0 .. half-1: swap(result[t], result[i-t-1]) + dollarImpl(x, result) proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.} ## The stringify operator for an integer argument. Returns `x` diff --git a/tests/system/tdollars.nim b/tests/system/tdollars.nim index 62f77c8578b4..1db6252b9645 100644 --- a/tests/system/tdollars.nim +++ b/tests/system/tdollars.nim @@ -101,6 +101,31 @@ block: # #14350, #16674, #16686 for JS doAssert nil1 == cstring("") doAssert nil2 == cstring("") +block: + block: + let x = -1'i8 + let y = uint32(x) + + doAssert $y == "4294967295" + + block: + let x = -1'i16 + let y = uint32(x) + + doAssert $y == "4294967295" + + block: + let x = -1'i32 + let y = uint32(x) + + doAssert $y == "4294967295" + + block: + let x = 4294967295'u32 + doAssert $x == "4294967295" + + block: + doAssert $(4294967295'u32) == "4294967295" proc main()= block: From 9a40fbffb134c0ed7971529759598bb38bb4e027 Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 18 Feb 2021 23:33:29 +0800 Subject: [PATCH 02/10] better --- tests/system/tdollars.nim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/system/tdollars.nim b/tests/system/tdollars.nim index 1db6252b9645..04595c93c583 100644 --- a/tests/system/tdollars.nim +++ b/tests/system/tdollars.nim @@ -149,5 +149,8 @@ proc main()= doAssert $(0) == "0" + doAssert $uint32.high == "4294967295" + + static: main() main() From 5f5c86282b702948f57d7f42d6d227168a121a5c Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 19 Feb 2021 21:42:07 +0800 Subject: [PATCH 03/10] Use `std` prefix for standard library modules --- doc/nep1.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/nep1.rst b/doc/nep1.rst index 3c7c6979421e..952856683cce 100644 --- a/doc/nep1.rst +++ b/doc/nep1.rst @@ -167,7 +167,7 @@ new newFoo initializes a reference type ``Foo`` via ``new`` this or self self for method like procs, e.g.: `proc fun(self: Foo, a: int)` - rationale: `self` is more unique in english + rationale: `self` is more unique in English than `this`, and `foo` would not be DRY. find find should return the position where something was found; for a bool result @@ -287,6 +287,9 @@ Miscellaneous - Use `a..b` instead of `a .. b`, except when `b` contains an operator, for example `a .. -3`. Likewise with `a.. Date: Sat, 20 Feb 2021 16:28:52 +0800 Subject: [PATCH 04/10] update cookies module --- lib/pure/cookies.nim | 35 ++++++++++++++++++++++------------- tests/stdlib/tcookies.nim | 9 +++++++-- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index 7e686d44fafb..6dc897086017 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -9,18 +9,23 @@ ## This module implements helper procs for parsing Cookies. -import strtabs, times +import std/[strtabs, times, options] + + +type + SameSite* {.pure.} = enum ## The SameSite cookie attribute. + None, Lax, Strict proc parseCookies*(s: string): StringTableRef = - ## parses cookies into a string table. + ## Parses cookies into a string table. ## ## The proc is meant to parse the Cookie header set by a client, not the ## "Set-Cookie" header set by servers. - ## - ## Example: - ## - ## .. code-block::Nim - ## doAssert parseCookies("a=1; foo=bar") == {"a": 1, "foo": "bar"}.newStringTable + runnableExamples: + import std/strtabs + let cookieJar = parseCookies("a=1; foo=bar") + assert cookieJar["a"] == "1" + assert cookieJar["foo"] == "bar" result = newStringTable(modeCaseInsensitive) var i = 0 @@ -39,9 +44,10 @@ proc parseCookies*(s: string): StringTableRef = proc setCookie*(key, value: string, domain = "", path = "", expires = "", noName = false, - secure = false, httpOnly = false): string = + secure = false, httpOnly = false, + maxAge = none(int), sameSite = SameSite.Lax): string = ## Creates a command in the format of - ## ``Set-Cookie: key=value; Domain=...; ...`` + ## `Set-Cookie: key=value; Domain=...; ...` result = "" if not noName: result.add("Set-Cookie: ") result.add key & "=" & value @@ -50,12 +56,15 @@ proc setCookie*(key, value: string, domain = "", path = "", if expires != "": result.add("; Expires=" & expires) if secure: result.add("; Secure") if httpOnly: result.add("; HttpOnly") + if maxAge.isSome: result.add("; Max-Age=" & $maxAge.get) + if sameSite != SameSite.None: result.add("; SameSite=" & $sameSite) proc setCookie*(key, value: string, expires: DateTime|Time, domain = "", path = "", noName = false, - secure = false, httpOnly = false): string = + secure = false, httpOnly = false, + maxAge = none(int), sameSite = SameSite.Lax): string = ## Creates a command in the format of - ## ``Set-Cookie: key=value; Domain=...; ...`` - return setCookie(key, value, domain, path, + ## `Set-Cookie: key=value; Domain=...; ...` + result = setCookie(key, value, domain, path, format(expires.utc, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'"), - noname, secure, httpOnly) + noname, secure, httpOnly, maxAge, sameSite) diff --git a/tests/stdlib/tcookies.nim b/tests/stdlib/tcookies.nim index 95b431b19aec..0f8dadd568ee 100644 --- a/tests/stdlib/tcookies.nim +++ b/tests/stdlib/tcookies.nim @@ -1,4 +1,9 @@ -import cookies, times, strtabs +discard """ + targets: "c js" +""" + + +import std/[cookies, times, strtabs] let expire = fromUnix(0) + 1.seconds @@ -7,7 +12,7 @@ let theCookies = [ setCookie("test", "value", expire.local), setCookie("test", "value", expire.utc) ] -let expected = "Set-Cookie: test=value; Expires=Thu, 01 Jan 1970 00:00:01 GMT" +let expected = "Set-Cookie: test=value; Expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=Lax" doAssert theCookies == [expected, expected, expected] let table = parseCookies("uid=1; kp=2") From f405a42e0c019c00a311db62d3dd61b3d194b548 Mon Sep 17 00:00:00 2001 From: flywind Date: Sat, 20 Feb 2021 16:43:54 +0800 Subject: [PATCH 05/10] use unsafeGet --- lib/pure/cookies.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index 6dc897086017..92243251c352 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -56,7 +56,7 @@ proc setCookie*(key, value: string, domain = "", path = "", if expires != "": result.add("; Expires=" & expires) if secure: result.add("; Secure") if httpOnly: result.add("; HttpOnly") - if maxAge.isSome: result.add("; Max-Age=" & $maxAge.get) + if maxAge.isSome: result.add("; Max-Age=" & $maxAge.unsafeGet) if sameSite != SameSite.None: result.add("; SameSite=" & $sameSite) proc setCookie*(key, value: string, expires: DateTime|Time, From 6a94301660c4c1e3e4b449d4fdd676549e08349b Mon Sep 17 00:00:00 2001 From: flywind Date: Sat, 20 Feb 2021 17:42:09 +0800 Subject: [PATCH 06/10] introduce sameSite.Default --- lib/pure/cookies.nim | 10 +++++++--- tests/stdlib/tcookies.nim | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index 92243251c352..97dc88e88856 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -14,7 +14,7 @@ import std/[strtabs, times, options] type SameSite* {.pure.} = enum ## The SameSite cookie attribute. - None, Lax, Strict + Default, None, Lax, Strict proc parseCookies*(s: string): StringTableRef = ## Parses cookies into a string table. @@ -45,7 +45,7 @@ proc parseCookies*(s: string): StringTableRef = proc setCookie*(key, value: string, domain = "", path = "", expires = "", noName = false, secure = false, httpOnly = false, - maxAge = none(int), sameSite = SameSite.Lax): string = + maxAge = none(int), sameSite = SameSite.Default): string = ## Creates a command in the format of ## `Set-Cookie: key=value; Domain=...; ...` result = "" @@ -57,7 +57,11 @@ proc setCookie*(key, value: string, domain = "", path = "", if secure: result.add("; Secure") if httpOnly: result.add("; HttpOnly") if maxAge.isSome: result.add("; Max-Age=" & $maxAge.unsafeGet) - if sameSite != SameSite.None: result.add("; SameSite=" & $sameSite) + + if sameSite != SameSite.Default: + if sameSite == SameSite.None: + doAssert httpOnly, "Cookies with SameSite=None must must specify the Secure attribute!" + result.add("; SameSite=" & $sameSite) proc setCookie*(key, value: string, expires: DateTime|Time, domain = "", path = "", noName = false, diff --git a/tests/stdlib/tcookies.nim b/tests/stdlib/tcookies.nim index 0f8dadd568ee..0a36cbebcd74 100644 --- a/tests/stdlib/tcookies.nim +++ b/tests/stdlib/tcookies.nim @@ -12,7 +12,7 @@ let theCookies = [ setCookie("test", "value", expire.local), setCookie("test", "value", expire.utc) ] -let expected = "Set-Cookie: test=value; Expires=Thu, 01 Jan 1970 00:00:01 GMT; SameSite=Lax" +let expected = "Set-Cookie: test=value; Expires=Thu, 01 Jan 1970 00:00:01 GMT" doAssert theCookies == [expected, expected, expected] let table = parseCookies("uid=1; kp=2") From 6275281cb6e920569cdf33f75610e8d3ab8fec86 Mon Sep 17 00:00:00 2001 From: flywind Date: Sat, 20 Feb 2021 17:43:39 +0800 Subject: [PATCH 07/10] better --- lib/pure/cookies.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index 97dc88e88856..806ed673253e 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -66,7 +66,7 @@ proc setCookie*(key, value: string, domain = "", path = "", proc setCookie*(key, value: string, expires: DateTime|Time, domain = "", path = "", noName = false, secure = false, httpOnly = false, - maxAge = none(int), sameSite = SameSite.Lax): string = + maxAge = none(int), sameSite = SameSite.Default): string = ## Creates a command in the format of ## `Set-Cookie: key=value; Domain=...; ...` result = setCookie(key, value, domain, path, From 057be018e9bee0e75ba8521039484daed0e0ee8f Mon Sep 17 00:00:00 2001 From: flywind Date: Sat, 20 Feb 2021 17:52:43 +0800 Subject: [PATCH 08/10] docuemnt sameSite --- lib/pure/cookies.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index 806ed673253e..41a8e7ded3cf 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -14,6 +14,8 @@ import std/[strtabs, times, options] type SameSite* {.pure.} = enum ## The SameSite cookie attribute. + ## `Default` means that `setCookie` + ## proc will not set `SameSite` attribute. Default, None, Lax, Strict proc parseCookies*(s: string): StringTableRef = From 73325988599c7c58f82084d95694f76b25de2614 Mon Sep 17 00:00:00 2001 From: flywind Date: Sat, 20 Feb 2021 17:55:02 +0800 Subject: [PATCH 09/10] fix a typo --- lib/pure/cookies.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index 41a8e7ded3cf..d9471f024831 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -62,7 +62,7 @@ proc setCookie*(key, value: string, domain = "", path = "", if sameSite != SameSite.Default: if sameSite == SameSite.None: - doAssert httpOnly, "Cookies with SameSite=None must must specify the Secure attribute!" + doAssert httpOnly, "Cookies with SameSite=None must specify the Secure attribute!" result.add("; SameSite=" & $sameSite) proc setCookie*(key, value: string, expires: DateTime|Time, From 9916307cb1f3833e63c0239844a1a6e487099f24 Mon Sep 17 00:00:00 2001 From: flywind Date: Mon, 22 Feb 2021 17:37:22 -0600 Subject: [PATCH 10/10] Update lib/pure/cookies.nim Co-authored-by: hlaaftana <10591326+hlaaftana@users.noreply.github.com> --- lib/pure/cookies.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index d9471f024831..8d9cc0c95802 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -62,7 +62,7 @@ proc setCookie*(key, value: string, domain = "", path = "", if sameSite != SameSite.Default: if sameSite == SameSite.None: - doAssert httpOnly, "Cookies with SameSite=None must specify the Secure attribute!" + doAssert secure, "Cookies with SameSite=None must specify the Secure attribute!" result.add("; SameSite=" & $sameSite) proc setCookie*(key, value: string, expires: DateTime|Time,