Skip to content

Commit 750c344

Browse files
committed
Externrefs typerel
1 parent 06a0b1b commit 750c344

File tree

2 files changed

+66
-18
lines changed

2 files changed

+66
-18
lines changed

tests/t_import.nim

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,21 @@ block:
5858
doAssert(myJSObject().someFunc(1, 2) == 3)
5959
myJSObject().someProp = "hi"
6060
doAssert(myJSObject().someProp == "hi")
61+
62+
proc foo() =
63+
let j = myJSObject()
64+
doAssert(j.someProp == "hi")
65+
let jo: JSObj = myJSObject()
66+
doAssert(jo.someProp == "hi")
67+
foo()
68+
6169
block:
6270
proc getNull(): JSObj {.importwasmexpr: "null".}
6371
doAssert(getNull() == nil)
6472
doAssert(nil == getNull())
6573
var j: JSObj = getNull()
6674
doAssert(j.isNil)
67-
75+
6876

6977
block: # Callback
7078
proc setCallbackAux(t: int, c: proc(a: int) {.cdecl.}) {.importwasmraw: """
@@ -158,15 +166,36 @@ block: # Callback with nil env
158166

159167
main()
160168

161-
# block:
162-
# # Custom types
163-
# type
164-
# HTMLElement = object of JSObj
165-
# Canvas = object of HTMLElement
166-
# proc append(e, c: HTMLElement) {.importwasmraw: "".}
167-
# var a: HTMLElement
168-
# # var c: JSExternObj[Canvas] # Must be implicitly convertible to JSExternObj[HTMLElement]
169-
# var c: Canvas # Must be implicitly convertible to JSExternObj[HTMLElement]
170-
# append(a, c)
169+
block:
170+
# Custom types
171+
type
172+
HTMLElement = object of JSObj
173+
Canvas = object of HTMLElement
174+
proc objType(e: HTMLElement): string {.importwasmp.}
175+
proc getSomeCanvas(): Canvas {.importwasmexpr: "{objType:'canvas'}".}
176+
proc getSomeElement(): HTMLElement {.importwasmexpr: "{objType:'element'}".}
177+
proc append(e, c: HTMLElement) {.importwasmraw: "$0.appended = $1".}
178+
proc appended(e: HTMLElement): HTMLElement {.importwasmp.}
179+
180+
proc test() =
181+
let a = getSomeElement()
182+
doAssert(a.objType == "element")
183+
let c = getSomeCanvas()
184+
doAssert(c.objType == "canvas")
185+
a.append(c)
186+
doAssert(a.appended.objType == "canvas")
187+
let ao: HTMLElement = getSomeElement()
188+
doAssert(ao.objType == "element")
189+
let co: Canvas = getSomeCanvas()
190+
doAssert(co.objType == "canvas")
191+
ao.append(co)
192+
doAssert(ao.appended.objType == "canvas")
193+
let ce: HTMLElement = getSomeCanvas().toJSObj()
194+
a.append(ce)
195+
doAssert(a.appended.objType == "canvas")
196+
let ce1 = c.to(HTMLElement)
197+
a.append(ce1)
198+
doAssert(a.appended.objType == "canvas")
199+
test()
171200

172201
echo "ok"

wasmrt.nim

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,26 @@ type
3030
JSObj* {.inheritable, pure.} = object
3131
o*: JSRef
3232
JSString* = object of JSObj
33-
JSExternRef* {.importc: "__externref_t", noinit.} = object
34-
JSExternObj*[T] {.noinit.} = distinct JSExternRef
33+
JSExternObjBase {.inheritable, pure, noinit, importc: "__externref_t", bycopy.} = object
34+
35+
JSExternRef* = JSExternObjBase
36+
37+
macro parent(t: typedesc): untyped =
38+
let n = t.getType()[1]
39+
if sameType(n, bindSym"JSObj"):
40+
return bindSym"JSExternRef"
41+
else:
42+
let imp = n.getTypeImpl()
43+
imp.expectKind(nnkObjectTy)
44+
let base = imp[1][0]
45+
result = newTree(nnkObjectTy,
46+
newEmptyNode(),
47+
newTree(nnkOfInherit,
48+
newTree(nnkBracketExpr, ident"JSExternObj", base)),
49+
newEmptyNode())
50+
51+
type
52+
JSExternObj*[T] {.noinit, importc: "__externref_t", bycopy.} = parent(T)
3553

3654
type ExternRefTable {.importc.} = object
3755
var globalRefs {.codegendecl: "static __externref_t $2[0]".}: ExternRefTable
@@ -40,8 +58,6 @@ proc wasmTableSet(t: ExternRefTable, i: cint, e: JSExternRef) {.importc: "__buil
4058
proc wasmTableGet(t: ExternRefTable, i: cint): JSExternRef {.importc: "__builtin_wasm_table_get", nodecl.}
4159

4260
proc nullExternRef(): JSExternRef {.importc: "__builtin_wasm_ref_null_extern", nodecl.}
43-
# proc blabla(): JSExternRef {.importc, constructor: "blabla()".} =
44-
# discard
4561

4662
proc globalRefsTab(): int =
4763
proc initGlobalRefsTab(): int =
@@ -132,7 +148,7 @@ template toWasmWrapperType(t: typedesc): typedesc =
132148
elif t is JSRef:
133149
JSExternRef
134150
elif t is JSObj:
135-
JSExternObj[t]
151+
JSExternObj[t] | t
136152
else:
137153
t
138154

@@ -377,10 +393,13 @@ proc `==`*(n: typeof(nil), e: JSExternObj): bool {.inline, enforceNoRaises.} = i
377393
converter toJSRef*(e: JSExternRef): JSRef =
378394
createJSRef(e)
379395

380-
converter toJSExternObj*[T: JSObj](o: T): JSExternObj[T] =
396+
converter toJSExternObj*[T: JSObj](o: T): JSExternObj[T] {.inline.} =
381397
JSExternObj[T](wasmTableGet(globalRefs, cast[int32](o.o)))
382398

383-
converter toJSObj*[T: JSObj](e: JSExternObj[T]): T =
399+
converter toJSObj*[T: JSObj](e: JSExternObj[T]): T {.inline.} =
400+
T(o: cast[JSRef](storeRef(JSExternRef(e))))
401+
402+
proc to*[T: JSObj, F](e: JSExternObj[F]): T {.inline.} =
384403
T(o: cast[JSRef](storeRef(JSExternRef(e))))
385404

386405
proc toFuncExternRef(p: pointer): JSExternFuncRef {.importc, codegendecl: codegenDeclStr("\\06\\01_nimm.exports.__indirect_function_table.get").}

0 commit comments

Comments
 (0)