about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-05-12 12:42:15 +0200
committerbptato <nincsnevem662@gmail.com>2024-05-12 12:45:49 +0200
commit53079a080291889428071700f8c0919f84132534 (patch)
tree95cfcde7ed6a043ac3d0f38e7ad789ee074fb19d /src
parent911ec9a85fc7b773fcea4b005d926702020a551f (diff)
downloadchawan-53079a080291889428071700f8c0919f84132534.tar.gz
js: allow var instead of ptr
Diffstat (limited to 'src')
-rw-r--r--src/config/config.nim30
-rw-r--r--src/html/dom.nim40
-rw-r--r--src/html/env.nim66
-rw-r--r--src/js/fromjs.nim3
-rw-r--r--src/js/javascript.nim55
5 files changed, 100 insertions, 94 deletions
diff --git a/src/config/config.nim b/src/config/config.nim
index 2e71a27d..872f0440 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -227,45 +227,45 @@ func getRealKey(key: string): string =
     realk &= '\\'
   return realk
 
-proc getter(a: ptr ActionMap; s: string): Option[string] {.jsgetprop.} =
+proc getter(a: var ActionMap; s: string): Option[string] {.jsgetprop.} =
   a.t.withValue(s, p):
     return some(p[])
   return none(string)
 
-proc setter(a: ptr ActionMap; k, v: string) {.jssetprop.} =
+proc setter(a: var ActionMap; k, v: string) {.jssetprop.} =
   let k = getRealKey(k)
   if k == "":
     return
-  a[][k] = v
+  a[k] = v
   var teststr = k
   teststr.setLen(teststr.high)
   for i in countdown(k.high, 0):
-    if teststr notin a[]:
-      a[][teststr] = "client.feedNext()"
+    if teststr notin a:
+      a[teststr] = "client.feedNext()"
     teststr.setLen(i)
 
-proc delete(a: ptr ActionMap; k: string): bool {.jsdelprop.} =
+proc delete(a: var ActionMap; k: string): bool {.jsdelprop.} =
   let k = getRealKey(k)
-  let ina = k in a[]
-  a[].t.del(k)
+  let ina = k in a
+  a.t.del(k)
   return ina
 
-func names(ctx: JSContext; a: ptr ActionMap): JSPropertyEnumList
+func names(ctx: JSContext; a: var ActionMap): JSPropertyEnumList
     {.jspropnames.} =
-  let L = uint32(a[].t.len)
+  let L = uint32(a.t.len)
   var list = newJSPropertyEnumList(ctx, L)
-  for key in a[].t.keys:
+  for key in a.t.keys:
     list.add(key)
   return list
 
 proc bindPagerKey(config: Config; key, action: string) {.jsfunc.} =
-  (addr config.page).setter(key, action)
+  config.page.setter(key, action)
 
 proc bindLineKey(config: Config; key, action: string) {.jsfunc.} =
-  (addr config.line).setter(key, action)
+  config.line.setter(key, action)
 
-proc hasprop(a: ptr ActionMap; s: string): bool {.jshasprop.} =
-  return s in a[]
+proc hasprop(a: var ActionMap; s: string): bool {.jshasprop.} =
+  return s in a
 
 proc openFileExpand(dir, file: string): FileStream =
   if file.len == 0:
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 3e93de79..2293db90 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -1307,26 +1307,26 @@ func validateAttributeQName(name: string): Err[DOMException] =
   return errDOMException("Invalid character in attribute name",
     "InvalidCharacterError")
 
-func hasprop(map: ptr DOMStringMap; name: string): bool {.jshasprop.} =
-  let name = map[].target.document.toAtom("data-" & name)
-  return map[].target.attrb(name)
+func hasprop(map: var DOMStringMap; name: string): bool {.jshasprop.} =
+  let name = map.target.document.toAtom("data-" & name)
+  return map.target.attrb(name)
 
-proc delete(map: ptr DOMStringMap; name: string): bool {.jsfunc.} =
-  let name = map[].target.document.toAtom("data-" & name.camelToKebabCase())
-  let i = map[].target.findAttr(name)
+proc delete(map: var DOMStringMap; name: string): bool {.jsfunc.} =
+  let name = map.target.document.toAtom("data-" & name.camelToKebabCase())
+  let i = map.target.findAttr(name)
   if i != -1:
-    map[].target.delAttr(i)
+    map.target.delAttr(i)
   return i != -1
 
