about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/monoucha0/monoucha/javascript.nim16
-rw-r--r--lib/monoucha0/monoucha/tojs.nim90
-rw-r--r--src/config/config.nim8
-rw-r--r--src/html/dom.nim48
-rw-r--r--src/html/jsintl.nim2
-rw-r--r--src/html/script.nim9
-rw-r--r--src/local/client.nim4
7 files changed, 115 insertions, 62 deletions
diff --git a/lib/monoucha0/monoucha/javascript.nim b/lib/monoucha0/monoucha/javascript.nim
index 2a811ce6..14cd95eb 100644
--- a/lib/monoucha0/monoucha/javascript.nim
+++ b/lib/monoucha0/monoucha/javascript.nim
@@ -332,19 +332,19 @@ func newJSClass*(ctx: JSContext; cdef: JSClassDefConst; nimt: pointer;
   if cdef.exotic != nil and cdef.exotic.get_own_property != nil:
     let val = JS_DupValue(ctx, ctxOpaque.valRefs[jsvArrayPrototypeValues])
     let itSym = ctxOpaque.symRefs[jsyIterator]
-    ctx.defineProperty(proto, itSym, val)
+    doAssert ctx.defineProperty(proto, itSym, val) == dprSuccess
   let news = JS_NewAtomString(ctx, cdef.class_name)
   doAssert not JS_IsException(news)
-  ctx.definePropertyC(proto, ctxOpaque.symRefs[jsyToStringTag],
-    JS_DupValue(ctx, news))
+  doAssert ctx.definePropertyC(proto, ctxOpaque.symRefs[jsyToStringTag],
+    JS_DupValue(ctx, news)) == dprSuccess
   JS_SetClassProto(ctx, result, proto)
   ctx.addClassUnforgeable(proto, result, parent, unforgeable)
   if asglobal:
     let global = ctxOpaque.global
     assert ctxOpaque.gclass == 0
     ctxOpaque.gclass = result
-    ctx.definePropertyC(global, ctxOpaque.symRefs[jsyToStringTag],
-      JS_DupValue(ctx, news))
+    doAssert ctx.definePropertyC(global, ctxOpaque.symRefs[jsyToStringTag],
+      JS_DupValue(ctx, news)) == dprSuccess
     if JS_SetPrototype(ctx, global, proto) != 1:
       raise newException(Defect, "Failed to set global prototype: " &
         $cdef.class_name)
@@ -370,9 +370,11 @@ func newJSClass*(ctx: JSContext; cdef: JSClassDefConst; nimt: pointer;
   ctxOpaque.ctors[result] = JS_DupValue(ctx, jctor)
   if not nointerface:
     if JS_IsNull(namespace):
-      ctx.definePropertyCW(ctxOpaque.global, $cdef.class_name, jctor)
+      doAssert ctx.definePropertyCW(ctxOpaque.global, $cdef.class_name,
+        jctor) == dprSuccess
     else:
-      ctx.definePropertyCW(namespace, $cdef.class_name, jctor)
+      doAssert ctx.definePropertyCW(namespace, $cdef.class_name,
+        jctor) == dprSuccess
   else:
     JS_FreeValue(ctx, jctor)
 
diff --git a/lib/monoucha0/monoucha/tojs.nim b/lib/monoucha0/monoucha/tojs.nim
index 526b41fb..4ced6947 100644
--- a/lib/monoucha0/monoucha/tojs.nim
+++ b/lib/monoucha0/monoucha/tojs.nim
@@ -98,59 +98,66 @@ makeToJSP(Result)
 makeToJSP(JSValue)
 makeToJSP(JSDict)
 
+type DefinePropertyResult* = enum
+  dprException, dprSuccess, dprFail
+
 # Note: this consumes `prop'.
 proc defineProperty*(ctx: JSContext; this: JSValue; name: JSAtom;
-    prop: JSValue; flags = cint(0)) =
-  if JS_DefinePropertyValue(ctx, this, name, prop, flags) <= 0:
-    raise newException(Defect, "Failed to define property string")
+    prop: JSValue; flags = cint(0)): DefinePropertyResult =
+  return case JS_DefinePropertyValue(ctx, this, name, prop, flags)
+  of 0: dprFail
+  of 1: dprSuccess
+  else: dprException
 
 # Note: this consumes `prop'.
 proc defineProperty(ctx: JSContext; this: JSValue; name: int64;
-    prop: JSValue; flags = cint(0)) =
+    prop: JSValue; flags = cint(0)): DefinePropertyResult =
   let name = JS_NewInt64(ctx, name)
   let atom = JS_ValueToAtom(ctx, name)
   JS_FreeValue(ctx, name)
   if unlikely(atom == JS_ATOM_NULL):
