diff options
author | bptato <nincsnevem662@gmail.com> | 2023-08-01 19:05:45 +0200 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2023-08-01 19:37:48 +0200 |
commit | af3dbce840d0d0956663ffb20012329a4c22d5dd (patch) | |
tree | da3c2bad567d9b08f585cbc973aac61ef4eb05ae | |
parent | cab49aa0952c24941bcfb9a5b483f796158bf373 (diff) | |
download | chawan-af3dbce840d0d0956663ffb20012329a4c22d5dd.tar.gz |
Fixes & workarounds to compile on Nim 2.0.0
* Import punycode, as it has been removed from stdlib. * Fix some syntax errors * Apparently you can no longer compare distinct pointers with nil. Add explicit comparisons with typeof(nil) instead. * htmlparser: rename _ to other, as semantics of _ have changed. (Quite a shame, it looked better with _. Oh well.) * Explicitly specify mm:refc, as the browser OOMs with orc for some reason. Confirmed to compile & run on 2.0.0, 1.6.14, 1.6.12, 1.6.10 and 1.6.8. (<1.6.8 it's broken & wontfix.)
-rw-r--r-- | lib/punycode.nim | 211 | ||||
-rw-r--r-- | nim.cfg | 1 | ||||
-rw-r--r-- | src/bindings/curl.nim | 2 | ||||
-rw-r--r-- | src/bindings/quickjs.nim | 3 | ||||
-rw-r--r-- | src/config/toml.nim | 2 | ||||
-rw-r--r-- | src/css/cssparser.nim | 5 | ||||
-rw-r--r-- | src/css/match.nim | 2 | ||||
-rw-r--r-- | src/html/dom.nim | 12 | ||||
-rw-r--r-- | src/html/htmlparser.nim | 42 | ||||
-rw-r--r-- | src/io/promise.nim | 3 | ||||
-rw-r--r-- | src/io/response.nim | 2 | ||||
-rw-r--r-- | src/js/javascript.nim | 2 | ||||
-rw-r--r-- | src/utils/twtstr.nim | 6 |
13 files changed, 257 insertions, 36 deletions
diff --git a/lib/punycode.nim b/lib/punycode.nim new file mode 100644 index 00000000..bfd77e40 --- /dev/null +++ b/lib/punycode.nim @@ -0,0 +1,211 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2016 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## .. note:: In order to use this module, run `nimble install punycode`. +## +## Implements a representation of Unicode with the limited +## ASCII character subset. + +import strutils +import unicode + +# issue #3045 + +const + Base = 36 + TMin = 1 + TMax = 26 + Skew = 38 + Damp = 700 + InitialBias = 72 + InitialN = 128 + Delimiter = '-' + +type + PunyError* = object of ValueError + +func decodeDigit(x: char): int {.raises: [PunyError].} = + if '0' <= x and x <= '9': + result = ord(x) - (ord('0') - 26) + elif 'A' <= x and x <= 'Z': + result = ord(x) - ord('A') + elif 'a' <= x and x <= 'z': + result = ord(x) - ord('a') + else: + raise newException(PunyError, "Bad input") + +func encodeDigit(digit: int): Rune {.raises: [PunyError].} = + if 0 <= digit and digit < 26: + result = Rune(digit + ord('a')) + elif 26 <= digit and digit < 36: + result = Rune(digit + (ord('0') - 26)) + else: + raise newException(PunyError, "internal error in punycode encoding") + +func isBasic(c: char): bool = ord(c) < 0x80 +func isBasic(r: Rune): bool = int(r) < 0x80 + +func adapt(delta, numPoints: int, first: bool): int = + var d = if first: delta div Damp else: delta div 2 + d += d div numPoints + var k = 0 + while d > ((Base-TMin)*TMax) div 2: + d = d div (Base - TMin) + k += Base + result = k + (Base - TMin + 1) * d div (d + Skew) + +func encode*(prefix, s: string): string {.raises: [PunyError].} = + ## Encode a string that may contain Unicode. + ## Prepend `prefix` to the result + result = prefix + var (d, n, bias) = (0, InitialN, InitialBias) + var (b, remaining) = (0, 0) + for r in s.runes: + if r.isBasic: + # basic Ascii character + inc b + result.add($r) + else: + # special character + inc remaining + + var h = b + if b > 0: + result.add(Delimiter) # we have some Ascii chars + while remaining != 0: + var m: int = high(int32) + for r in s.runes: + if m > int(r) and int(r) >= n: + m = int(r) + d += (m - n) * (h + 1) + if d < 0: + raise newException(PunyError, "invalid label " & s) + n = m + for r in s.runes: + if int(r) < n: + inc d + if d < 0: + raise newException(PunyError, "invalid label " & s) + continue + if int(r) > n: + continue + var q = d + var k = Base + while true: + var t = k - bias + if t < TMin: + t = TMin + elif t > TMax: + t = TMax + if q < t: + break + result.add($encodeDigit(t + (q - t) mod (Base - t))) + q = (q - t) div (Base - t) + k += Base + result.add($encodeDigit(q)) + bias = adapt(d, h + 1, h == b) + d = 0 + inc h + dec remaining + inc d + inc n + +func encode*(s: string): string {.raises: [PunyError].} = + ## Encode a string that may contain Unicode. Prefix is empty. + result = encode("", s) + +func decode*(encoded: string): string {.raises: [PunyError].} = + ## Decode a Punycode-encoded string + var + n = InitialN + i = 0 + bias = InitialBias + var d = rfind(encoded, Delimiter) + var output: seq[Rune] + + if d > 0: + # found Delimiter + for j in 0..<d: + var c = encoded[j] # char + if not c.isBasic: + raise newException(PunyError, "Encoded contains a non-basic char") + output.add(Rune(c)) # add the character + inc d + else: + d = 0 # set to first index + + while (d < len(encoded)): + var oldi = i + var w = 1 + var k = Base + while true: + if d == len(encoded): + raise newException(PunyError, "Bad input: " & encoded) + var c = encoded[d]; inc d + var digit = int(decodeDigit(c)) + if digit > (high(int32) - i) div w: + raise newException(PunyError, "Too large a value: " & $digit) + i += digit * w + var t: int + if k <= bias: + t = TMin + elif k >= bias + TMax: + t = TMax + else: + t = k - bias + if digit < t: + break + w *= Base - t + k += Base + bias = adapt(i - oldi, len(output) + 1, oldi == 0) + + if i div (len(output) + 1) > high(int32) - n: + raise newException(PunyError, "Value too large") + + n += i div (len(output) + 1) + i = i mod (len(output) + 1) + insert(output, Rune(n), i) + inc i + + result = $output + +runnableExamples: + static: + block: + doAssert encode("") == "" + doAssert encode("a") == "a-" + doAssert encode("A") == "A-" + doAssert encode("3") == "3-" + doAssert encode("-") == "--" + doAssert encode("--") == "---" + doAssert encode("abc") == "abc-" + doAssert encode("London") == "London-" + doAssert encode("Lloyd-Atkinson") == "Lloyd-Atkinson-" + doAssert encode("This has spaces") == "This has spaces-" + doAssert encode("ü") == "tda" + doAssert encode("München") == "Mnchen-3ya" + doAssert encode("Mnchen-3ya") == "Mnchen-3ya-" + doAssert encode("München-Ost") == "Mnchen-Ost-9db" + doAssert encode("Bahnhof München-Ost") == "Bahnhof Mnchen-Ost-u6b" + block: + doAssert decode("") == "" + doAssert decode("a-") == "a" + doAssert decode("A-") == "A" + doAssert decode("3-") == "3" + doAssert decode("--") == "-" + doAssert decode("---") == "--" + doAssert decode("abc-") == "abc" + doAssert decode("London-") == "London" + doAssert decode("Lloyd-Atkinson-") == "Lloyd-Atkinson" + doAssert decode("This has spaces-") == "This has spaces" + doAssert decode("tda") == "ü" + doAssert decode("Mnchen-3ya") == "München" + doAssert decode("Mnchen-3ya-") == "Mnchen-3ya" + doAssert decode("Mnchen-Ost-9db") == "München-Ost" + doAssert decode("Bahnhof Mnchen-Ost-u6b") == "Bahnhof München-Ost" diff --git a/nim.cfg b/nim.cfg index f81553bc..03c3173f 100644 --- a/nim.cfg +++ b/nim.cfg @@ -4,3 +4,4 @@ --import:"utils/eprint" --experimental:"overloadableEnums" --warning:Effect:off +--mm:refc diff --git a/src/bindings/curl.nim b/src/bindings/curl.nim index 07395b65..ed2057eb 100644 --- a/src/bindings/curl.nim +++ b/src/bindings/curl.nim @@ -286,7 +286,9 @@ type CURLMSG_LAST # last, not used proc `==`*(a: CURL, b: CURL): bool {.borrow.} +proc `==`*(a: CURL, b: typeof(nil)): bool {.borrow.} proc `==`*(a: CURLM, b: CURLM): bool {.borrow.} +proc `==`*(a: CURLM, b: typeof(nil)): bool {.borrow.} {.push importc.} diff --git a/src/bindings/quickjs.nim b/src/bindings/quickjs.nim index 7ff8fd0f..d415c17e 100644 --- a/src/bindings/quickjs.nim +++ b/src/bindings/quickjs.nim @@ -281,7 +281,8 @@ template JS_CGETSET_DEF*(n: string, fgetter, fsetter: untyped): JSCFunctionListE get: JSCFunctionType(getter: fgetter), set: JSCFunctionType(setter: fsetter)))) -template JS_CGETSET_MAGIC_DEF*(n: string, fgetter, fsetter: untyped, m: cint): JSCFunctionListEntry = +template JS_CGETSET_MAGIC_DEF*(n: string, fgetter, fsetter: untyped, + m: int16): JSCFunctionListEntry = JSCFunctionListEntry(name: cstring(n), prop_flags: JS_PROP_CONFIGURABLE, def_type: JS_DEF_CGETSET_MAGIC, diff --git a/src/config/toml.nim b/src/config/toml.nim index fc066048..66f8335f 100644 --- a/src/config/toml.nim +++ b/src/config/toml.nim @@ -124,7 +124,7 @@ proc consumeEscape(state: var TomlParser, c: char): Result[Rune, TomlError] = if i != len - 1: return state.err("invalid escaped length (" & $i & ", needs " & $len & ")") - if num > 0x10FFFF or num in {0xD800..0xDFFF}: + if num > 0x10FFFF or num in 0xD800..0xDFFF: return state.err("invalid escaped codepoint: " & $num) else: return ok(cast[Rune](num)) diff --git a/src/css/cssparser.nim b/src/css/cssparser.nim index fb8b0cfa..c5448599 100644 --- a/src/css/cssparser.nim +++ b/src/css/cssparser.nim @@ -195,7 +195,8 @@ proc next3startsWithIdentSequence(state: var CSSTokenizerState): bool = case state.peek() of '-': - return state.has(1) and state.peek(1) in IdentStart + {'-'} or state.has(2) and isValidEscape(state.peek(1), state.peek(2)): + return state.has(1) and state.peek(1) in IdentStart + {'-'} or + state.has(2) and isValidEscape(state.peek(1), state.peek(2)) of IdentStart: return true of '\\': @@ -239,7 +240,7 @@ proc consumeEscape(state: var CSSTokenizerState): string = inc i if state.peek().isWhitespace(): discard state.consume() - if num == 0 or num > 0x10FFFF or num in {0xD800..0xDFFF}: + if num == 0 or num > 0x10FFFF or num in 0xD800..0xDFFF: return $Rune(0xFFFD) else: return $Rune(num) diff --git a/src/css/match.nim b/src/css/match.nim index 6f684e8b..810cdbe4 100644 --- a/src/css/match.nim +++ b/src/css/match.nim @@ -142,7 +142,7 @@ func complexSelectorMatches[T: Element|StyledNode](elem: T, cxsel: ComplexSelect var match = false case sels.ct of NO_COMBINATOR: - match = e.selectorsMatch(sels, felem): + match = e.selectorsMatch(sels, felem) of DESCENDANT_COMBINATOR: e = e.parentElement while e != nil: diff --git a/src/html/dom.nim b/src/html/dom.nim index 4318c517..11254c56 100644 --- a/src/html/dom.nim +++ b/src/html/dom.nim @@ -2872,9 +2872,9 @@ proc querySelector*(node: Node, q: string): Element {.jsfunc.} = const (ReflectTable, TagReflectMap, ReflectAllStartIndex) = (func(): ( seq[ReflectEntry], - Table[TagType, seq[uint16]], - uint16) = - var i: uint16 = 0 + Table[TagType, seq[int16]], + int16) = + var i: int16 = 0 while i < ReflectTable0.len: let x = ReflectTable0[i] result[0].add(x) @@ -2882,7 +2882,7 @@ const (ReflectTable, TagReflectMap, ReflectAllStartIndex) = (func(): ( break for tag in result[0][i].tags: if tag notin result[1]: - result[1][tag] = newSeq[uint16]() + result[1][tag] = newSeq[int16]() result[1][tag].add(i) assert result[0][i].tags.len != 0 inc i @@ -2967,8 +2967,8 @@ func getReflectFunctions(tags: set[TagType]): seq[TabGetSet] = return result func getElementReflectFunctions(): seq[TabGetSet] = - var i: uint16 = ReflectAllStartIndex - while i < uint16(ReflectTable.len): + var i: int16 = ReflectAllStartIndex + while i < int16(ReflectTable.len): let entry = ReflectTable[i] assert entry.tags == AllTagTypes result.add(TabGetSet(name: ReflectTable[i].funcname, get: jsReflectGet, set: jsReflectSet, magic: i)) diff --git a/src/html/htmlparser.nim b/src/html/htmlparser.nim index 05e830fb..2192ccf8 100644 --- a/src/html/htmlparser.nim +++ b/src/html/htmlparser.nim @@ -1152,7 +1152,7 @@ proc closeP(parser: var HTML5Parser) = # ("<p>", "<a>", "</div>") => (block: echo "p, a or closing div") # ("<div>", "</p>") => (block: anything_else) # (TokenType.START_TAG, TokenType.END_TAG) => (block: assert false, "invalid") -# _ => (block: echo "anything else") +# other => (block: echo "anything else") # # (effectively) generates this: # @@ -1322,7 +1322,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], quote do: discard (`v`, proc() = `body`) - template _ = discard + template other = discard template reprocess(tok: Token) = parser.processInHTMLContent(tok, parser.insertionMode) @@ -1362,7 +1362,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], parser.setQuirksMode(LIMITED_QUIRKS) parser.insertionMode = BEFORE_HTML ) - _ => (block: + other => (block: if not parser.opts.isIframeSrcdoc: parse_error UNEXPECTED_INITIAL_TOKEN parser.setQuirksMode(QUIRKS) @@ -1386,7 +1386,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], ) ("</head>", "</body>", "</html>", "</br>") => (block: anything_else) TokenType.END_TAG => (block: parse_error UNEXPECTED_END_TAG) - _ => (block: + other => (block: let element = parser.createElement(TAG_HTML, Namespace.HTML) parser.append(parser.document, element) parser.pushElement(element) @@ -1406,7 +1406,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], ) ("</head>", "</body>", "</html>", "</br>") => (block: anything_else) TokenType.END_TAG => (block: parse_error UNEXPECTED_END_TAG) - _ => (block: + other => (block: let head = Token(t: START_TAG, tagtype: TAG_HEAD) parser.head = some(parser.insertHTMLElement(head)) parser.insertionMode = IN_HEAD @@ -1481,7 +1481,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], parser.resetInsertionMode() ) ("<head>", TokenType.END_TAG) => (block: parse_error UNEXPECTED_END_TAG) - _ => (block: + other => (block: pop_current_node parser.insertionMode = AFTER_HEAD reprocess token @@ -1503,7 +1503,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], "</br>" => (block: anything_else) ("<head>", "<noscript>") => (block: parse_error UNEXPECTED_START_TAG) TokenType.END_TAG => (block: parse_error UNEXPECTED_END_TAG) - _ => (block: + other => (block: pop_current_node parser.insertionMode = IN_HEAD reprocess token @@ -1537,7 +1537,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], ("</body>", "</html>", "</br>") => (block: anything_else) ("<head>") => (block: parse_error UNEXPECTED_START_TAG) (TokenType.END_TAG) => (block: parse_error UNEXPECTED_END_TAG) - _ => (block: + other => (block: discard parser.insertHTMLElement(Token(t: START_TAG, tagtype: TAG_BODY)) parser.insertionMode = IN_BODY reprocess token @@ -2089,7 +2089,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], TokenType.EOF => (block: parser.processInHTMLContent(token, IN_BODY) ) - _ => (block: + other => (block: parse_error UNEXPECTED_START_TAG parser.fosterParenting = true parser.processInHTMLContent(token, IN_BODY) @@ -2108,7 +2108,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], parser.pendingTableChars &= $token.r parser.pendingTableCharsWhitespace = false ) - _ => (block: + other => (block: if not parser.pendingTableCharsWhitespace: # I *think* this is effectively the same thing the specification # wants... @@ -2151,7 +2151,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], "</tfoot>", "</th>", "</thead>", "</tr>") => (block: parse_error UNEXPECTED_END_TAG ) - _ => (block: parser.processInHTMLContent(token, IN_BODY)) + other => (block: parser.processInHTMLContent(token, IN_BODY)) of IN_COLUMN_GROUP: match token: @@ -2175,7 +2175,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], parser.processInHTMLContent(token, IN_HEAD) ) TokenType.EOF => (block: parser.processInHTMLContent(token, IN_BODY)) - _ => (block: + other => (block: if parser.getTagType(parser.currentNode) != TAG_COLGROUP: parse_error MISMATCHED_TAGS else: @@ -2224,7 +2224,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], "</th>", "</tr>") => (block: parse_error ELEMENT_NOT_IN_SCOPE ) - _ => (block: parser.processInHTMLContent(token, IN_TABLE)) + other => (block: parser.processInHTMLContent(token, IN_TABLE)) of IN_ROW: template clear_the_stack_back_to_a_table_row_context() = @@ -2269,7 +2269,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], ) ("</body>", "</caption>", "</col>", "</colgroup>", "</html>", "</td>", "</th>") => (block: parse_error UNEXPECTED_END_TAG) - _ => (block: parser.processInHTMLContent(token, IN_TABLE)) + other => (block: parser.processInHTMLContent(token, IN_TABLE)) of IN_CELL: template close_cell() = @@ -2308,7 +2308,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], close_cell reprocess token ) - _ => (block: parser.processInHTMLContent(token, IN_BODY)) + other => (block: parser.processInHTMLContent(token, IN_BODY)) of IN_SELECT: match token: @@ -2391,7 +2391,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], parser.resetInsertionMode() reprocess token ) - _ => (block: parser.processInHTMLContent(token, IN_SELECT)) + other => (block: parser.processInHTMLContent(token, IN_SELECT)) of IN_TEMPLATE: match token: @@ -2458,7 +2458,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], parser.insertionMode = AFTER_AFTER_BODY ) TokenType.EOF => (block: discard) # stop - _ => (block: + other => (block: parse_error UNEXPECTED_AFTER_BODY_TOKEN parser.insertionMode = IN_BODY reprocess token @@ -2489,7 +2489,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], parse_error UNEXPECTED_EOF # stop ) - _ => (block: parser.parseErrorByTokenType(token.t)) + other => (block: parser.parseErrorByTokenType(token.t)) of AFTER_FRAMESET: match token: @@ -2500,7 +2500,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], "</html>" => (block: parser.insertionMode = AFTER_AFTER_FRAMESET) "<noframes>" => (block: parser.processInHTMLContent(token, IN_HEAD)) TokenType.EOF => (block: discard) # stop - _ => (block: parser.parseErrorByTokenType(token.t)) + other => (block: parser.parseErrorByTokenType(token.t)) of AFTER_AFTER_BODY: match token: @@ -2511,7 +2511,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], parser.processInHTMLContent(token, IN_BODY) ) TokenType.EOF => (block: discard) # stop - _ => (block: + other => (block: parser.parseErrorByTokenType(token.t) parser.insertionMode = IN_BODY reprocess token @@ -2527,7 +2527,7 @@ proc processInHTMLContent[Handle](parser: var HTML5Parser[Handle], ) TokenType.EOF => (block: discard) # stop "<noframes>" => (block: parser.processInHTMLContent(token, IN_HEAD)) - _ => (block: parser.parseErrorByTokenType(token.t)) + other => (block: parser.parseErrorByTokenType(token.t)) const CaseTable = { "altglyph": "altGlyph", diff --git a/src/io/promise.nim b/src/io/promise.nim index ba1dad07..ee4f0654 100644 --- a/src/io/promise.nim +++ b/src/io/promise.nim @@ -22,6 +22,9 @@ type tab: Table[int, EmptyPromise] opaque*: pointer +proc newPromise*[T](): Promise[T] = + return Promise[T]() + proc newPromiseMap*(opaque: pointer): PromiseMap = return PromiseMap( opaque: opaque diff --git a/src/io/response.nim b/src/io/response.nim index 6a5a5bbf..b64f1504 100644 --- a/src/io/response.nim +++ b/src/io/response.nim @@ -49,7 +49,7 @@ proc close*(response: Response) {.jsfunc.} = proc text*(response: Response): Promise[Result[string, JSError]] {.jsfunc.} = if response.bodyRead == nil: - let p = Promise[Result[string, JSError]]() + let p = newPromise[Result[string, JSError]]() let err = Result[string, JSError] .err(newTypeError("Body has already been consumed")) p.resolve(err) diff --git a/src/js/javascript.nim b/src/js/javascript.nim index 48d82954..0cc1fb83 100644 --- a/src/js/javascript.nim +++ b/src/js/javascript.nim @@ -1829,7 +1829,7 @@ type name*: string get*: JSGetterMagicFunction set*: JSSetterMagicFunction - magic*: uint16 + magic*: int16 TabFunc* = object name*: string diff --git a/src/utils/twtstr.nim b/src/utils/twtstr.nim index 9273b703..1c2c2a1d 100644 --- a/src/utils/twtstr.nim +++ b/src/utils/twtstr.nim @@ -5,7 +5,6 @@ import os import math import sequtils import options -import punycode import bindings/libunicode import data/charwidth @@ -13,6 +12,7 @@ import data/idna import js/javascript import utils/map import utils/opt +import lib/punycode when defined(posix): import posix @@ -951,7 +951,9 @@ func isCombining(r: Rune): bool = # We do not store a lookup table of ambiguous ranges, either. type PropertyTable = array[0..(0xFFFF div 8), uint8] -func makePropertyTable(ranges, skip: openarray[(uint32, uint32)] = @[]): PropertyTable = +type RangeMap = openarray[(uint32, uint32)] + +func makePropertyTable(ranges: RangeMap, skip: RangeMap = @[]): PropertyTable = var ucs: uint32 = 0 var j = 0 var k = 0 |