about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-03-24 20:43:19 +0100
committerbptato <nincsnevem662@gmail.com>2024-03-24 21:45:23 +0100
commitcc7eacf75ebee5b3846e26b4fe338279a34bf939 (patch)
tree1f805566927f79ba2500e039561d93c18b00e7f9 /src
parent78a977b76dc4cb695f406666e035c880cce8cdd5 (diff)
downloadchawan-cc7eacf75ebee5b3846e26b4fe338279a34bf939.tar.gz
js: proper distinction between Opt/Option
until now, this had very strange (and inconsistent) semantics:

* err() was used for exception propagation, but also as a null value
* Option accepted undefined as a none value, but not null
* Opt and Option were used interchangeably (and mostly randomly)

Now, Result is always used for error reporting, and err(nil) means
JS_EXCEPTION. (Opt is a special case of Result where we don't care about
the error type, and is not used in JS.)

Option on the other hand means "nullable variation of normally
non-nullable type", and translates to JS_NULL. In JS we mainly use
it for turning strings nullable.
Diffstat (limited to 'src')
-rw-r--r--src/config/config.nim79
-rw-r--r--src/html/dom.nim20
-rw-r--r--src/html/event.nim11
-rw-r--r--src/html/formdata.nim2
-rw-r--r--src/js/encoding.nim9
-rw-r--r--src/js/fromjs.nim45
-rw-r--r--src/js/tojs.nim3
-rw-r--r--src/loader/cgi.nim1
-rw-r--r--src/loader/request.nim34
-rw-r--r--src/local/pager.nim12
-rw-r--r--src/server/buffer.nim12
11 files changed, 110 insertions, 118 deletions
diff --git a/src/config/config.nim b/src/config/config.nim
index a01187a7..962ede7f 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -35,19 +35,19 @@ type
     t: Table[string, string]
 
   SiteConfig* = object
-    url*: Opt[Regex]
-    host*: Opt[Regex]
+    url*: Option[Regex]
+    host*: Option[Regex]
     rewrite_url*: (proc(s: URL): JSResult[URL])
-    cookie*: Opt[bool]
+    cookie*: Option[bool]
     third_party_cookie*: seq[Regex]
-    share_cookie_jar*: Opt[string]
-    referer_from*: Opt[bool]
-    scripting*: Opt[bool]
+    share_cookie_jar*: Option[string]
+    referer_from*: Option[bool]
+    scripting*: Option[bool]
     document_charset*: seq[Charset]
-    images*: Opt[bool]
-    stylesheet*: Opt[string]
-    proxy*: Opt[URL]
-    default_headers*: Opt[Table[string, string]]
+    images*: Option[bool]
+    stylesheet*: Option[string]
+    proxy*: Option[URL]
+    default_headers*: TableRef[string, string]
 
   OmniRule* = object
     match*: Regex
@@ -67,7 +67,7 @@ type
     ignore_case* {.jsgetset.}: bool
 
   EncodingConfig = object
-    display_charset* {.jsgetset.}: Opt[Charset]
+    display_charset* {.jsgetset.}: Option[Charset]
     document_charset* {.jsgetset.}: seq[Charset]
 
   ExternalConfig = object
@@ -92,19 +92,19 @@ type
     default_headers* {.jsgetset.}: Table[string, string]
 
   DisplayConfig = object
-    color_mode* {.jsgetset.}: Opt[ColorMode]
-    format_mode* {.jsgetset.}: Opt[FormatMode]
+    color_mode* {.jsgetset.}: Option[ColorMode]
+    format_mode* {.jsgetset.}: Option[FormatMode]
     no_format_mode* {.jsgetset.}: FormatMode
     emulate_overline* {.jsgetset.}: bool
-    alt_screen* {.jsgetset.}: Opt[bool]
+    alt_screen* {.jsgetset.}: Option[bool]
     highlight_color* {.jsgetset.}: RGBAColor
     highlight_marks* {.jsgetset.}: bool
     double_width_ambiguous* {.jsgetset.}: bool
     minimum_contrast* {.jsgetset.}: int32
     force_clear* {.jsgetset.}: bool
     set_title* {.jsgetset.}: bool