-    raise newException(Defect, "Failed to define property string")
-  ctx.defineProperty(this, atom, prop, flags)
+    return dprException
+  result = ctx.defineProperty(this, atom, prop, flags)
   JS_FreeAtom(ctx, atom)
 
 proc definePropertyC*(ctx: JSContext; this: JSValue; name: JSAtom;
-    prop: JSValue) =
+    prop: JSValue): DefinePropertyResult =
   ctx.defineProperty(this, name, prop, JS_PROP_CONFIGURABLE)
 
 proc defineProperty(ctx: JSContext; this: JSValue; name: string;
-    prop: JSValue; flags = cint(0)) =
-  if JS_DefinePropertyValueStr(ctx, this, cstring(name), prop, flags) <= 0:
-    raise newException(Defect, "Failed to define property string: " & name)
+    prop: JSValue; flags = cint(0)): DefinePropertyResult =
+  return case JS_DefinePropertyValueStr(ctx, this, cstring(name), prop, flags)
+  of 0: dprFail
+  of 1: dprSuccess
+  else: dprException
 
 proc definePropertyC*(ctx: JSContext; this: JSValue; name: string;
-    prop: JSValue) =
+    prop: JSValue): DefinePropertyResult =
   ctx.defineProperty(this, name, prop, JS_PROP_CONFIGURABLE)
 
 proc defineProperty*[T](ctx: JSContext; this: JSValue; name: string; prop: T;
-    flags = cint(0)) =
-  defineProperty(ctx, this, name, toJS(ctx, prop), flags)
+    flags = cint(0)): DefinePropertyResult =
+  ctx.defineProperty(this, name, ctx.toJS(prop), flags)
 
 proc definePropertyE*[T](ctx: JSContext; this: JSValue; name: string;
-    prop: T) =
-  defineProperty(ctx, this, name, prop, JS_PROP_ENUMERABLE)
+    prop: T): DefinePropertyResult =
+  ctx.defineProperty(this, name, prop, JS_PROP_ENUMERABLE)
 
 proc definePropertyCW*[T](ctx: JSContext; this: JSValue; name: string;
-    prop: T) =
-  defineProperty(ctx, this, name, prop, JS_PROP_CONFIGURABLE or
+    prop: T): DefinePropertyResult =
+  ctx.defineProperty(this, name, prop, JS_PROP_CONFIGURABLE or
     JS_PROP_WRITABLE)
 
 proc definePropertyCWE*[T](ctx: JSContext; this: JSValue; name: string;
-    prop: T) =
-  defineProperty(ctx, this, name, prop, JS_PROP_C_W_E)
+    prop: T): DefinePropertyResult =
+  ctx.defineProperty(this, name, prop, JS_PROP_C_W_E)
 
 proc newFunction*(ctx: JSContext; args: openArray[string]; body: string):
     JSValue =
   var paramList: seq[JSValue] = @[]
   for arg in args:
-    paramList.add(toJS(ctx, arg))
-  paramList.add(toJS(ctx, body))
+    paramList.add(ctx.toJS(arg))
+  paramList.add(ctx.toJS(body))
   let fun = JS_CallConstructor(ctx, ctx.getOpaque().valRefs[jsvFunction],
     cint(paramList.len), paramList.toJSValueArray())
   for param in paramList:
@@ -171,9 +178,9 @@ proc toJS*(ctx: JSContext; n: int64): JSValue =
 
 proc toJS*(ctx: JSContext; n: int): JSValue =
   when sizeof(int) > 4:
-    return toJS(ctx, int64(n))
+    return ctx.toJS(int64(n))
   else:
-    return toJS(ctx, int32(n))
+    return ctx.toJS(int32(n))
 
 proc toJS*(ctx: JSContext; n: uint16): JSValue =
   return JS_NewUint32(ctx, uint32(n))
