diff options
Diffstat (limited to 'lib/js')
-rw-r--r-- | lib/js/asyncjs.nim | 19 | ||||
-rw-r--r-- | lib/js/dom.nim | 57 | ||||
-rw-r--r-- | lib/js/jscore.nim | 96 | ||||
-rw-r--r-- | lib/js/jsffi.nim | 30 |
4 files changed, 185 insertions, 17 deletions
diff --git a/lib/js/asyncjs.nim b/lib/js/asyncjs.nim index 62444e49a..7439b66e1 100644 --- a/lib/js/asyncjs.nim +++ b/lib/js/asyncjs.nim @@ -92,7 +92,10 @@ proc isFutureVoid(node: NimNode): bool = node[1].kind == nnkIdent and $node[1] == "void" proc generateJsasync(arg: NimNode): NimNode = - assert arg.kind == nnkProcDef + if arg.kind notin {nnkProcDef, nnkLambda, nnkMethodDef, nnkDo}: + error("Cannot transform this node kind into an async proc." & + " proc/method definition or lambda node expected.") + result = arg var isVoid = false let jsResolve = ident("jsResolve") @@ -108,7 +111,7 @@ proc generateJsasync(arg: NimNode): NimNode = if len(code) > 0: var awaitFunction = quote: - proc await[T](f: Future[T]): T {.importcpp: "(await #)".} + proc await[T](f: Future[T]): T {.importcpp: "(await #)", used.} result.body.add(awaitFunction) var resolve: NimNode @@ -117,7 +120,7 @@ proc generateJsasync(arg: NimNode): NimNode = var `jsResolve` {.importcpp: "undefined".}: Future[void] else: resolve = quote: - proc jsResolve[T](a: T): Future[T] {.importcpp: "#".} + proc jsResolve[T](a: T): Future[T] {.importcpp: "#", used.} result.body.add(resolve) else: result.body = newEmptyNode() @@ -129,14 +132,20 @@ proc generateJsasync(arg: NimNode): NimNode = return `jsResolve` result.body.add(voidFix) - result.pragma = quote: + let asyncPragma = quote: {.codegenDecl: "async function $2($3)".} + result.addPragma(asyncPragma[0]) macro async*(arg: untyped): untyped = ## Macro which converts normal procedures into ## javascript-compatible async procedures - generateJsasync(arg) + if arg.kind == nnkStmtList: + result = newStmtList() + for oneProc in arg: + result.add generateJsasync(oneProc) + else: + result = generateJsasync(arg) proc newPromise*[T](handler: proc(resolve: proc(response: T))): Future[T] {.importcpp: "(new Promise(#))".} ## A helper for wrapping callback-based functions diff --git a/lib/js/dom.nim b/lib/js/dom.nim index 55692d47d..cf219df3d 100644 --- a/lib/js/dom.nim +++ b/lib/js/dom.nim @@ -45,6 +45,7 @@ type location*: Location closed*: bool defaultStatus*: cstring + devicePixelRatio*: float innerHeight*, innerWidth*: int locationbar*: ref TLocationBar menubar*: ref TMenuBar @@ -53,11 +54,15 @@ type pageXOffset*, pageYOffset*: int personalbar*: ref TPersonalBar scrollbars*: ref TScrollBars + scrollX*: float + scrollY*: float statusbar*: ref TStatusBar status*: cstring toolbar*: ref TToolBar frames*: seq[TFrame] screen*: Screen + performance*: Performance + onpopstate*: proc (event: Event) Frame* = ref FrameObj FrameObj {.importc.} = object of WindowObj @@ -171,6 +176,12 @@ type text*: cstring value*: cstring + TextAreaElement* = ref object of ElementObj + value*: cstring + selectionStart*, selectionEnd*: int + selectionDirection*: cstring + rows*, cols*: int + FormElement* = ref FormObj FormObj {.importc.} = object of ElementObj action*: cstring @@ -190,7 +201,7 @@ type vspace*: int width*: int - Style = ref StyleObj + Style* = ref StyleObj StyleObj {.importc.} = object of RootObj background*: cstring backgroundAttachment*: cstring @@ -253,6 +264,8 @@ type minHeight*: cstring minWidth*: cstring overflow*: cstring + overflowX*: cstring + overflowY*: cstring padding*: cstring paddingBottom*: cstring paddingLeft*: cstring @@ -400,12 +413,47 @@ type once*: bool passive*: bool + BoundingRect* {.importc.} = ref object + top*, bottom*, left*, right*, x*, y*, width*, height*: float + + PerformanceMemory* {.importc.} = ref object + jsHeapSizeLimit*: float + totalJSHeapSize*: float + usedJSHeapSize*: float + + PerformanceTiming* {.importc.} = ref object + connectStart*: float + domComplete*: float + domContentLoadedEventEnd*: float + domContentLoadedEventStart*: float + domInteractive*: float + domLoading*: float + domainLookupEnd*: float + domainLookupStart*: float + fetchStart*: float + loadEventEnd*: float + loadEventStart*: float + navigationStart*: float + redirectEnd*: float + redirectStart*: float + requestStart*: float + responseEnd*: float + responseStart*: float + secureConnectionStart*: float + unloadEventEnd*: float + unloadEventStart*: float + + Performance* {.importc.} = ref object + memory*: PerformanceMemory + timing*: PerformanceTiming + {.push importcpp.} # EventTarget "methods" proc addEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), useCapture: bool = false) proc addEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), options: AddEventListenerOptions) proc removeEventListener*(et: EventTarget, ev: cstring, cb: proc(ev: Event), useCapture: bool = false) +proc dispatchEvent*(et: EventTarget, ev: Event) # Window "methods" proc alert*(w: Window, msg: cstring) @@ -451,6 +499,7 @@ proc cloneNode*(n: Node, copyContent: bool): Node proc deleteData*(n: Node, start, len: int) proc getAttribute*(n: Node, attr: cstring): cstring proc getAttributeNode*(n: Node, attr: cstring): Node +proc getBoundingClientRect*(e: Node): BoundingRect proc hasChildNodes*(n: Node): bool proc insertBefore*(n, newNode, before: Node) proc insertData*(n: Node, position: int, data: cstring) @@ -459,7 +508,7 @@ proc removeAttributeNode*(n, attr: Node) proc removeChild*(n, child: Node) proc replaceChild*(n, newNode, oldNode: Node) proc replaceData*(n: Node, start, len: int, text: cstring) -proc scrollIntoView*(n: Node) +proc scrollIntoView*(n: Node, alignToTop: bool=true) proc setAttribute*(n: Node, name, value: cstring) proc setAttributeNode*(n: Node, attr: Node) @@ -530,6 +579,9 @@ proc preventDefault*(ev: Event) proc identifiedTouch*(list: TouchList): Touch proc item*(list: TouchList, i: int): Touch +# Performance "methods" +proc now*(p: Performance): float + {.pop.} var @@ -552,6 +604,7 @@ proc parseFloat*(s: cstring): BiggestFloat {.importc, nodecl.} proc parseInt*(s: cstring): int {.importc, nodecl.} proc parseInt*(s: cstring, radix: int):int {.importc, nodecl.} +proc newEvent*(name: cstring): Event {.importcpp: "new Event(@)", constructor.} type TEventHandlers* {.deprecated.} = EventTargetObj diff --git a/lib/js/jscore.nim b/lib/js/jscore.nim new file mode 100644 index 000000000..bf64b0794 --- /dev/null +++ b/lib/js/jscore.nim @@ -0,0 +1,96 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2018 Nim contributors +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module wraps core JavaScript functions. +## +## Unless your application has very +## specific requirements and solely targets JavaScript, you should be using +## the relevant functions in the ``math``, ``json``, and ``times`` stdlib +## modules instead. + +when not defined(js) and not defined(Nimdoc): + {.error: "This module only works on the JavaScript platform".} + +type + MathLib* = ref object + JsonLib* = ref object + DateLib* = ref object + DateTime* = ref object + +var + Math* {.importc, nodecl.}: MathLib + Date* {.importc, nodecl.}: DateLib + JSON* {.importc, nodecl.}: JsonLib + +# Math library +proc abs*(m: MathLib, a: SomeNumber): SomeNumber {.importcpp.} +proc acos*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc acosh*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc asin*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc asinh*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc atan*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc atan2*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc atanh*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc cbrt*(m: MathLib, f: SomeFloat): SomeFloat {.importcpp.} +proc ceil*(m: MathLib, f: SomeFloat): SomeFloat {.importcpp.} +proc clz32*(m: MathLib, f: SomeInteger): int {.importcpp.} +proc cos*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc cosh*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc exp*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc expm1*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc floor*(m: MathLib, f: SomeFloat): int {.importcpp.} +proc fround*(m: MathLib, f: SomeFloat): float32 {.importcpp.} +proc hypot*(m: MathLib, args: varargs[distinct SomeNumber]): float {.importcpp.} +proc imul*(m: MathLib, a, b: int32): int32 {.importcpp.} +proc log*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc log10*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc log1p*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc log2*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc max*(m: MathLib, a, b: SomeNumber): SomeNumber {.importcpp.} +proc min*[T: SomeNumber | JsRoot](m: MathLib, a, b: T): T {.importcpp.} +proc pow*(m: MathLib, a, b: distinct SomeNumber): float {.importcpp.} +proc random*(m: MathLib): float {.importcpp.} +proc round*(m: MathLib, f: SomeFloat): int {.importcpp.} +proc sign*(m: MathLib, f: SomeNumber): int {.importcpp.} +proc sin*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc sinh*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc sqrt*(m: MathLib, f: SomeFloat): SomeFloat {.importcpp.} +proc tan*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc tanh*(m: MathLib, a: SomeNumber): float {.importcpp.} +proc trunc*(m: MathLib, f: SomeFloat): int {.importcpp.} + +# Date library +proc now*(d: DateLib): int {.importcpp.} +proc UTC*(d: DateLib): int {.importcpp.} +proc parse*(d: DateLib, s: cstring): int {.importcpp.} + +proc newDate*(): DateTime {. + importcpp: "new Date()".} + +proc newDate*(date: int|string): DateTime {. + importcpp: "new Date(#)".} + +proc newDate*(year, month, day, hours, minutes, + seconds, milliseconds: int): DateTime {. + importcpp: "new Date(#,#,#,#,#,#,#)".} + +proc getDay*(d: DateTime): int {.importcpp.} +proc getFullYear*(d: DateTime): int {.importcpp.} +proc getHours*(d: DateTime): int {.importcpp.} +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.} + +#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 f34efe9a2..7b44c57c7 100644 --- a/lib/js/jsffi.nim +++ b/lib/js/jsffi.nim @@ -70,22 +70,29 @@ template mangleJsName(name: cstring): cstring = "mangledName" & $nameCounter type - JsRoot* = ref object of RootObj - ## Root type of both JsObject and JsAssoc JsObject* = ref object of JsRoot ## Dynamically typed wrapper around a JavaScript object. JsAssoc*[K, V] = ref object of JsRoot ## Statically typed wrapper around a JavaScript object. - NotString = concept c - c isnot string + js* = JsObject -var jsarguments* {.importc: "arguments", nodecl}: JsObject - ## JavaScript's arguments pseudo-variable +var + jsArguments* {.importc: "arguments", nodecl}: JsObject + ## JavaScript's arguments pseudo-variable + jsNull* {.importc: "null", nodecl.}: JsObject + ## JavaScript's null literal + jsUndefined* {.importc: "undefined", nodecl.}: JsObject + ## JavaScript's undefined literal + jsDirname* {.importc: "__dirname", nodecl.}: cstring + ## JavaScript's __dirname pseudo-variable + jsFilename* {.importc: "__filename", nodecl.}: cstring + ## JavaScript's __filename pseudo-variable # New proc newJsObject*: JsObject {. importcpp: "{@}" .} ## Creates a new empty JsObject + proc newJsAssoc*[K, V]: JsAssoc[K, V] {. importcpp: "{@}" .} ## Creates a new empty JsAssoc with key type `K` and value type `V`. @@ -97,13 +104,16 @@ proc hasOwnProperty*(x: JsObject, prop: cstring): bool proc jsTypeOf*(x: JsObject): cstring {. importcpp: "typeof(#)" .} ## Returns the name of the JsObject's JavaScript type as a cstring. -proc jsnew*(x: auto): JsObject {.importcpp: "(new #)".} +proc jsNew*(x: auto): JsObject {.importcpp: "(new #)".} ## Turns a regular function call into an invocation of the ## JavaScript's `new` operator -proc jsdelete*(x: auto): JsObject {.importcpp: "(delete #)".} +proc jsDelete*(x: auto): JsObject {.importcpp: "(delete #)".} ## JavaScript's `delete` operator +proc require*(module: cstring): JsObject {.importc.} + ## JavaScript's `require` function + # Conversion to and from JsObject proc to*(x: JsObject, T: typedesc): T {. importcpp: "(#)" .} ## Converts a JsObject `x` to type `T`. @@ -155,7 +165,7 @@ proc `[]=`*[T](obj: JsObject, field: cstring, val: T) {. importcpp: setImpl .} proc `[]=`*[T](obj: JsObject, field: int, val: T) {. importcpp: setImpl .} ## Set the value of a property of name `field` in a JsObject `obj` to `v`. -proc `[]`*[K: NotString, V](obj: JsAssoc[K, V], field: K): V +proc `[]`*[K: not string, V](obj: JsAssoc[K, V], field: K): V {. importcpp: getImpl .} ## Return the value of a property of name `field` from a JsAssoc `obj`. @@ -163,7 +173,7 @@ proc `[]`*[V](obj: JsAssoc[string, V], field: cstring): V {. importcpp: getImpl .} ## Return the value of a property of name `field` from a JsAssoc `obj`. -proc `[]=`*[K: NotString, V](obj: JsAssoc[K, V], field: K, val: V) +proc `[]=`*[K: not string, V](obj: JsAssoc[K, V], field: K, val: V) {. importcpp: setImpl .} ## Set the value of a property of name `field` in a JsAssoc `obj` to `v`. |