about summary refs log tree commit diff stats
path: root/lib/monoucha0
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2025-02-19 18:54:44 +0100
committerbptato <nincsnevem662@gmail.com>2025-02-19 19:35:07 +0100
commit3f663454031657610bddceb169cd881754ec232a (patch)
treeae088232c3bdbe9f74cfaf19a5d9b99e0dfc8131 /lib/monoucha0
parentb65993b77789ddbde72f65db648ab993a5097121 (diff)
downloadchawan-3f663454031657610bddceb169cd881754ec232a.tar.gz
fromjs, javascript: optimize out class name registry
Instead of hashing the class name for isInstanceOf, we now just reuse
the Nim type pointer -> JSClassID map, which should be more efficient.

This removes getClass and hasClass; these can be replaced by just
reusing the class ID returned from registerType.
Diffstat (limited to 'lib/monoucha0')
-rw-r--r--lib/monoucha0/monoucha/fromjs.nim27
-rw-r--r--lib/monoucha0/monoucha/javascript.nim21
-rw-r--r--lib/monoucha0/monoucha/jsopaque.nim1
3 files changed, 21 insertions, 28 deletions
diff --git a/lib/monoucha0/monoucha/fromjs.nim b/lib/monoucha0/monoucha/fromjs.nim
index 7cf5db9a..ece36119 100644
--- a/lib/monoucha0/monoucha/fromjs.nim
+++ b/lib/monoucha0/monoucha/fromjs.nim
@@ -7,6 +7,7 @@ import jsopaque
 import jstypes
 import optshim
 import quickjs
+import tojs
 
 proc fromJS*(ctx: JSContext; val: JSValue; res: out string): Opt[void]
 proc fromJS*(ctx: JSContext; val: JSValue; res: out int32): Opt[void]
@@ -31,10 +32,9 @@ proc fromJS*(ctx: JSContext; val: JSValue; res: out JSArrayBufferView):
   Opt[void]
 proc fromJS*(ctx: JSContext; val: JSValue; res: out JSValue): Opt[void]
 
-func isInstanceOf*(ctx: JSContext; val: JSValue; class: cstring): bool =
+func isInstanceOf*(ctx: JSContext; val: JSValue; tclassid: JSClassID): bool =
   let ctxOpaque = ctx.getOpaque()
   var classid = JS_GetClassID(val)
-  let tclassid = ctxOpaque.creg.getOrDefault(class, JS_CLASS_OBJECT)
   if classid == JS_CLASS_OBJECT:
     let p0 = JS_VALUE_GET_PTR(ctxOpaque.global)
     let p1 = JS_VALUE_GET_PTR(val)
@@ -328,7 +328,7 @@ proc fromJS*[T: enum](ctx: JSContext; val: JSValue; res: out T): Opt[void] =
   res = default(T)
   return err()
 
-proc fromJS(ctx: JSContext; val: JSValue; t: cstring; res: out pointer):
+proc fromJS(ctx: JSContext; val: JSValue; nimt: pointer; res: out pointer):
     Opt[void] =
   if not JS_IsObject(val):
     if not JS_IsException(val):
@@ -336,25 +336,34 @@ proc fromJS(ctx: JSContext; val: JSValue; t: cstring; res: out pointer):
     res = nil
     return err()
   let p = JS_GetOpaque(val, JS_GetClassID(val))
-  if p == nil or not ctx.isInstanceOf(val, t):
-    JS_ThrowTypeError(ctx, "%s expected", t)
+  let ctxOpaque = ctx.getOpaque()
+  let tclassid = ctxOpaque.typemap.getOrDefault(nimt, JS_CLASS_OBJECT)
+  if p == nil or not ctx.isInstanceOf(val, tclassid):
     res = nil
+    let proto = JS_GetClassProto(ctx, tclassid)
+    let name = JS_GetProperty(ctx, proto, ctxOpaque.symRefs[jsyToStringTag])
+    JS_FreeValue(ctx, proto)
+    defer: JS_FreeValue(ctx, name)
+    var s: string
+    if ctx.fromJS(name, s).isNone:
+      return err()
+    JS_ThrowTypeError(ctx, "%s expected", cstring(s))
     return err()
   res = p
   return ok()
 
 proc fromJS*[T](ctx: JSContext; val: JSValue; res: out ptr T): Opt[void] =
+  let nimt = getTypePtr(T)
   var x: pointer
