about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-09-09 11:20:42 +0200
committerbptato <nincsnevem662@gmail.com>2023-09-09 11:20:42 +0200
commit07245ef4826298fffc3e34e34a74fdf77c7a4fac (patch)
tree7b0d0aa27da58ad7109fe69d51beed7a159f1aac /src
parent11219c7d21c8ec7f438d52de063c4ac25f84711d (diff)
downloadchawan-07245ef4826298fffc3e34e34a74fdf77c7a4fac.tar.gz
javascript: add JSDict type
And use that in extern().
Diffstat (limited to 'src')
-rw-r--r--src/display/pager.nim24
-rw-r--r--src/js/dict.nim5
-rw-r--r--src/js/fromjs.nim17
-rw-r--r--src/js/tojs.nim14
4 files changed, 46 insertions, 14 deletions
diff --git a/src/display/pager.nim b/src/display/pager.nim
index 0229c706..438f8763 100644
--- a/src/display/pager.nim
+++ b/src/display/pager.nim
@@ -28,6 +28,7 @@ import io/tempfile
 import io/window
 import ips/forkserver
 import ips/socketstream
+import js/dict
 import js/javascript
 import js/regex
 import js/tojs
@@ -839,25 +840,22 @@ proc setEnvVars(pager: Pager) {.jsfunc.} =
   except OSError:
     pager.alert("Warning: failed to set some environment variables")
 
-type ExternType = enum
-  SUSPEND_SETENV = "suspend-setenv"
-  SUSPEND_SETENV_WAIT = "suspend-setenv-wait"
-  SUSPEND_NO_SETENV = "suspend-no-setenv"
-  SUSPEND_NO_SETENV_WAIT = "suspend-no-setenv-wait"
-  NO_SUSPEND_SETENV = "no-suspend-setenv"
-  NO_SUSPEND_NO_SETENV = "no-suspend-no-setenv"
+#TODO use default values instead...
+type ExternDict = object of JSDict
+  setenv: Opt[bool]
+  suspend: Opt[bool]
+  wait: bool
 
 #TODO this could be handled much better.
 # * suspend, setenv, wait as dict flags
 # * retval as int?
-proc extern(pager: Pager, cmd: string, t = SUSPEND_SETENV): bool {.jsfunc.} =
-  if t in {SUSPEND_SETENV, SUSPEND_SETENV_WAIT, NO_SUSPEND_SETENV}:
+proc extern(pager: Pager, cmd: string, t = ExternDict()): bool {.jsfunc.} =
+  if t.setenv.get(true):
     pager.setEnvVars()
-  if t in {NO_SUSPEND_SETENV, NO_SUSPEND_NO_SETENV}:
-    return runProcess(cmd)
+  if t.suspend.get(true):
+    return runProcess(pager.term, cmd, t.wait)
   else:
-    return runProcess(pager.term, cmd,
-      t in {SUSPEND_SETENV_WAIT, SUSPEND_NO_SETENV_WAIT})
+    return runProcess(cmd)
 
 proc authorize(pager: Pager) =
   pager.setLineEdit("Username: ", USERNAME)
diff --git a/src/js/dict.nim b/src/js/dict.nim
new file mode 100644
index 00000000..5003b92c
--- /dev/null
+++ b/src/js/dict.nim
@@ -0,0 +1,5 @@
+# This is the WebIDL dictionary type.
+# We only use it for type inference in generics.
+#TODO required members
+
+type JSDict* = object of RootObj
diff --git a/src/js/fromjs.nim b/src/js/fromjs.nim
index 310550e4..701f0a60 100644
--- a/src/js/fromjs.nim
+++ b/src/js/fromjs.nim
@@ -5,6 +5,7 @@ import tables
 import unicode
 
 import bindings/quickjs
+import js/dict
 import js/error
 import js/opaque
 import js/tojs
@@ -403,7 +404,19 @@ proc fromJSVoid(ctx: JSContext, val: JSValue): JSResult[void] =
     return err()
   return ok()
 
-type FromJSAllowedT = (object and not (Result|Option|Table|JSValue))
+proc fromJSDict[T: JSDict](ctx: JSContext, val: JSValue): JSResult[T] =
+  if not JS_IsUndefined(val) and not JS_IsNull(val) and not JS_IsObject(val):
+    return err(newTypeError("Dictionary is not an object"))
+  #TODO throw on missing required values
+  var d: T
+  if JS_IsObject(val):
+    for k, v in d.fieldPairs:
+      let esm = JS_GetPropertyStr(ctx, val, k)
+      if not JS_IsUndefined(esm):
+        v = ?fromJS[typeof(v)](ctx, esm)
+  return ok(d)
+
+type FromJSAllowedT = (object and not (Result|Option|Table|JSValue|JSDict))
 
 proc fromJS*[T](ctx: JSContext, val: JSValue): JSResult[T] =
   when T is string:
@@ -441,6 +454,8 @@ proc fromJS*[T](ctx: JSContext, val: JSValue): JSResult[T] =
     return fromJSObject[T](ctx, val)
   elif T is void:
     return fromJSVoid(ctx, val)
+  elif T is JSDict:
+    return fromJSDict[T](ctx, val)
   elif compiles(fromJS2(ctx, val, result)):
     fromJS2(ctx, val, result)
   else:
diff --git a/src/js/tojs.nim b/src/js/tojs.nim
index ca38bd2b..cd4f2b86 100644
--- a/src/js/tojs.nim
+++ b/src/js/tojs.nim
@@ -4,6 +4,7 @@ import unicode
 
 import bindings/quickjs
 import io/promise
+import js/dict
 import js/error
 import js/opaque
 import js/typeptr
@@ -33,6 +34,7 @@ proc toJS*(ctx: JSContext, promise: EmptyPromise): JSValue
 proc toJS*(ctx: JSContext, obj: ref object): JSValue
 proc toJS*(ctx: JSContext, err: JSError): JSValue
 proc toJS*(ctx: JSContext, f: JSCFunction): JSValue
+proc toJS*(ctx: JSContext, d: JSDict): JSValue
 
 # Convert Nim types to the corresponding JavaScript type, with knowledge of
 # the parent object.
@@ -55,6 +57,7 @@ makeToJSP(Table)
 makeToJSP(Option)
 makeToJSP(Result)
 makeToJSP(JSValue)
+makeToJSP(JSDict)
 
 proc defineProperty(ctx: JSContext, this: JSValue, name: string,
     prop: JSValue, flags = cint(0)) =
@@ -254,6 +257,17 @@ proc toJS*(ctx: JSContext, err: JSError): JSValue =
 proc toJS*(ctx: JSContext, f: JSCFunction): JSValue =
   return JS_NewCFunction(ctx, f, cstring"", 0)
 
+proc toJS*(ctx: JSContext, d: JSDict): JSValue =
+  let obj = JS_NewObject(ctx)
+  if JS_IsException(obj):
+    return obj
+  for k, v in d.fieldPairs:
+    let val = toJS(ctx, v)
+    if JS_IsException(val):
+      return val
+    definePropertyCWE(ctx, obj, k, val)
+  return obj
+
 proc toJSP(ctx: JSContext, parent: ref object, child: var object): JSValue =
   let p = addr child
   # Save parent as the original ancestor for this tree.