-func getter(map: ptr DOMStringMap; name: string): Option[string]
+func getter(map: var DOMStringMap; name: string): Option[string]
     {.jsgetprop.} =
-  let name = map[].target.document.toAtom("data-" & name.camelToKebabCase())
-  let i = map[].target.findAttr(name)
+  let name = map.target.document.toAtom("data-" & name.camelToKebabCase())
+  let i = map.target.findAttr(name)
   if i != -1:
-    return some(map[].target.attrs[i].value)
+    return some(map.target.attrs[i].value)
   return none(string)
 
-proc setter(map: ptr DOMStringMap; name, value: string): Err[DOMException]
+proc setter(map: var DOMStringMap; name, value: string): Err[DOMException]
     {.jssetprop.} =
   var washy = false
   for c in name:
@@ -1337,15 +1337,15 @@ proc setter(map: ptr DOMStringMap; name, value: string): Err[DOMException]
       "InvalidCharacterError")
   let name = "data-" & name.camelToKebabCase()
   ?name.validateAttributeName()
-  let aname = map[].target.document.toAtom(name)
+  let aname = map.target.document.toAtom(name)
   map.target.attr(aname, value)
   return ok()
 
-func names(ctx: JSContext; map: ptr DOMStringMap): JSPropertyEnumList
+func names(ctx: JSContext; map: var DOMStringMap): JSPropertyEnumList
     {.jspropnames.} =
-  var list = newJSPropertyEnumList(ctx, uint32(map[].target.attrs.len))
-  for attr in map[].target.attrs:
-    let k = map[].target.document.toStr(attr.localName)
+  var list = newJSPropertyEnumList(ctx, uint32(map.target.attrs.len))
+  for attr in map.target.attrs:
+    let k = map.target.document.toStr(attr.localName)
     if k.startsWith("data-") and AsciiUpperAlpha notin k:
       list.add(k["data-".len .. ^1].kebabToCamelCase())
   return list
@@ -3845,7 +3845,7 @@ proc createElement(document: Document; localName: string):
 proc createDocumentFragment(document: Document): DocumentFragment {.jsfunc.} =
   return newDocumentFragment(document)
 
