Skip to content

Commit

Permalink
make jsffi properly gensym
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Aug 23, 2023
1 parent 6b04d03 commit 469b451
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 22 deletions.
51 changes: 29 additions & 22 deletions lib/js/jsffi.nim
Original file line number Diff line number Diff line change
Expand Up @@ -227,36 +227,40 @@ macro `.`*(obj: JsObject, field: untyped): JsObject =
assert obj.a.to(int) == 20
if validJsName($field):
let importString = "#." & $field
let helperName = genSym(nskProc, "helper")
result = quote do:
proc helper(o: JsObject): JsObject
{.importjs: `importString`, gensym.}
helper(`obj`)
proc `helperName`(o: JsObject): JsObject
{.importjs: `importString`.}
`helperName`(`obj`)
else:
if not mangledNames.hasKey($field):
mangledNames[$field] = mangleJsName($field)
let importString = "#." & mangledNames[$field]
let helperName = genSym(nskProc, "helper")
result = quote do:
proc helper(o: JsObject): JsObject
{.importjs: `importString`, gensym.}
helper(`obj`)
proc `helperName`(o: JsObject): JsObject
{.importjs: `importString`.}
`helperName`(`obj`)

macro `.=`*(obj: JsObject, field, value: untyped): untyped =
## Experimental dot accessor (set) for type JsObject.
## Sets the value of a property of name `field` in a JsObject `x` to `value`.
if validJsName($field):
let importString = "#." & $field & " = #"
let helperName = genSym(nskProc, "helper")
result = quote do:
proc helper(o: JsObject, v: auto)
{.importjs: `importString`, gensym.}
helper(`obj`, `value`)
proc `helperName`(o: JsObject, v: auto)
{.importjs: `importString`.}
`helperName`(`obj`, `value`)
else:
if not mangledNames.hasKey($field):
mangledNames[$field] = mangleJsName($field)
let importString = "#." & mangledNames[$field] & " = #"
let helperName = genSym(nskProc, "helper")
result = quote do:
proc helper(o: JsObject, v: auto)
{.importjs: `importString`, gensym.}
helper(`obj`, `value`)
proc `helperName`(o: JsObject, v: auto)
{.importjs: `importString`.}
`helperName`(`obj`, `value`)

macro `.()`*(obj: JsObject,
field: untyped,
Expand All @@ -283,10 +287,11 @@ macro `.()`*(obj: JsObject,
if not mangledNames.hasKey($field):
mangledNames[$field] = mangleJsName($field)
importString = "#." & mangledNames[$field] & "(@)"
result = quote:
proc helper(o: JsObject): JsObject
{.importjs: `importString`, gensym, discardable.}
helper(`obj`)
let helperName = genSym(nskProc, "helper")
result = quote do:
proc `helperName`(o: JsObject): JsObject
{.importjs: `importString`, discardable.}
`helperName`(`obj`)
for idx in 0 ..< args.len:
let paramName = newIdentNode("param" & $idx)
result[0][3].add newIdentDefs(paramName, newIdentNode("JsObject"))
Expand All @@ -303,10 +308,11 @@ macro `.`*[K: cstring, V](obj: JsAssoc[K, V],
if not mangledNames.hasKey($field):
mangledNames[$field] = mangleJsName($field)
importString = "#." & mangledNames[$field]
let helperName = genSym(nskProc, "helper")
result = quote do:
proc helper(o: type(`obj`)): `obj`.V
{.importjs: `importString`, gensym.}
helper(`obj`)
proc `helperName`(o: type(`obj`)): `obj`.V
{.importjs: `importString`.}
`helperName`(`obj`)

macro `.=`*[K: cstring, V](obj: JsAssoc[K, V],
field: untyped,
Expand All @@ -320,10 +326,11 @@ macro `.=`*[K: cstring, V](obj: JsAssoc[K, V],
if not mangledNames.hasKey($field):
mangledNames[$field] = mangleJsName($field)
importString = "#." & mangledNames[$field] & " = #"
let helperName = genSym(nskProc, "helper")
result = quote do:
proc helper(o: type(`obj`), v: `obj`.V)
{.importjs: `importString`, gensym.}
helper(`obj`, `value`)
proc `helperName`(o: type(`obj`), v: `obj`.V)
{.importjs: `importString`.}
`helperName`(`obj`, `value`)

macro `.()`*[K: cstring, V: proc](obj: JsAssoc[K, V],
field: untyped,
Expand Down
6 changes: 6 additions & 0 deletions tests/js/tjsffi.nim
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,9 @@ block: # test **
doAssert to(`**`(a + a, b), int) == 2

doAssert to(`**`(toJs(1) + toJs(1), toJs(2)), int) == 4

block: # issue #21208
type MyEnum = enum baz
var obj: JsObject
{.emit: "`obj` = {bar: {baz: 123}}".}
discard obj.bar.baz

0 comments on commit 469b451

Please sign in to comment.