@@ -195,12 +202,16 @@ proc toJS*[U, V](ctx: JSContext; t: Table[U, V]): JSValue =
   let obj = JS_NewObject(ctx)
   if not JS_IsException(obj):
     for k, v in t:
-      definePropertyCWE(ctx, obj, k, v)
+      case ctx.definePropertyCWE(obj, k, v)
+      of dprException:
+        JS_FreeValue(ctx, obj)
+        return JS_EXCEPTION
+      else: discard
   return obj
 
 proc toJS*(ctx: JSContext; opt: Option): JSValue =
   if opt.isSome:
-    return toJS(ctx, opt.get)
+    return ctx.toJS(opt.get)
   return JS_NULL
 
 proc toJS*[T, E](ctx: JSContext; opt: Result[T, E]): JSValue =
@@ -222,17 +233,26 @@ proc toJS*(ctx: JSContext; s: seq): JSValue =
       let val = toJS(ctx, s[i])
       if JS_IsException(val):
         return val
-      ctx.defineProperty(a, int64(i), val, JS_PROP_C_W_E or JS_PROP_THROW)
+      case ctx.defineProperty(a, int64(i), val, JS_PROP_C_W_E or JS_PROP_THROW)
+      of dprException: return JS_EXCEPTION
+      else: discard
   return a
 
 proc toJS*[T](ctx: JSContext; s: set[T]): JSValue =
-  #TODO this is a bit lazy :p
-  var x = newSeq[T]()
-  for e in s:
-    x.add(e)
-  var a = toJS(ctx, x)
+  let a = JS_NewArray(ctx)
   if JS_IsException(a):
     return a
+  var i = 0i64
+  for e in s:
+    let val = ctx.toJS(e)
+    if JS_IsException(val):
+      return val
+    case ctx.defineProperty(a, i, val, JS_PROP_C_W_E or JS_PROP_THROW)
+    of dprException:
+      JS_FreeValue(ctx, a)
+      return JS_EXCEPTION
+    else: discard
+    inc i
   let ret = JS_CallConstructor(ctx, ctx.getOpaque().valRefs[jsvSet], 1,
     a.toJSValueArray())
   JS_FreeValue(ctx, a)
@@ -241,12 +261,16 @@ proc toJS*[T](ctx: JSContext; s: set[T]): JSValue =
 proc toJS(ctx: JSContext; t: tuple): JSValue =
   let a = JS_NewArray(ctx)
   if not JS_IsException(a):
-    var i = 0
+    var i = 0i64
     for f in t.fields:
       let val = toJS(ctx, f)
       if JS_IsException(val):
         return val
-      ctx.defineProperty(a, int64(i), val, JS_PROP_C_W_E or JS_PROP_THROW)
+      case ctx.defineProperty(a, i, val, JS_PROP_C_W_E or JS_PROP_THROW)
+      of dprException:
+        JS_FreeValue(ctx, a)
+        return JS_EXCEPTION
+      else: discard
       inc i
   return a
 
diff --git a/src/config/config.nim b/src/config/config.nim
index 3909e46c..0dbc6877 100644
--- a/src/config/config.nim
+++ b/src/config/config.nim
@@ -826,7 +826,9 @@ proc initCommands*(config: Config): Err[string] =
         var prop = JS_GetPropertyStr(ctx, objIt, cstring(ss))
         if JS_IsUndefined(prop):
           prop = JS_NewObject(ctx)
-          ctx.definePropertyE(objIt, ss, JS_DupValue(ctx, prop))
+          case ctx.definePropertyE(objIt, ss, JS_DupValue(ctx, prop))
+          of dprException: return err(ctx.getExceptionMsg())
+          else: discard
         if JS_IsException(prop):
           return err(ctx.getExceptionMsg())
         JS_FreeValue(ctx, objIt)
@@ -840,7 +842,9 @@ proc initCommands*(config: Config): Err[string] =
     if not JS_IsFunction(ctx, fun):
       JS_FreeValue(ctx, fun)
       return err(k & " is not a function")
