diff options
Diffstat (limited to 'lib/js')
-rw-r--r-- | lib/js/asyncjs.nim | 21 | ||||
-rw-r--r-- | lib/js/dom.nim | 58 | ||||
-rw-r--r-- | lib/js/jscore.nim | 91 | ||||
-rw-r--r-- | lib/js/jsffi.nim | 24 |
4 files changed, 179 insertions, 15 deletions
diff --git a/lib/js/asyncjs.nim b/lib/js/asyncjs.nim index ec410ee39..894102ca0 100644 --- a/lib/js/asyncjs.nim +++ b/lib/js/asyncjs.nim @@ -71,14 +71,17 @@ type PromiseJs* {.importcpp: "Promise".} = ref object ## A JavaScript Promise + proc replaceReturn(node: var NimNode) = var z = 0 for s in node: var son = node[z] + let jsResolve = ident("jsResolve") if son.kind == nnkReturnStmt: - node[z] = nnkReturnStmt.newTree(nnkCall.newTree(ident("jsResolve"), son[0])) + let value = if son[0].kind != nnkEmpty: nnkCall.newTree(jsResolve, son[0]) else: jsResolve + 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(ident("jsResolve"), son[1])) + node[z] = nnkAsgn.newTree(son[0], nnkCall.newTree(jsResolve, son[1])) else: replaceReturn(son) inc z @@ -92,8 +95,7 @@ proc generateJsasync(arg: NimNode): NimNode = assert arg.kind == nnkProcDef result = arg var isVoid = false - var jsResolveNode = ident("jsResolve") - + let jsResolve = ident("jsResolve") if arg.params[0].kind == nnkEmpty: result.params[0] = nnkBracketExpr.newTree(ident("Future"), ident("void")) isVoid = true @@ -112,7 +114,7 @@ proc generateJsasync(arg: NimNode): NimNode = var resolve: NimNode if isVoid: resolve = quote: - var `jsResolveNode` {.importcpp: "undefined".}: Future[void] + var `jsResolve` {.importcpp: "undefined".}: Future[void] else: resolve = quote: proc jsResolve[T](a: T): Future[T] {.importcpp: "#".} @@ -124,12 +126,13 @@ proc generateJsasync(arg: NimNode): NimNode = if len(code) > 0 and isVoid: var voidFix = quote: - return `jsResolveNode` + 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 @@ -139,3 +142,7 @@ macro async*(arg: untyped): untyped = proc newPromise*[T](handler: proc(resolve: proc(response: T))): Future[T] {.importcpp: "(new Promise(#))".} ## A helper for wrapping callback-based functions ## into promises and async procedures + +proc newPromise*(handler: proc(resolve: proc())): Future[void] {.importcpp: "(new Promise(#))".} + ## A helper for wrapping callback-based functions + ## into promises and async procedures diff --git a/lib/js/dom.nim b/lib/js/dom.nim index aa7f5d839..fd81fdf3f 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 @@ -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) @@ -507,6 +556,7 @@ proc replace*(loc: Location, s: cstring) proc back*(h: History) proc forward*(h: History) proc go*(h: History, pagesToJump: int) +proc pushState*[T](h: History, stateObject: T, title, url: cstring) # Navigator "methods" proc javaEnabled*(h: Navigator): bool @@ -529,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 @@ -551,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..91f3ff8bb --- /dev/null +++ b/lib/js/jscore.nim @@ -0,0 +1,91 @@ +## 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 + +{.push importcpp.} + +# Math library +proc abs*(m: MathLib, a: SomeNumber): SomeNumber +proc acos*(m: MathLib, a: SomeNumber): float +proc acosh*(m: MathLib, a: SomeNumber): float +proc asin*(m: MathLib, a: SomeNumber): float +proc asinh*(m: MathLib, a: SomeNumber): float +proc atan*(m: MathLib, a: SomeNumber): float +proc atan2*(m: MathLib, a: SomeNumber): float +proc atanh*(m: MathLib, a: SomeNumber): float +proc cbrt*(m: MathLib, f: SomeFloat): SomeFloat +proc ceil*(m: MathLib, f: SomeFloat): SomeFloat +proc clz32*(m: MathLib, f: SomeInteger): int +proc cos*(m: MathLib, a: SomeNumber): float +proc cosh*(m: MathLib, a: SomeNumber): float +proc exp*(m: MathLib, a: SomeNumber): float +proc expm1*(m: MathLib, a: SomeNumber): float +proc floor*(m: MathLib, f: SomeFloat): int +proc fround*(m: MathLib, f: SomeFloat): float32 +proc hypot*(m: MathLib, args: varargs[distinct SomeNumber]): float +proc imul*(m: MathLib, a, b: int32): int32 +proc log*(m: MathLib, a: SomeNumber): float +proc log10*(m: MathLib, a: SomeNumber): float +proc log1p*(m: MathLib, a: SomeNumber): float +proc log2*(m: MathLib, a: SomeNumber): float +proc max*(m: MathLib, a, b: SomeNumber): SomeNumber +proc min*[T: SomeNumber | JsRoot](m: MathLib, a, b: T): T +proc pow*(m: MathLib, a, b: distinct SomeNumber): float +proc random*(m: MathLib): float +proc round*(m: MathLib, f: SomeFloat): int +proc sign*(m: MathLib, f: SomeNumber): int +proc sin*(m: MathLib, a: SomeNumber): float +proc sinh*(m: MathLib, a: SomeNumber): float +proc sqrt*(m: MathLib, f: SomeFloat): SomeFloat +proc tan*(m: MathLib, a: SomeNumber): float +proc tanh*(m: MathLib, a: SomeNumber): float +proc trunc*(m: MathLib, f: SomeFloat): int + +# Date library +proc now*(d: DateLib): int +proc UTC*(d: DateLib): int +proc parse*(d: DateLib, s: cstring): int + +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 +proc getFullYear*(d: DateTime): int +proc getHours*(d: DateTime): int +proc getMilliseconds*(d: DateTime): int +proc getMinutes*(d: DateTime): int +proc getMonth*(d: DateTime): int +proc getSeconds*(d: DateTime): int +proc getYear*(d: DateTime): int +proc getTime*(d: DateTime): int +proc toString*(d: DateTime): cstring + +#JSON library +proc stringify*(l: JsonLib, s: JsRoot): cstring +proc parse*(l: JsonLib, s: cstring): JsRoot + +{.pop.} diff --git a/lib/js/jsffi.nim b/lib/js/jsffi.nim index f34efe9a2..6e48db6c7 100644 --- a/lib/js/jsffi.nim +++ b/lib/js/jsffi.nim @@ -70,22 +70,31 @@ 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 +106,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`. |