-    default_background_color* {.jsgetset.}: Opt[RGBColor]
-    default_foreground_color* {.jsgetset.}: Opt[RGBColor]
+    default_background_color* {.jsgetset.}: Option[RGBColor]
+    default_foreground_color* {.jsgetset.}: Option[RGBColor]
     query_da1* {.jsgetset.}: bool
     columns* {.jsgetset.}: int32
     lines* {.jsgetset.}: int32
@@ -211,9 +211,10 @@ func getRealKey(key: string): string =
     realk &= '\\'
   return realk
 
-proc getter(a: ptr ActionMap; s: string): Opt[string] {.jsgetprop.} =
+proc getter(a: ptr ActionMap; s: string): Option[string] {.jsgetprop.} =
   a.t.withValue(s, p):
-    return opt(p[])
+    return some(p[])
+  return none(string)
 
 proc setter(a: ptr ActionMap; k, v: string) {.jssetprop.} =
   let k = getRealKey(k)
@@ -294,9 +295,9 @@ proc parseConfigValue(ctx: var ConfigParser; x: var int32; v: TomlValue;
   k: string)
 proc parseConfigValue(ctx: var ConfigParser; x: var int64; v: TomlValue;
   k: string)
-proc parseConfigValue(ctx: var ConfigParser; x: var Opt[ColorMode];
+proc parseConfigValue(ctx: var ConfigParser; x: var Option[ColorMode];
   v: TomlValue; k: string)
-proc parseConfigValue(ctx: var ConfigParser; x: var Opt[FormatMode];
+proc parseConfigValue(ctx: var ConfigParser; x: var Option[FormatMode];
   v: TomlValue; k: string)
 proc parseConfigValue(ctx: var ConfigParser; x: var FormatMode; v: TomlValue;
   k: string)
@@ -304,14 +305,14 @@ proc parseConfigValue(ctx: var ConfigParser; x: var RGBAColor; v: TomlValue;
   k: string)
 proc parseConfigValue(ctx: var ConfigParser; x: var RGBColor; v: TomlValue;
   k: string)
-proc parseConfigValue[T](ctx: var ConfigParser; x: var Opt[T]; v: TomlValue;
-  k: string)
 proc parseConfigValue(ctx: var ConfigParser; x: var ActionMap; v: TomlValue;
   k: string)
 proc parseConfigValue(ctx: var ConfigParser; x: var CSSConfig; v: TomlValue;
   k: string)
 proc parseConfigValue[U; V](ctx: var ConfigParser; x: var Table[U, V];
   v: TomlValue; k: string)
+proc parseConfigValue[U; V](ctx: var ConfigParser; x: var TableRef[U, V];
+  v: TomlValue; k: string)
 proc parseConfigValue[T](ctx: var ConfigParser; x: var set[T]; v: TomlValue;
   k: string)
 proc parseConfigValue(ctx: var ConfigParser; x: var TomlTable; v: TomlValue;
@@ -364,6 +365,16 @@ proc parseConfigValue[U, V](ctx: var ConfigParser; x: var Table[U, V];
     ctx.parseConfigValue(y, vv, kkk)
     x[kk] = y
 
+proc parseConfigValue[U, V](ctx: var ConfigParser; x: var TableRef[U, V];
+    v: TomlValue; k: string) =
+  typeCheck(v, VALUE_TABLE, k)
+  x = TableRef[U, V]()
+  for kk, vv in v:
+    var y: V
+    let kkk = k & "[" & kk & "]"
+    ctx.parseConfigValue(y, vv, kkk)
+    x[kk] = y
+
 proc parseConfigValue(ctx: var ConfigParser; x: var bool; v: TomlValue;
     k: string) =
   typeCheck(v, VALUE_BOOLEAN, k)
@@ -417,28 +428,28 @@ proc parseConfigValue(ctx: var ConfigParser; x: var int64; v: TomlValue;
   typeCheck(v, VALUE_INTEGER, k)
   x = v.i
 
-proc parseConfigValue(ctx: var ConfigParser; x: var Opt[ColorMode];
+proc parseConfigValue(ctx: var ConfigParser; x: var Option[ColorMode];
     v: TomlValue; k: string) =
   typeCheck(v, VALUE_STRING, k)
   case v.s
-  of "auto": x.err()
-  of "monochrome": x.ok(MONOCHROME)
-  of "ansi": x.ok(ANSI)
-  of "8bit", "eight-bit": x.ok(EIGHT_BIT)
-  of "24bit", "true-color": x.ok(TRUE_COLOR)
+  of "auto": x = none(ColorMode)
+  of "monochrome": x = some(MONOCHROME)
+  of "ansi": x = some(ANSI)
+  of "8bit", "eight-bit": x = some(EIGHT_BIT)
+  of "24bit", "true-color": x = some(TRUE_COLOR)
   else:
     raise newException(ValueError, "unknown color mode '" & v.s &
       "' for key " & k)
 
-proc parseConfigValue(ctx: var ConfigParser; x: var Opt[FormatMode];
+proc parseConfigValue(ctx: var ConfigParser; x: var Option[FormatMode];
     v: TomlValue; k: string) =
   typeCheck(v, {VALUE_STRING, VALUE_ARRAY}, k)
   if v.vt == VALUE_STRING and v.s == "auto":
-    x.err()
+    x = none(FormatMode)
   else:
     var y: FormatMode
     ctx.parseConfigValue(y, v, k)
-    x.ok(y)
+    x = some(y)
 
 proc parseConfigValue(ctx: var ConfigParser; x: var FormatMode; v: TomlValue;
     k: string) =
@@ -477,14 +488,14 @@ proc parseConfigValue(ctx: var ConfigParser; x: var RGBColor; v: TomlValue;
       "' for key " & k)
   x = c.get
 
-proc parseConfigValue[T](ctx: var ConfigParser; x: var Opt[T]; v: TomlValue;
+proc parseConfigValue[T](ctx: var ConfigParser; x: var Option[T]; v: TomlValue;
     k: string) =
   if v.vt == VALUE_STRING and v.s == "auto":
-    x.err()
+    x = none(T)
   else:
     var y: T
     ctx.parseConfigValue(y, v, k)
-    x.ok(y)
+    x = some(y)
 
 proc parseConfigValue(ctx: var ConfigParser; x: var ActionMap; v: TomlValue;
     k: string) =
diff --git a/src/html/dom.nim b/src/html/dom.nim
index f0cc05c9..0ee42967 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -1902,10 +1902,10 @@ func textContent*(node: Node): string =
       if not (child of Comment):
         result &= child.textContent
 
-func jsTextContent(node: Node): Opt[string] {.jsfget: "textContent".} =
+func jsTextContent(node: Node): Option[string] {.jsfget: "textContent".} =
   if node of Document or node of DocumentType:
-    return err() # null
-  return ok(node.textContent)
+    return none(string) # null
+  return some(node.textContent)
 
 func childTextContent*(node: Node): string =
   for child in node.childList:
@@ -2730,10 +2730,10 @@ proc cssText(this: CSSStyleDeclaration): string {.jsfunc.} =
 func length(this: CSSStyleDeclaration): uint32 =
   return uint32(this.decls.len)
 
-func item(this: CSSStyleDeclaration, u: uint32): Opt[string] =
+func item(this: CSSStyleDeclaration, u: uint32): Option[string] =
   if u < this.length:
-    return ok(this.decls[int(u)].name)
-  return err()
+    return some(this.decls[int(u)].name)
+  return none(string)
 
 proc getPropertyValue(this: CSSStyleDeclaration, s: string): string =
   for decl in this.decls:
@@ -2752,16 +2752,16 @@ func IDLAttributeToCSSProperty(s: string, dashPrefix = false): string =
       result &= c
 
 proc getter[T: uint32|string](this: CSSStyleDeclaration, u: T):
-    Opt[string] {.jsgetprop.} =
+    Option[string] {.jsgetprop.} =
   when T is uint32:
     return this.item(u)
   else:
     if u.isSupportedProperty():
-      return ok(this.getPropertyValue(u))
+      return some(this.getPropertyValue(u))
     let u = IDLAttributeToCSSProperty(u)
     if u.isSupportedProperty():
-      return ok(this.getPropertyValue(u))
-    return err()
+      return some(this.getPropertyValue(u))
+    return none(string)
 
 proc style*(element: Element): CSSStyleDeclaration {.jsfget.} =
   if element.style_cached == nil:
diff --git a/src/html/event.nim b/src/html/event.nim
index 4eb389f9..7196d151 100644
--- a/src/html/event.nim
+++ b/src/html/event.nim
@@ -1,4 +1,5 @@
 import std/math
+import std/options
 import std/times
 
 import bindings/quickjs
@@ -51,7 +52,7 @@ type
     ctype*: string
     callback*: EventListenerCallback
     capture: bool
-    passive: Opt[bool]
+    passive: Option[bool]
     once: bool
     #TODO AbortSignal
     removed: bool
@@ -194,7 +195,7 @@ proc addAnEventListener(eventTarget: EventTarget, listener: EventListener) =
   if listener.callback == nil:
     return
   if listener.passive.isNone:
-    listener.passive = opt(defaultPassiveValue(listener.ctype, eventTarget))
+    listener.passive = some(defaultPassiveValue(listener.ctype, eventTarget))
   if eventTarget.findEventListener(listener.ctype, listener.callback,
       listener.capture) == -1: # dedup
     eventTarget.eventListeners.add(listener)
@@ -216,20 +217,20 @@ proc flattenMore(ctx: JSContext, options: JSValue):
     tuple[
       capture: bool,
       once: bool,
-      passive: Opt[bool]
+      passive: Option[bool]
       #TODO signals
     ] =
   if JS_IsUndefined(options):
     return
   let capture = flatten(ctx, options)
   var once = false
-  var passive: Opt[bool]
+  var passive: Option[bool]
   if JS_IsObject(options):
     once = fromJS[bool](ctx, JS_GetPropertyStr(ctx, options, "once"))
       .get(false)
     let x = fromJS[bool](ctx, JS_GetPropertyStr(ctx, options, "passive"))
     if x.isSome:
-      passive = opt(x.get)
+      passive = some(x.get)
   return (capture, once, passive)
 
 proc addEventListener(ctx: JSContext, eventTarget: EventTarget, ctype: string,
diff --git a/src/html/formdata.nim b/src/html/formdata.nim
index d34b0194..6db82333 100644
--- a/src/html/formdata.nim
+++ b/src/html/formdata.nim
@@ -44,7 +44,7 @@ proc newFormData*(form: HTMLFormElement = nil,
 #TODO filename should not be allowed for string entries
 # in other words, this should be an overloaded function, not just an or type
 proc append*[T: string|Blob](this: FormData, name: string, value: T,
-    filename = opt(string)) {.jsfunc.} =
+    filename = none(string)) {.jsfunc.} =
   when T is Blob:
     let filename = if filename.isSome:
       filename.get
diff --git a/src/js/encoding.nim b/src/js/encoding.nim
index b2ef1d1b..eff99805 100644
--- a/src/js/encoding.nim
+++ b/src/js/encoding.nim
@@ -146,8 +146,9 @@ type TextDecodeOptions = object of JSDict
   stream: bool
 
 #TODO AllowSharedBufferSource
-proc decode(ctx: JSContext, this: JSTextDecoder, input = opt(JSArrayBufferView),
-    options = TextDecodeOptions()): JSResult[JSValue] {.jsfunc.} =
+proc decode(ctx: JSContext; this: JSTextDecoder;
+    input = none(JSArrayBufferView); options = TextDecodeOptions()):
+    JSResult[JSValue] {.jsfunc.} =
   if not this.doNotFlush:
     if this.td != nil:
       this.td = newTextDecoder(this.encoding)
@@ -175,10 +176,10 @@ func newTextEncoder(): JSTextEncoder {.jsctor.} =
 func jencoding(this: JSTextEncoder): string {.jsfget: "encoding".} =
   return "utf-8"
 
-proc dealloc_wrap(rt: JSRuntime, opaque, p: pointer) {.cdecl.} =
+proc dealloc_wrap(rt: JSRuntime; opaque, p: pointer) {.cdecl.} =
   dealloc(p)
 
-proc encode(this: JSTextEncoder, input = ""): JSUint8Array {.jsfunc.} =
+proc encode(this: JSTextEncoder; input = ""): JSUint8Array {.jsfunc.} =
   # we have to validate input first :/
   #TODO it is possible to do less copies here...
   var input = input.toValidUTF8()
diff --git a/src/js/fromjs.nim b/src/js/fromjs.nim
index be90e192..a176cd33 100644
--- a/src/js/fromjs.nim
+++ b/src/js/fromjs.nim
@@ -134,18 +134,13 @@ macro fromJSTupleBody(a: tuple) =
       defer: JS_FreeValue(ctx, doneVal)
       `done` = ?fromJS[bool](ctx, doneVal)
       if `done`:
-        JS_ThrowTypeError(ctx,
-          "Too few arguments in sequence (got %d, expected %d)", cint(`i`),
-          cint(`len`))
-        return err()
+        return errTypeError("Too few arguments in sequence (got " & $`i` &
+          ", expected " & $`len` & ")")
       let valueVal = JS_GetProperty(ctx, next, ctx.getOpaque().str_refs[VALUE])
       if JS_IsException(valueVal):
         return err()
       defer: JS_FreeValue(ctx, valueVal)
-      let genericRes = fromJS[typeof(`a`[`i`])](ctx, valueVal)
-      if genericRes.isErr: # exception
-        return err()
-      `a`[`i`] = genericRes.get
+      `a`[`i`] = ?fromJS[typeof(`a`[`i`])](ctx, valueVal)
     )
     if i == len - 1:
       result.add(quote do:
@@ -222,10 +217,8 @@ proc fromJSSeq[T](ctx: JSContext, val: JSValue): JSResult[seq[T]] =
     if JS_IsException(valueVal):
       return err()
     defer: JS_FreeValue(ctx, valueVal)
-    let genericRes = fromJS[typeof(s[0])](ctx, valueVal)
-    if genericRes.isNone: # exception
-      return err()
-    s.add(genericRes.get)
+    let genericRes = ?fromJS[typeof(s[0])](ctx, valueVal)
+    s.add(genericRes)
   return ok(s)
 
 proc fromJSSet[T](ctx: JSContext, val: JSValue): JSResult[set[T]] =
@@ -345,24 +338,17 @@ proc fromJSFunction[T](ctx: JSContext, val: JSValue):
 template optionType[T](o: type Option[T]): auto =
   T
 
-# wrap
+# Option vs Opt:
+# Option is for nullable types, e.g. if you want to return either a string
+# or null. (This is rather pointless for anything else.)
+# Opt is for passing down exceptions received up in the chain.
+# So e.g. none(T) translates to JS_NULL, but err() translates to JS_EXCEPTION.
 proc fromJSOption[T](ctx: JSContext, val: JSValue): JSResult[Option[T]] =
-  if JS_IsUndefined(val):
-    #TODO what about null?
-    return err()
+  if JS_IsNull(val):
+    return ok(none(T))
   let res = ?fromJS[T](ctx, val)
   return ok(option(res))
 
-# wrap
-proc fromJSOpt[T](ctx: JSContext, val: JSValue): JSResult[T] =
-  if JS_IsUndefined(val):
-    #TODO what about null?
-    return err()
-  let res = fromJS[T.valType](ctx, val)
-  if res.isErr:
-    return ok(opt(T.valType))
-  return ok(opt(res.get))
-
 proc fromJSBool(ctx: JSContext, val: JSValue): JSResult[bool] =
   let ret = JS_ToBool(ctx, val)
   if ret == -1: # exception
@@ -391,9 +377,7 @@ proc fromJSPObj0(ctx: JSContext, val: JSValue, t: string):
   if not JS_IsObject(val):
     return err(newTypeError("Value is not an object"))
   if not isInstanceOfNonGlobal(ctx, val, t):
-    let errmsg = t & " expected"
-    JS_ThrowTypeError(ctx, cstring(errmsg))
-    return err(newTypeError(errmsg))
+    return errTypeError(t & " expected")
   let classid = JS_GetClassID(val)
   let op = JS_GetOpaque(val, classid)
   return ok(op)
@@ -403,7 +387,6 @@ proc fromJSObject[T: ref object](ctx: JSContext, val: JSValue): JSResult[T] =
 
 proc fromJSVoid(ctx: JSContext, val: JSValue): JSResult[void] =
   if JS_IsException(val):
-    #TODO maybe wrap or something
     return err()
   return ok()
 
@@ -483,8 +466,6 @@ proc fromJS*[T](ctx: JSContext, val: JSValue): JSResult[T] =
     return fromJSFunction[T](ctx, val)
   elif T is Option:
     return fromJSOption[optionType(T)](ctx, val)
-  elif T is Opt: # unwrap
-    return fromJSOpt[T](ctx, val)
   elif T is seq:
     return fromJSSeq[typeof(result.get.items)](ctx, val)
   elif T is set:
diff --git a/src/js/tojs.nim b/src/js/tojs.nim
index 746dccbb..807c85f5 100644
--- a/src/js/tojs.nim
+++ b/src/js/tojs.nim
@@ -211,8 +211,7 @@ proc toJS[T, E](ctx: JSContext, opt: Result[T, E]): JSValue =
       let res = toJS(ctx, opt.error)
       if not JS_IsNull(res):
         return JS_Throw(ctx, res)
-    else:
-      return JS_NULL
+    return JS_EXCEPTION
 
 proc toJS(ctx: JSContext, s: seq): JSValue =
   let a = JS_NewArray(ctx)
diff --git a/src/loader/cgi.nim b/src/loader/cgi.nim
index 8d6d60b3..3e3ec4fc 100644
--- a/src/loader/cgi.nim
+++ b/src/loader/cgi.nim
@@ -11,7 +11,6 @@ import loader/headers
 import loader/loaderhandle
 import loader/request
 import types/formdata
-import types/opt
 import types/url
 import utils/twtstr
 
diff --git a/src/loader/request.nim b/src/loader/request.nim
index 60632041..824e643e 100644
--- a/src/loader/request.nim
+++ b/src/loader/request.nim
@@ -71,8 +71,8 @@ type
     httpMethod*: HttpMethod
     url*: URL
     headers* {.jsget.}: Headers
-    body*: Opt[string]
-    multipart*: Opt[FormData]
+    body*: Option[string]
+    multipart*: Option[FormData]
     referrer*: URL
     mode* {.jsget.}: RequestMode
     destination* {.jsget.}: RequestDestination
@@ -103,7 +103,7 @@ iterator pairs*(headers: Headers): (string, string) =
       yield (k, v)
 
 func newRequest*(url: URL; httpMethod = HTTP_GET; headers = newHeaders();
-    body = opt(string); multipart = opt(FormData); mode = RequestMode.NO_CORS;
+    body = none(string); multipart = none(FormData); mode = RequestMode.NO_CORS;
     credentialsMode = CredentialsMode.SAME_ORIGIN;
     destination = RequestDestination.NO_DESTINATION; proxy: URL = nil;
     referrer: URL = nil; suspended = false): Request =
@@ -121,9 +121,9 @@ func newRequest*(url: URL; httpMethod = HTTP_GET; headers = newHeaders();
     suspended: suspended
   )
 
-func newRequest*(url: URL, httpMethod = HTTP_GET,
-    headers: seq[(string, string)] = @[], body = opt(string),
-    multipart = opt(FormData), mode = RequestMode.NO_CORS, proxy: URL = nil):
+func newRequest*(url: URL; httpMethod = HTTP_GET;
+    headers: seq[(string, string)] = @[]; body = none(string);
+    multipart = none(FormData); mode = RequestMode.NO_CORS; proxy: URL = nil):
     Request =
   let hl = newHeaders()
   for pair in headers:
@@ -172,13 +172,13 @@ type
   RequestInit* = object of JSDict
     #TODO aliasing in dicts
     `method`: HttpMethod # default: GET
-    headers: Opt[HeadersInit]
-    body: Opt[BodyInit]
-    referrer: Opt[string]
-    referrerPolicy: Opt[ReferrerPolicy]
-    credentials: Opt[CredentialsMode]
+    headers: Option[HeadersInit]
+    body: Option[BodyInit]
+    referrer: Option[string]
+    referrerPolicy: Option[ReferrerPolicy]
+    credentials: Option[CredentialsMode]
     proxyUrl: URL
-    mode: Opt[RequestMode]
+    mode: Option[RequestMode]
 
 proc fromJSBodyInit(ctx: JSContext, val: JSValue): JSResult[BodyInit] =
   if JS_IsUndefined(val) or JS_IsNull(val):
@@ -211,8 +211,8 @@ func newRequest*[T: string|Request](ctx: JSContext, resource: T,
     var headers = newHeaders()
     let referrer: URL = nil
     var credentials = CredentialsMode.SAME_ORIGIN
-    var body: Opt[string]
-    var multipart: Opt[FormData]
+    var body: Option[string]
+    var multipart: Option[FormData]
     var proxyUrl: URL #TODO?
     let fallbackMode = opt(RequestMode.CORS)
   else:
@@ -224,7 +224,7 @@ func newRequest*[T: string|Request](ctx: JSContext, resource: T,
     var body = resource.body
     var multipart = resource.multipart
     var proxyUrl = resource.proxy #TODO?
-    let fallbackMode = opt(RequestMode)
+    let fallbackMode = none(RequestMode)
     #TODO window
   var mode = fallbackMode.get(RequestMode.NO_CORS)
   let destination = NO_DESTINATION
@@ -240,9 +240,9 @@ func newRequest*[T: string|Request](ctx: JSContext, resource: T,
       let ibody = init.body.get
       case ibody.t
       of BODY_INIT_FORM_DATA:
-        multipart = opt(ibody.formData)
+        multipart = some(ibody.formData)
       of BODY_INIT_STRING:
-        body = opt(ibody.str)
+        body = some(ibody.str)
       else:
         discard #TODO
       if httpMethod in {HTTP_GET, HTTP_HEAD}:
diff --git a/src/local/pager.nim b/src/local/pager.nim
index 4105f08c..4628b11f 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -910,8 +910,8 @@ proc applySiteconf(pager: Pager; url: var URL; charsetOverride: Charset;
       userstyle &= sc.stylesheet.get
     if sc.proxy.isSome:
       proxy = sc.proxy.get
-    if sc.default_headers.isSome:
-      headers = newHeaders(sc.default_headers.get)
+    if sc.default_headers != nil:
+      headers = newHeaders(sc.default_headers[])
   loaderConfig = LoaderClientConfig(
     defaultHeaders: headers,
     cookiejar: cookieJar,
@@ -1211,12 +1211,12 @@ proc setEnvVars(pager: Pager) {.jsfunc.} =
 
 #TODO use default values instead...
 type ExternDict = object of JSDict
-  setenv: Opt[bool]
-  suspend: Opt[bool]
+  setenv: Option[bool]
+  suspend: Option[bool]
   wait: bool
 
 #TODO we should have versions with retval as int?
-proc extern(pager: Pager, cmd: string, t = ExternDict()): bool {.jsfunc.} =
+proc extern(pager: Pager; cmd: string; t = ExternDict()): bool {.jsfunc.} =
   if t.setenv.get(true):
     pager.setEnvVars()
   if t.suspend.get(true):
@@ -1236,7 +1236,7 @@ proc externInto(pager: Pager, cmd, ins: string): bool {.jsfunc.} =
   return runProcessInto(cmd, ins)
 
 proc externFilterSource(pager: Pager; cmd: string; c: Container = nil;
-    contentType = opt(string)) {.jsfunc.} =
+    contentType = none(string)) {.jsfunc.} =
   let fromc = if c != nil: c else: pager.container
   let fallback = pager.container.contentType.get("text/plain")
   let contentType = contentType.get(fallback)
diff --git a/src/server/buffer.nim b/src/server/buffer.nim
index fe2201e6..13a7ea20 100644
--- a/src/server/buffer.nim
+++ b/src/server/buffer.nim
@@ -1200,7 +1200,7 @@ proc serializeMultipartFormData(entries: seq[FormDataEntry]): FormData =
       let value = makeCRLF(entry.svalue)
       formData.append(name, value)
     else:
-      formData.append(name, entry.value, opt(entry.filename))
+      formData.append(name, entry.value, some(entry.filename))
   return formData
 
 proc serializePlainTextFormData(kvs: seq[(string, string)]): string =
@@ -1274,22 +1274,22 @@ proc submitForm(form: HTMLFormElement, submitter: Element): Option[Request] =
 
   template submitAsEntityBody() =
     var mimetype: string
-    var body: Opt[string]
-    var multipart: Opt[FormData]
+    var body: Option[string]
+    var multipart: Option[FormData]
     case enctype
     of FORM_ENCODING_TYPE_URLENCODED:
       #TODO with charset
       let kvlist = entrylist.toNameValuePairs()
-      body.ok(serializeApplicationXWWWFormUrlEncoded(kvlist))
+      body = some(serializeApplicationXWWWFormUrlEncoded(kvlist))
       mimeType = $enctype
     of FORM_ENCODING_TYPE_MULTIPART:
       #TODO with charset
-      multipart.ok(serializeMultipartFormData(entrylist))
+      multipart = some(serializeMultipartFormData(entrylist))
       mimetype = $enctype
     of FORM_ENCODING_TYPE_TEXT_PLAIN:
       #TODO with charset
       let kvlist = entrylist.toNameValuePairs()
-      body.ok(serializePlainTextFormData(kvlist))
+      body = some(serializePlainTextFormData(kvlist))
       mimetype = $enctype
     let req = newRequest(parsedaction, httpmethod, @{"Content-Type": mimetype},
       body, multipart)