-    ctx.definePropertyE(objIt, name, JS_DupValue(ctx, fun))
+    case ctx.definePropertyE(objIt, name, JS_DupValue(ctx, fun))
+    of dprException: return err(ctx.getExceptionMsg())
+    else: discard
     config.cmd.map[k] = fun
     JS_FreeValue(ctx, objIt)
   config.cmd.jsObj = JS_DupValue(ctx, obj)
diff --git a/src/html/dom.nim b/src/html/dom.nim
index b0e98d78..48d6655c 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -1476,7 +1476,11 @@ proc parentNodeChildrenImpl(ctx: JSContext; parentNode: Node): JSValue =
     childonly = true
   ))
   let this = ctx.toJS(parentNode)
-  ctx.definePropertyCW(this, "children", JS_DupValue(ctx, children))
+  case ctx.definePropertyCW(this, "children", JS_DupValue(ctx, children))
+  of dprException:
+    JS_FreeValue(ctx, this)
+    return JS_EXCEPTION
+  else: discard
   JS_FreeValue(ctx, this)
   return children
 
@@ -1497,7 +1501,11 @@ func childNodes(ctx: JSContext; node: Node): JSValue {.jsfget.} =
     childonly = true
   ))
   let this = ctx.toJS(node)
-  ctx.definePropertyCW(this, "childNodes", JS_DupValue(ctx, childNodes))
+  case ctx.definePropertyCW(this, "childNodes", JS_DupValue(ctx, childNodes))
+  of dprException:
+    JS_FreeValue(ctx, this)
+    return JS_EXCEPTION
+  else: discard
   JS_FreeValue(ctx, this)
   return childNodes
 
@@ -1849,10 +1857,12 @@ proc newLocation*(window: Window): Location =
   let location = Location(window: window)
   let ctx = window.jsctx
   if ctx != nil:
-    let val = toJS(ctx, location)
-    let valueOf = ctx.getOpaque().valRefs[jsvObjectPrototypeValueOf]
-    defineProperty(ctx, val, "valueOf", JS_DupValue(ctx, valueOf))
-    defineProperty(ctx, val, "toPrimitive", JS_UNDEFINED)
+    let val = ctx.toJS(location)
+    let valueOf0 = ctx.getOpaque().valRefs[jsvObjectPrototypeValueOf]
+    let valueOf = JS_DupValue(ctx, valueOf0)
+    doAssert ctx.defineProperty(val, "valueOf", valueOf) != dprException
+    doAssert ctx.defineProperty(val, "toPrimitive",
+      JS_UNDEFINED) != dprException
     #TODO [[DefaultProperties]]
     JS_FreeValue(ctx, val)
   return location
@@ -3318,8 +3328,12 @@ proc selectedOptions(ctx: JSContext; this: HTMLSelectElement): JSValue
     childonly = false
   ))
   let this = ctx.toJS(this)
-  ctx.definePropertyCW(this, "selectedOptions",
+  case ctx.definePropertyCW(this, "selectedOptions",
     JS_DupValue(ctx, selectedOptions))
+  of dprException:
+    JS_FreeValue(ctx, this)
+    return JS_EXCEPTION
+  else: discard
   JS_FreeValue(ctx, this)
   return selectedOptions
 
@@ -3441,7 +3455,11 @@ proc tBodies(ctx: JSContext; this: HTMLTableElement): JSValue {.jsfget.} =
     childonly = true
   ))
   let this = ctx.toJS(this)
-  ctx.definePropertyCW(this, "tBodies", JS_DupValue(ctx, tBodies))
+  case ctx.definePropertyCW(this, "tBodies", JS_DupValue(ctx, tBodies))
+  of dprException:
+    JS_FreeValue(ctx, this)
+    return JS_EXCEPTION
+  else: discard
   JS_FreeValue(ctx, this)
   return tBodies
 
@@ -3561,7 +3579,11 @@ proc cells(ctx: JSContext; this: HTMLTableRowElement): JSValue {.jsfget.} =
     childonly = true
   ))
   let this = ctx.toJS(this)
-  ctx.definePropertyCW(this, "cells", JS_DupValue(ctx, cells))
+  case ctx.definePropertyCW(this, "cells", JS_DupValue(ctx, cells))
+  of dprException:
+    JS_FreeValue(ctx, this)
+    return JS_EXCEPTION
+  else: discard
   JS_FreeValue(ctx, this)
   return cells
 