-  const tname = cstring($T)
-  ?ctx.fromJS(val, tname, x)
+  ?ctx.fromJS(val, nimt, x)
   res = cast[ptr T](x)
   return ok()
 
 proc fromJS*[T: ref object](ctx: JSContext; val: JSValue; res: out T):
     Opt[void] =
+  let nimt = getTypePtr(T)
   var x: pointer
-  const tname = cstring($T)
-  ?ctx.fromJS(val, tname, x)
+  ?ctx.fromJS(val, nimt, x)
   res = cast[T](x)
   return ok()
 
diff --git a/lib/monoucha0/monoucha/javascript.nim b/lib/monoucha0/monoucha/javascript.nim
index 75b1548a..1f921d5d 100644
--- a/lib/monoucha0/monoucha/javascript.nim
+++ b/lib/monoucha0/monoucha/javascript.nim
@@ -191,19 +191,6 @@ proc newJSContext*(rt: JSRuntime): JSContext =
   JS_SetContextOpaque(ctx, cast[pointer](opaque))
   return ctx
 
-func getClass*(ctx: JSContext; class: cstring): JSClassID =
-  ## Get the class ID of the registered class `class'.
-  ## Note: this uses the Nim type's name, **not** the JS type's name.
-  try:
-    return ctx.getOpaque().creg[class]
-  except KeyError:
-    raise newException(Defect, "Class does not exist")
-
-func hasClass*(ctx: JSContext; class: cstring): bool =
-  ## Check if `class' is registered.
-  ## Note: this uses the Nim type's name, **not** the JS type's name.
-  return class in ctx.getOpaque().creg
-
 proc free*(ctx: JSContext) =
   ## Free the JSContext and associated resources.
   ## Note: this is not an alias of `JS_FreeContext`; `free` also frees various
@@ -311,8 +298,8 @@ proc newCtorFunFromParentClass(ctx: JSContext; ctor: JSCFunction;
       0, ctx.getOpaque().ctors[parent])
   return JS_NewCFunction2(ctx, ctor, className, 0, JS_CFUNC_constructor, 0)
 
-func newJSClass*(ctx: JSContext; cdef: JSClassDefConst; tname: cstring;
-    nimt: pointer; ctor: JSCFunction; funcs: JSFunctionList; parent: JSClassID;
+func newJSClass*(ctx: JSContext; cdef: JSClassDefConst; nimt: pointer;
+    ctor: JSCFunction; funcs: JSFunctionList; parent: JSClassID;
     asglobal, nointerface, ishtmldda: bool; finalizer: JSFinalizerFunction;
     namespace: JSValue; errid: Opt[JSErrorEnum];
     unforgeable, staticfuns: JSFunctionList): JSClassID
@@ -327,7 +314,6 @@ func newJSClass*(ctx: JSContext; cdef: JSClassDefConst; tname: cstring;
       $cdef.class_name)
   ctxOpaque.typemap[nimt] = result
   rtOpaque.inverseTypemap[result] = nimt
-  ctxOpaque.creg[tname] = result
   if ctxOpaque.parents.len <= int(result):
     ctxOpaque.parents.setLen(int(result) + 1)
   ctxOpaque.parents[result] = parent
@@ -1509,12 +1495,11 @@ macro registerType*(ctx: JSContext; t: typed; parent: JSClassID = 0;
   endstmts.bindEndStmts(info)
   let tabList = info.tabList
   let finName = info.finName
-  let tname = info.tname
   let unforgeable = info.tabUnforgeable
   let staticfuns = info.tabStatic
   let global = asglobal and not globalparent
   endstmts.add(quote do:
-    `ctx`.newJSClass(classDef, `tname`, getTypePtr(`t`), `sctr`, `tabList`,
+    `ctx`.newJSClass(classDef, getTypePtr(`t`), `sctr`, `tabList`,
       `parent`, `global`, `nointerface`, `ishtmldda`, `finName`, `namespace`,
       `errid`, `unforgeable`, `staticfuns`)
   )
diff --git a/lib/monoucha0/monoucha/jsopaque.nim b/lib/monoucha0/monoucha/jsopaque.nim
index 7b90329a..e7920ea2 100644
--- a/lib/monoucha0/monoucha/jsopaque.nim
+++ b/lib/monoucha0/monoucha/jsopaque.nim
@@ -27,7 +27,6 @@ type
     jsvFunction = "Function"
 
   JSContextOpaque* = ref object
-    creg*: Table[cstring, JSClassID]
     typemap*: Table[pointer, JSClassID]
     ctors*: seq[JSValue] # JSClassID -> JSValue
     parents*: seq[JSClassID] # JSClassID -> JSClassID