diff options
Diffstat (limited to 'lib/js')
-rw-r--r-- | lib/js/asyncjs.nim | 16 | ||||
-rw-r--r-- | lib/js/dom.nim | 19 | ||||
-rw-r--r-- | lib/js/jscore.nim | 26 | ||||
-rw-r--r-- | lib/js/jsffi.nim | 53 | ||||
-rw-r--r-- | lib/js/jsre.nim | 7 |
5 files changed, 82 insertions, 39 deletions
diff --git a/lib/js/asyncjs.nim b/lib/js/asyncjs.nim index 364f7a21a..9b043f3e5 100644 --- a/lib/js/asyncjs.nim +++ b/lib/js/asyncjs.nim @@ -90,6 +90,8 @@ proc replaceReturn(node: var NimNode) = node[z] = nnkReturnStmt.newTree(value) elif son.kind == nnkAsgn and son[0].kind == nnkIdent and $son[0] == "result": node[z] = nnkAsgn.newTree(son[0], nnkCall.newTree(jsResolve, son[1])) + elif son.kind in RoutineNodes: + discard else: replaceReturn(son) inc z @@ -100,10 +102,18 @@ proc isFutureVoid(node: NimNode): bool = node[1].kind == nnkIdent and $node[1] == "void" proc generateJsasync(arg: NimNode): NimNode = - if arg.kind notin {nnkProcDef, nnkLambda, nnkMethodDef, nnkDo}: + if arg.kind notin {nnkProcDef, nnkLambda, nnkMethodDef, nnkDo, nnkProcTy}: error("Cannot transform this node kind into an async proc." & " proc/method definition or lambda node expected.") + # Transform type X = proc (): something {.async.} + # into type X = proc (): Future[something] + if arg.kind == nnkProcTy: + result = arg + if arg[0][0].kind == nnkEmpty: + result[0][0] = quote do: Future[void] + return result + result = arg var isVoid = false let jsResolve = ident("jsResolve") @@ -233,7 +243,7 @@ since (1, 5, 1): else: type A = impl(onSuccess(default(T))) var ret: A - asm "`ret` = `future`.then(`onSuccess`, `onReject`)" + {.emit: "`ret` = `future`.then(`onSuccess`, `onReject`);".} return ret proc catch*[T](future: Future[T], onReject: OnReject): Future[void] = @@ -256,4 +266,4 @@ since (1, 5, 1): discard main() - asm "`result` = `future`.catch(`onReject`)" + {.emit: "`result` = `future`.catch(`onReject`);".} diff --git a/lib/js/dom.nim b/lib/js/dom.nim index 36434846a..be2a34db1 100644 --- a/lib/js/dom.nim +++ b/lib/js/dom.nim @@ -1423,7 +1423,7 @@ when defined(nodejs): parent.childNodes[i] = newNode return inc i - doAssert false, "old node not in node list" + raiseAssert "old node not in node list" proc removeChild*(parent, child: Node) = child.parentNode = nil @@ -1433,7 +1433,7 @@ when defined(nodejs): parent.childNodes.delete(i) return inc i - doAssert false, "old node not in node list" + raiseAssert "old node not in node list" proc insertBefore*(parent, newNode, before: Node) = appendChild(parent, newNode) @@ -1445,7 +1445,7 @@ when defined(nodejs): parent.childNodes[i-1] = newNode return inc i - #doAssert false, "before not in node list" + #raiseAssert "before not in node list" proc createElement*(d: Document, identifier: cstring): Element = new(result) @@ -1503,7 +1503,7 @@ proc confirm*(w: Window, msg: cstring): bool proc disableExternalCapture*(w: Window) proc enableExternalCapture*(w: Window) proc find*(w: Window, text: cstring, caseSensitive = false, - backwards = false) + backwards = false): bool proc focus*(w: Window) proc forward*(w: Window) proc getComputedStyle*(w: Window, e: Node, pe: Node = nil): Style @@ -1655,7 +1655,7 @@ proc item*(list: TouchList, i: int): Touch proc clearData*(dt: DataTransfer, format: cstring) proc getData*(dt: DataTransfer, format: cstring): cstring proc setData*(dt: DataTransfer, format: cstring, data: cstring) -proc setDragImage*(dt: DataTransfer, img: Element, xOffset: int64, yOffset: int64) +proc setDragImage*(dt: DataTransfer, img: Element, xOffset: int, yOffset: int) # DataTransferItem "methods" proc getAsFile*(dti: DataTransferItem): File @@ -1682,7 +1682,6 @@ proc `$`*(s: Selection): string = $(s.toString()) # Storage "methods" proc getItem*(s: Storage, key: cstring): cstring proc setItem*(s: Storage, key, value: cstring) -proc hasItem*(s: Storage, key: cstring): bool proc clear*(s: Storage) proc removeItem*(s: Storage, key: cstring) @@ -1832,3 +1831,11 @@ since (1, 7): proc matches*(self: Node; cssSelector: cstring): bool {.importjs: "(#.$1(#) || false)".} ## https://developer.mozilla.org/en-US/docs/Web/API/Element/matches + + +since (2, 1): + type VisualViewport* {.importc.} = ref object of EventTarget + offsetLeft*, offsetTop*, pageLeft*, pageTop*, width*, height*, scale*: float + onResize*, onScroll*: proc (event: Event) {.closure.} + + func visualViewport*(self: Window): VisualViewport {.importjs: "#.$1", nodecl.} diff --git a/lib/js/jscore.nim b/lib/js/jscore.nim index 781e8fd57..be353875c 100644 --- a/lib/js/jscore.nim +++ b/lib/js/jscore.nim @@ -13,7 +13,7 @@ ## specific requirements and solely targets JavaScript, you should be using ## the relevant functions in the `math`, `json`, and `times` stdlib ## modules instead. -import std/private/since +import std/private/[since, jsutils] when not defined(js): {.error: "This module only works on the JavaScript platform".} @@ -74,9 +74,16 @@ proc parse*(d: DateLib, s: cstring): int {.importcpp.} proc newDate*(): DateTime {. importcpp: "new Date()".} -proc newDate*(date: int|int64|string): DateTime {. +proc newDate*(date: int|string): DateTime {. importcpp: "new Date(#)".} +whenJsNoBigInt64: + proc newDate*(date: int64): DateTime {. + importcpp: "new Date(#)".} +do: + proc newDate*(date: int64): DateTime {. + importcpp: "new Date(Number(#))".} + proc newDate*(year, month, day, hours, minutes, seconds, milliseconds: int): DateTime {. importcpp: "new Date(#,#,#,#,#,#,#)".} @@ -88,20 +95,27 @@ proc getMilliseconds*(d: DateTime): int {.importcpp.} proc getMinutes*(d: DateTime): int {.importcpp.} proc getMonth*(d: DateTime): int {.importcpp.} proc getSeconds*(d: DateTime): int {.importcpp.} -proc getYear*(d: DateTime): int {.importcpp.} proc getTime*(d: DateTime): int {.importcpp.} -proc toString*(d: DateTime): cstring {.importcpp.} +proc getTimezoneOffset*(d: DateTime): int {.importcpp.} proc getUTCDate*(d: DateTime): int {.importcpp.} +proc getUTCDay*(d: DateTime): int {.importcpp.} proc getUTCFullYear*(d: DateTime): int {.importcpp.} proc getUTCHours*(d: DateTime): int {.importcpp.} proc getUTCMilliseconds*(d: DateTime): int {.importcpp.} proc getUTCMinutes*(d: DateTime): int {.importcpp.} proc getUTCMonth*(d: DateTime): int {.importcpp.} proc getUTCSeconds*(d: DateTime): int {.importcpp.} -proc getUTCDay*(d: DateTime): int {.importcpp.} -proc getTimezoneOffset*(d: DateTime): int {.importcpp.} +proc getYear*(d: DateTime): int {.importcpp.} + proc setFullYear*(d: DateTime, year: int) {.importcpp.} +func toDateString*(d: DateTime): cstring {.importcpp.} +func toISOString*(d: DateTime): cstring {.importcpp.} +func toJSON*(d: DateTime): cstring {.importcpp.} +proc toString*(d: DateTime): cstring {.importcpp.} +func toTimeString*(d: DateTime): cstring {.importcpp.} +func toUTCString*(d: DateTime): cstring {.importcpp.} + #JSON library proc stringify*(l: JsonLib, s: JsRoot): cstring {.importcpp.} proc parse*(l: JsonLib, s: cstring): JsRoot {.importcpp.} diff --git a/lib/js/jsffi.nim b/lib/js/jsffi.nim index db40e7515..d50d58ae5 100644 --- a/lib/js/jsffi.nim +++ b/lib/js/jsffi.nim @@ -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, @@ -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")) @@ -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, @@ -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, @@ -461,7 +468,7 @@ proc replaceSyms(n: NimNode): NimNode = for i in 0..<n.len: result[i] = replaceSyms(n[i]) -macro bindMethod*(procedure: typed): auto = +macro bindMethod*(procedure: typed): auto {.deprecated: "Don't use it with closures".} = ## Takes the name of a procedure and wraps it into a lambda missing the first ## argument, which passes the JavaScript builtin `this` as the first ## argument to the procedure. Returns the resulting lambda. diff --git a/lib/js/jsre.nim b/lib/js/jsre.nim index 19888aaa9..2d931eb20 100644 --- a/lib/js/jsre.nim +++ b/lib/js/jsre.nim @@ -34,6 +34,9 @@ func compile*(self: RegExp; pattern: cstring; flags: cstring) {.importjs: "#.com func replace*(pattern: cstring; self: RegExp; replacement: cstring): cstring {.importjs: "#.replace(#, #)".} ## Returns a new string with some or all matches of a pattern replaced by given replacement +func replace*(pattern: cstring, self: RegExp, cb: proc (args: varargs[cstring]): cstring): cstring {.importcpp.} + ## Returns a new string with some or all matches of a pattern replaced by given callback function + func split*(pattern: cstring; self: RegExp): seq[cstring] {.importjs: "(#.split(#) || [])".} ## Divides a string into an ordered list of substrings and returns the array @@ -55,7 +58,7 @@ func contains*(pattern: cstring; self: RegExp): bool = assert jsregex in r"abc" assert jsregex notin r"abcd" assert "xabc".contains jsregex - asm "`result` = `self`.test(`pattern`);" + {.emit: "`result` = `self`.test(`pattern`);".} func startsWith*(pattern: cstring; self: RegExp): bool = ## Tests if string starts with given RegExp @@ -88,5 +91,7 @@ runnableExamples: assert "do1ne".split(jsregex) == @["do".cstring, "ne".cstring] jsregex.compile(r"[lw]", r"i") assert "hello world".replace(jsregex,"X") == "heXlo world" + jsregex.compile(r"([a-z])\1*", r"g") + assert "abbcccdddd".replace(jsregex, proc (m: varargs[cstring]): cstring = ($m[0] & $(m.len)).cstring) == "a1b2c3d4" let digitsRegex: RegExp = newRegExp(r"\d") assert "foo".match(digitsRegex) == @[] |