@@ -6207,10 +6229,10 @@ return option;
   doAssert JS_SetConstructorBit(ctx, imageFun, true)
   doAssert JS_SetConstructorBit(ctx, optionFun, true)
   let jsWindow = JS_GetGlobalObject(ctx)
-  ctx.definePropertyCW(jsWindow, "Image", imageFun)
-  ctx.definePropertyCW(jsWindow, "Option", optionFun)
-  ctx.definePropertyCW(jsWindow, "HTMLDocument",
-    JS_GetPropertyStr(ctx, jsWindow, "Document"))
+  doAssert ctx.definePropertyCW(jsWindow, "Image", imageFun) != dprException
+  doAssert ctx.definePropertyCW(jsWindow, "Option", optionFun) != dprException
+  doAssert ctx.definePropertyCW(jsWindow, "HTMLDocument",
+    JS_GetPropertyStr(ctx, jsWindow, "Document")) != dprException
   JS_FreeValue(ctx, jsWindow)
 
 # Forward declaration hack
diff --git a/src/html/jsintl.nim b/src/html/jsintl.nim
index 403c6311..c9260932 100644
--- a/src/html/jsintl.nim
+++ b/src/html/jsintl.nim
@@ -241,5 +241,5 @@ proc addIntlModule*(ctx: JSContext) =
   let intl = JS_NewObject(ctx)
   ctx.registerType(NumberFormat, namespace = intl)
   ctx.registerType(PluralRules, namespace = intl)
-  ctx.defineProperty(global, "Intl", intl)
+  doAssert ctx.defineProperty(global, "Intl", intl) != dprException
   JS_FreeValue(ctx, global)
diff --git a/src/html/script.nim b/src/html/script.nim
index 9eaa9d7e..d0a8e43a 100644
--- a/src/html/script.nim
+++ b/src/html/script.nim
@@ -147,8 +147,9 @@ proc setImportMeta*(ctx: JSContext; funcVal: JSValue; isMain: bool) =
   let m = cast[JSModuleDef](JS_VALUE_GET_PTR(funcVal))
   let moduleNameAtom = JS_GetModuleName(ctx, m)
   let metaObj = JS_GetImportMeta(ctx, m)
-  definePropertyCWE(ctx, metaObj, "url", JS_AtomToValue(ctx, moduleNameAtom))
-  definePropertyCWE(ctx, metaObj, "main", false)
+  doAssert ctx.definePropertyCWE(metaObj, "url",
+    JS_AtomToValue(ctx, moduleNameAtom)) == dprSuccess
+  doAssert ctx.definePropertyCWE(metaObj, "main", false) == dprSuccess
   JS_FreeValue(ctx, metaObj)
   JS_FreeAtom(ctx, moduleNameAtom)
 
@@ -181,8 +182,8 @@ proc defineConsts*(ctx: JSContext; classid: JSClassID; consts: typedesc[enum]) =
   # it isn't...
   for e in consts:
     let s = $e
-    ctx.definePropertyE(proto, s, uint16(e))
-    ctx.definePropertyE(ctor, s, uint16(e))
+    doAssert ctx.definePropertyE(proto, s, uint16(e)) == dprSuccess
+    doAssert ctx.definePropertyE(ctor, s, uint16(e)) == dprSuccess
   JS_FreeValue(ctx, proto)
 
 proc identity(ctx: JSContext; this_val: JSValue; argc: cint;
diff --git a/src/local/client.nim b/src/local/client.nim
index 74472e75..e19a646a 100644
--- a/src/local/client.nim
+++ b/src/local/client.nim
@@ -173,9 +173,9 @@ proc newClient*(config: Config; forkserver: ForkServer; loaderPid: int;
   )
   client.attrsp = addr client.pager.term.attrs
   client.timeouts = client.pager.timeouts
-  let global = JS_GetGlobalObject(jsctx)
   jsctx.setGlobal(client)
-  jsctx.definePropertyE(global, "cmd", config.cmd.jsObj)
+  let global = JS_GetGlobalObject(jsctx)
+  doAssert jsctx.definePropertyE(global, "cmd", config.cmd.jsObj) != dprException
   JS_FreeValue(jsctx, global)
   config.cmd.jsObj = JS_NULL
   let windowCID = client.addJSModules(jsctx)