-proc createDocumentType(implementation: ptr DOMImplementation; qualifiedName,
+proc createDocumentType(implementation: var DOMImplementation; qualifiedName,
     publicId, systemId: string): DOMResult[DocumentType] {.jsfunc.} =
   if not qualifiedName.matchQNameProduction():
     return errDOMException("Invalid character in document type name",
@@ -3853,7 +3853,7 @@ proc createDocumentType(implementation: ptr DOMImplementation; qualifiedName,
   let document = implementation.document
   return ok(document.newDocumentType(qualifiedName, publicId, systemId))
 
-proc createHTMLDocument(ctx: JSContext; implementation: ptr DOMImplementation;
+proc createHTMLDocument(ctx: JSContext; implementation: var DOMImplementation;
     title = none(string)): Document {.jsfunc.} =
   let doc = newDocument(ctx)
   doc.contentType = "text/html"
@@ -3870,7 +3870,7 @@ proc createHTMLDocument(ctx: JSContext; implementation: ptr DOMImplementation;
   #TODO set origin
   return doc
 
-proc hasFeature(implementation: ptr DOMImplementation): bool {.jsfunc.} =
+proc hasFeature(implementation: var DOMImplementation): bool {.jsfunc.} =
   return true
 
 proc createCDATASection(document: Document; data: string):
diff --git a/src/html/env.nim b/src/html/env.nim
index ef4b4658..dc63f790 100644
--- a/src/html/env.nim
+++ b/src/html/env.nim
@@ -29,27 +29,27 @@ import types/url
 import types/winattrs
 
 # NavigatorID
-proc appCodeName(navigator: ptr Navigator): string {.jsfget.} = "Mozilla"
-proc appName(navigator: ptr Navigator): string {.jsfget.} = "Netscape"
-proc appVersion(navigator: ptr Navigator): string {.jsfget.} = "5.0 (Windows)"
-proc platform(navigator: ptr Navigator): string {.jsfget.} = "Win32"
-proc product(navigator: ptr Navigator): string {.jsfget.} = "Gecko"
-proc productSub(navigator: ptr Navigator): string {.jsfget.} = "20100101"
-proc userAgent(navigator: ptr Navigator): string {.jsfget.} =
+proc appCodeName(navigator: var Navigator): string {.jsfget.} = "Mozilla"
+proc appName(navigator: var Navigator): string {.jsfget.} = "Netscape"
+proc appVersion(navigator: var Navigator): string {.jsfget.} = "5.0 (Windows)"
+proc platform(navigator: var Navigator): string {.jsfget.} = "Win32"
+proc product(navigator: var Navigator): string {.jsfget.} = "Gecko"
+proc productSub(navigator: var Navigator): string {.jsfget.} = "20100101"
+proc userAgent(navigator: var Navigator): string {.jsfget.} =
   #TODO TODO TODO this should be configurable
   "chawan"
-proc vendor(navigator: ptr Navigator): string {.jsfget.} = ""
-proc vendorSub(navigator: ptr Navigator): string {.jsfget.} = ""
-proc taintEnabled(navigator: ptr Navigator): bool {.jsfget.} = false
-proc oscpu(navigator: ptr Navigator): string {.jsfget.} = "Windows NT 10.0"
+proc vendor(navigator: var Navigator): string {.jsfget.} = ""
+proc vendorSub(navigator: var Navigator): string {.jsfget.} = ""
+proc taintEnabled(navigator: var Navigator): bool {.jsfget.} = false
+proc oscpu(navigator: var Navigator): string {.jsfget.} = "Windows NT 10.0"
 
 # NavigatorLanguage
-proc language(navigator: ptr Navigator): string {.jsfget.} = "en-US"
-proc languages(navigator: ptr Navigator): seq[string] {.jsfget.} =
+proc language(navigator: var Navigator): string {.jsfget.} = "en-US"
+proc languages(navigator: var Navigator): seq[string] {.jsfget.} =
   @["en-US"] #TODO frozen array?
 
 # NavigatorOnline
-proc onLine(navigator: ptr Navigator): bool {.jsfget.} =
+proc onLine(navigator: var Navigator): bool {.jsfget.} =
   true # at the very least, the terminal is on-line :)
 
 #TODO NavigatorContentUtils
@@ -57,39 +57,39 @@ proc onLine(navigator: ptr Navigator): bool {.jsfget.} =
 # NavigatorCookies
 # "this website needs cookies to be enabled to function correctly"
 # It's probably better to lie here.
-proc cookieEnabled(navigator: ptr Navigator): bool {.jsfget.} = true
+proc cookieEnabled(navigator: var Navigator): bool {.jsfget.} = true
 
 # NavigatorPlugins
-proc pdfViewerEnabled(navigator: ptr Navigator): bool {.jsfget.} = false
-proc javaEnabled(navigator: ptr Navigator): bool {.jsfunc.} = false
-proc namedItem(pluginArray: ptr PluginArray): string {.jsfunc.} = ""
-proc namedItem(mimeTypeArray: ptr MimeTypeArray): string {.jsfunc.} = ""
-proc item(pluginArray: ptr PluginArray): JSValue {.jsfunc.} = JS_NULL
-proc length(pluginArray: ptr PluginArray): uint32 {.jsfget.} = 0
-proc item(mimeTypeArray: ptr MimeTypeArray): JSValue {.jsfunc.} = JS_NULL
-proc length(mimeTypeArray: ptr MimeTypeArray): uint32 {.jsfget.} = 0
-proc getter(pluginArray: ptr PluginArray; i: uint32): Option[JSValue]
+proc pdfViewerEnabled(navigator: var Navigator): bool {.jsfget.} = false
+proc javaEnabled(navigator: var Navigator): bool {.jsfunc.} = false
+proc namedItem(pluginArray: var PluginArray): string {.jsfunc.} = ""
+proc namedItem(mimeTypeArray: var MimeTypeArray): string {.jsfunc.} = ""
+proc item(pluginArray: var PluginArray): JSValue {.jsfunc.} = JS_NULL
+proc length(pluginArray: var PluginArray): uint32 {.jsfget.} = 0
+proc item(mimeTypeArray: var MimeTypeArray): JSValue {.jsfunc.} = JS_NULL
+proc length(mimeTypeArray: var MimeTypeArray): uint32 {.jsfget.} = 0
+proc getter(pluginArray: var PluginArray; i: uint32): Option[JSValue]
     {.jsgetprop.} =
   discard
-proc getter(mimeTypeArray: ptr MimeTypeArray; i: uint32): Option[JSValue]
+proc getter(mimeTypeArray: var MimeTypeArray; i: uint32): Option[JSValue]
     {.jsgetprop.} =
   discard
 
 # Screen
-proc availWidth(screen: ptr Screen): int64 {.jsfget.} =
+proc availWidth(screen: var Screen): int64 {.jsfget.} =
   #TODO this is a fingerprinting vector, but users should be able to allow it
   # selectively
   # for now just return something standard-ish
   80 * 9
-proc availHeight(screen: ptr Screen): int64 {.jsfget.} =
+proc availHeight(screen: var Screen): int64 {.jsfget.} =
   #TODO see above
   24 * 18
-proc width(screen: ptr Screen): int64 {.jsfget.} =
+proc width(screen: var Screen): int64 {.jsfget.} =
   screen.availWidth
-proc height(screen: ptr Screen): int64 {.jsfget.} =
+proc height(screen: var Screen): int64 {.jsfget.} =
   screen.availHeight
-proc colorDepth(screen: ptr Screen): int64 {.jsfget.} = 24
-proc pixelDepth(screen: ptr Screen): int64 {.jsfget.} = screen.colorDepth
+proc colorDepth(screen: var Screen): int64 {.jsfget.} = 24
+proc pixelDepth(screen: var Screen): int64 {.jsfget.} = screen.colorDepth
 
 proc addNavigatorModule(ctx: JSContext) =
   ctx.registerType(Navigator)
@@ -122,9 +122,9 @@ proc screenY(window: Window): int64 {.jsfget.} = 0
 proc screenLeft(window: Window): int64 {.jsfget.} = 0
 proc screenTop(window: Window): int64 {.jsfget.} = 0
 proc outerWidth(window: Window): int64 {.jsfget.} =
-  (addr window.screen).availWidth
+  window.screen.availWidth
 proc outerHeight(window: Window): int64 {.jsfget.} =
-  (addr window.screen).availHeight
+  window.screen.availHeight
 proc devicePixelRatio(window: Window): float64 {.jsfget.} = 1
 
 proc setLocation(window: Window; s: string): Err[JSError]
diff --git a/src/js/fromjs.nim b/src/js/fromjs.nim
index ccf8abcb..055ae19e 100644
--- a/src/js/fromjs.nim
+++ b/src/js/fromjs.nim
@@ -98,6 +98,9 @@ func fromJSInt[T: SomeInteger](ctx: JSContext; val: JSValue):
     if JS_ToUint32(ctx, addr ret, val) < 0:
       return err()
     return ok(ret)
+  else:
+    static:
+      error($T & " cannot be converted to JS automatically")
 
 proc fromJSFloat64(ctx: JSContext; val: JSValue): JSResult[float64] =
   var f64: float64
diff --git a/src/js/javascript.nim b/src/js/javascript.nim
index 2427b6a8..bfe45aae 100644
--- a/src/js/javascript.nim
+++ b/src/js/javascript.nim
@@ -334,6 +334,7 @@ type FuncParam = tuple
   t: NimNode
   val: Option[NimNode]
   generic: Option[NimNode]
+  isptr: bool
 
 func getMinArgs(params: seq[FuncParam]): int =
   for i in 0..<params.len:
@@ -447,7 +448,8 @@ proc getParams(fun: NimNode): seq[FuncParam] =
         typeof(`x`)
     else:
       error("?? " & treeRepr(it))
-    if t.kind in {nnkRefTy, nnkPtrTy}:
+    let isptr = t.kind == nnkVarTy
+    if t.kind in {nnkRefTy, nnkVarTy}:
       t = t[0]
     let val = if it[^1].kind != nnkEmpty:
       let x = it[^1]
@@ -457,7 +459,7 @@ proc getParams(fun: NimNode): seq[FuncParam] =
     var g = none(NimNode)
     for i in 0 ..< it.len - 2:
       let name = $it[i]
-      funcParams.add((name, t, val, g))
+      funcParams.add((name, t, val, g, isptr))
   funcParams
 
 proc getReturn(fun: NimNode): Option[NimNode] =
@@ -716,46 +718,46 @@ proc addUnionParam(gen: var JSFuncGenerator; tt, s: NimNode;
   gen.addUnionParam0(tt, s, quote do: argv[`j`], fallback)
 
 proc addFixParam(gen: var JSFuncGenerator; name: string) =
-  let s = ident("arg_" & $gen.i)
-  let t = gen.funcParams[gen.i][1]
+  var s = ident("arg_" & $gen.i)
+  let t = gen.funcParams[gen.i].t
   let id = ident(name)
   if t.typeKind == ntyGenericParam:
     gen.addUnionParam0(t, s, id)
   else:
     gen.addParam2(s, t, id)
-  if gen.jsFunCall != nil:
-    gen.jsFunCall.add(s)
+  if gen.funcParams[gen.i].isptr:
+    s = quote do: `s`[]
+  gen.jsFunCall.add(s)
   inc gen.i
 
 proc addRequiredParams(gen: var JSFuncGenerator) =
   while gen.i < gen.minArgs:
-    let s = ident("arg_" & $gen.i)
-    let tt = gen.funcParams[gen.i][1]
+    var s = ident("arg_" & $gen.i)
+    let tt = gen.funcParams[gen.i].t
     if tt.typeKind == ntyGenericParam:
       gen.addUnionParam(tt, s)
     else:
       gen.addValueParam(s, tt)
-    if gen.jsFunCall != nil:
-      gen.jsFunCall.add(s)
+    if gen.funcParams[gen.i].isptr:
+      s = quote do: `s`[]
+    gen.jsFunCall.add(s)
     inc gen.j
     inc gen.i
 
 proc addOptionalParams(gen: var JSFuncGenerator) =
   while gen.i < gen.funcParams.len:
     let j = gen.j
-    let s = ident("arg_" & $gen.i)
-    let tt = gen.funcParams[gen.i][1]
+    var s = ident("arg_" & $gen.i)
+    let tt = gen.funcParams[gen.i].t
     if tt.typeKind == varargs.getType().typeKind: # pray it's not a generic...
       let vt = tt[1].getType()
       for i in 0..gen.jsFunCallLists.high:
         gen.jsFunCallLists[i].add(newLetStmt(s, quote do:
-          (
-            var valist: seq[`vt`]
-            for i in `j`..<argc:
-              let it = fromJS_or_return(`vt`, ctx, argv[i])
-              valist.add(it)
-            valist
-          )
+          var valist: seq[`vt`] = @[]
+          for i in `j`..<argc:
+            let it = fromJS_or_return(`vt`, ctx, argv[i])
+            valist.add(it)
+          valist
         ))
     else:
       if gen.funcParams[gen.i][2].isNone:
@@ -766,8 +768,9 @@ proc addOptionalParams(gen: var JSFuncGenerator) =
         gen.addUnionParam(tt, s, fallback)
       else:
         gen.addValueParam(s, tt, fallback)
-    if gen.jsFunCall != nil:
-      gen.jsFunCall.add(s)
+    if gen.funcParams[gen.i].isptr:
+      s = quote do: `s`[]
+    gen.jsFunCall.add(s)
     inc gen.j
     inc gen.i
 
@@ -868,8 +871,8 @@ proc addJSContext(gen: var JSFuncGenerator) =
 
 proc addThisName(gen: var JSFuncGenerator; thisname: Option[string]) =
   if thisname.isSome:
-    gen.thisTypeNode = gen.funcParams[gen.i][1]
-    gen.thisType = $gen.funcParams[gen.i][1]
+    gen.thisTypeNode = gen.funcParams[gen.i].t
+    gen.thisType = $gen.funcParams[gen.i].t
     gen.newName = ident($gen.t & "_" & gen.thisType & "_" & gen.funcName)
   else:
     let rt = gen.returnType.get
@@ -1597,9 +1600,9 @@ proc bindEndStmts(endstmts: NimNode; info: RegistryInfo) =
       )
       let `classDef` = JSClassDefConst(addr cd))
 
-macro registerType*(ctx: typed; t: typed; parent: JSClassID = 0;
-    asglobal: static bool = false; nointerface = false; name: static string = "";
-    has_extra_getset: static bool = false;
+macro registerType*(ctx: JSContext; t: typed; parent: JSClassID = 0;
+    asglobal: static bool = false; nointerface = false;
+    name: static string = ""; has_extra_getset: static bool = false;
     extra_getset: static openArray[TabGetSet] = []; namespace = JS_NULL;
     errid = opt(JSErrorEnum); ishtmldda = false): JSClassID =
   var stmts = newStmtList()