std/jsffi
 Source Edit
  This Module implements types and macros to facilitate the wrapping of, and interaction with JavaScript libraries. Using the provided types JsObject and JsAssoc together with the provided macros allows for smoother interfacing with JavaScript, allowing for example quick and easy imports of JavaScript variables:
  Example:
  import std/jsffi
# Here, we are using jQuery for just a few calls and do not want to wrap the
# whole library:
# import the document object and the console
var document {.importc, nodecl.}: JsObject
var console {.importc, nodecl.}: JsObject
# import the "$" function
proc jq(selector: JsObject): JsObject {.importjs: "$$(#)".}
# Use jQuery to make the following code run, after the document is ready.
# This uses an experimental `.()` operator for `JsObject`, to emit
# JavaScript calls, when no corresponding proc exists for `JsObject`.
proc main =
  jq(document).ready(proc() =
    console.log("Hello JavaScript!")
  )
  Imports
  macros, tables
  
Types
  
   
   
    - 
     JsAssoc[K; V] = ref object of JsRoot
 
- 
     Statically typed wrapper around a JavaScript object. Source Edit
    
 
   
    - 
     JsError {.importc: "Error".} = object of JsRoot
  message*: cstring
 
- Source Edit
    
 
   
    - 
     JsEvalError {.importc: "EvalError".} = object of JsError
 
- Source Edit
    
 
   
    - 
     JsKey = concept atypeof(T)
    cstring.toJsKey(T) is T
 
- Source Edit
    
 
   
    - 
     JsObject = ref object of JsRoot
 
- 
     Dynamically typed wrapper around a JavaScript object. Source Edit
    
 
   
    - 
     JsRangeError {.importc: "RangeError".} = object of JsError
 
- Source Edit
    
 
   
    - 
     JsReferenceError {.importc: "ReferenceError".} = object of JsError
 
- Source Edit
    
 
   
    - 
     JsSyntaxError {.importc: "SyntaxError".} = object of JsError
 
- Source Edit
    
 
   
    - 
     JsTypeError {.importc: "TypeError".} = object of JsError
 
- Source Edit
    
 
   
    - 
     JsURIError {.importc: "URIError".} = object of JsError
 
- Source Edit
    
 
  
Vars
  
   
    - 
     jsArguments {.importc: "arguments", nodecl.}: JsObject
 
- 
     JavaScript's arguments pseudo-variable. Source Edit
    
 
   
    - 
     jsDirname {.importc: "__dirname", nodecl.}: cstring
 
- 
     JavaScript's __dirname pseudo-variable. Source Edit
    
 
   
    - 
     jsFilename {.importc: "__filename", nodecl.}: cstring
 
- 
     JavaScript's __filename pseudo-variable. Source Edit
    
 
   
    - 
     jsNull {.importc: "null", nodecl.}: JsObject
 
- 
     JavaScript's null literal. Source Edit
    
 
   
    - 
     jsUndefined {.importc: "undefined", nodecl.}: JsObject
 
- 
     JavaScript's undefined literal. Source Edit
    
 
  
Procs
  
   
    
     - 
      proc `%`(x, y: JsObject): JsObject {.importjs: "(# % #)", ...raises: [], tags: [],
                                     forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `%=`(x, y: JsObject): JsObject {.importjs: "(# %= #)", discardable,
                                      ...raises: [], tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `&`(a, b: cstring): cstring {.importjs: "(# + #)", ...raises: [], tags: [],
                                   forbids: [].}
 
- 
      Concatenation operator for JavaScript strings. Source Edit
     
 
    
   
    
     - 
      proc `*`(x, y: JsObject): JsObject {.importjs: "(# * #)", ...raises: [], tags: [],
                                     forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `**`(x, y: JsObject): JsObject {.importjs: "((#) ** #)", ...raises: [],
                                      tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `*=`(x, y: JsObject): JsObject {.importjs: "(# *= #)", discardable,
                                      ...raises: [], tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `+`(x, y: JsObject): JsObject {.importjs: "(# + #)", ...raises: [], tags: [],
                                     forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `++`(x: JsObject): JsObject {.importjs: "(++#)", ...raises: [], tags: [],
                                   forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `+=`(x, y: JsObject): JsObject {.importjs: "(# += #)", discardable,
                                      ...raises: [], tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `-`(x, y: JsObject): JsObject {.importjs: "(# - #)", ...raises: [], tags: [],
                                     forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `--`(x: JsObject): JsObject {.importjs: "(--#)", ...raises: [], tags: [],
                                   forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `-=`(x, y: JsObject): JsObject {.importjs: "(# -= #)", discardable,
                                      ...raises: [], tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `/`(x, y: JsObject): JsObject {.importjs: "(# / #)", ...raises: [], tags: [],
                                     forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `/=`(x, y: JsObject): JsObject {.importjs: "(# /= #)", discardable,
                                      ...raises: [], tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `<`(x, y: JsObject): JsObject {.importjs: "(# < #)", ...raises: [], tags: [],
                                     forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `<=`(x, y: JsObject): JsObject {.importjs: "(# <= #)", ...raises: [],
                                      tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `==`(x, y: JsRoot): bool {.importjs: "(# === #)", ...raises: [], tags: [],
                                forbids: [].}
 
- 
      Compares two JsObjects or JsAssocs. Be careful though, as this is comparison like in JavaScript, so if your JsObjects are in fact JavaScript Objects, and not strings or numbers, this is a comparison of references. Source Edit
     
 
    
   
    
     - 
      proc `>`(x, y: JsObject): JsObject {.importjs: "(# > #)", ...raises: [], tags: [],
                                     forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `>=`(x, y: JsObject): JsObject {.importjs: "(# >= #)", ...raises: [],
                                      tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `[]`(obj: JsObject; field: cstring): JsObject {.importjs: "#[#]",
    ...raises: [], tags: [], forbids: [].}
 
- 
      Returns the value of a property of name fieldfrom a JsObjectobj. Source Edit
 
    
     - 
      proc `[]`(obj: JsObject; field: int): JsObject {.importjs: "#[#]", ...raises: [],
    tags: [], forbids: [].}
 
- 
      Returns the value of a property of name fieldfrom a JsObjectobj. Source Edit
 
    
     - 
      proc `[]`[K: JsKey; V](obj: JsAssoc[K, V]; field: K): V {.importjs: "#[#]",
    ...raises: [], tags: [], forbids: [].}
 
- 
      Returns the value of a property of name fieldfrom a JsAssocobj. Source Edit
 
    
     - 
      proc `[]`[V](obj: JsAssoc[cstring, V]; field: string): V
 
- Source Edit
     
 
    
   
    
     - 
      proc `[]=`[K: JsKey; V](obj: JsAssoc[K, V]; field: K; val: V) {.
    importjs: "#[#] = #", ...raises: [], tags: [], forbids: [].}
 
- 
      Sets the value of a property of name fieldin a JsAssocobjtov. Source Edit
 
    
     - 
      proc `[]=`[T](obj: JsObject; field: cstring; val: T) {.importjs: "#[#] = #",
    ...raises: [], tags: [], forbids: [].}
 
- 
      Sets the value of a property of name fieldin a JsObjectobjtov. Source Edit
 
    
     - 
      proc `[]=`[T](obj: JsObject; field: int; val: T) {.importjs: "#[#] = #",
    ...raises: [], tags: [], forbids: [].}
 
- 
      Sets the value of a property of name fieldin a JsObjectobjtov. Source Edit
 
    
     - 
      proc `[]=`[V](obj: JsAssoc[cstring, V]; field: string; val: V)
 
- Source Edit
     
 
    
   
    
     - 
      proc `and`(x, y: JsObject): JsObject {.importjs: "(# && #)", ...raises: [],
                                       tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc hasOwnProperty(x: JsObject; prop: cstring): bool {.
    importjs: "#.hasOwnProperty(#)", ...raises: [], tags: [], forbids: [].}
 
- 
      Checks, whether xhas a property of nameprop. Source Edit
 
    
   
    
     - 
      proc `in`(x, y: JsObject): JsObject {.importjs: "(# in #)", ...raises: [],
                                      tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc isNull[T](x: T): bool {.noSideEffect, importjs: "(# === null)", ...raises: [],
                             tags: [], forbids: [].}
 
- 
      Checks if a value is exactly null. Source Edit
     
 
    
   
    
     - 
      proc isUndefined[T](x: T): bool {.noSideEffect, importjs: "(# === undefined)",
                                  ...raises: [], tags: [], forbids: [].}
 
- 
      Checks if a value is exactly undefined. Source Edit
     
 
    
   
    
     - 
      proc jsDelete(x: auto): JsObject {.importjs: "(delete #)", ...raises: [], tags: [],
                                   forbids: [].}
 
- 
      JavaScript's deleteoperator. Source Edit
 
    
   
    
     - 
      proc jsNew(x: auto): JsObject {.importjs: "(new #)", ...raises: [], tags: [],
                                forbids: [].}
 
- 
      Turns a regular function call into an invocation of the JavaScript's newoperator. Source Edit
 
    
   
    
     - 
      proc jsTypeOf(x: JsObject): cstring {.importjs: "typeof(#)", ...raises: [],
                                      tags: [], forbids: [].}
 
- 
      Returns the name of the JsObject's JavaScript type as a cstring. Source Edit
     
 
    
   
    
     - 
      proc newJsAssoc[K: JsKey; V](): JsAssoc[K, V] {.importjs: "{@}", ...raises: [],
    tags: [], forbids: [].}
 
- 
      Creates a new empty JsAssoc with key type Kand value typeV. Source Edit
 
    
   
    
     - 
      proc newJsObject(): JsObject {.importjs: "{@}", ...raises: [], tags: [],
                               forbids: [].}
 
- 
      Creates a new empty JsObject. Source Edit
     
 
    
   
    
     - 
      proc `not`(x: JsObject): JsObject {.importjs: "(!#)", ...raises: [], tags: [],
                                    forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc `or`(x, y: JsObject): JsObject {.importjs: "(# || #)", ...raises: [],
                                      tags: [], forbids: [].}
 
- Source Edit
     
 
    
   
    
     - 
      proc require(module: cstring): JsObject {.importc, ...raises: [], tags: [],
    forbids: [].}
 
- 
      JavaScript's requirefunction. Source Edit
 
    
   
    
     - 
      proc to(x: JsObject; T: typedesc): T:type {.importjs: "(#)", ...raises: [],
    tags: [], forbids: [].}
 
- 
      Converts a JsObject xto typeT. Source Edit
 
    
   
    
     - 
      proc toJs[T](val: T): JsObject {.importjs: "(#)", ...raises: [], tags: [],
                                 forbids: [].}
 
- 
      Converts a value of any type to type JsObject. Source Edit
     
 
    
   
    
     - 
      proc toJsKey(text: cstring; t: type cstring): cstring
 
- Source Edit
     
 
    
     - 
      proc toJsKey[T: enum](text: cstring; t: type T): T
 
- Source Edit
     
 
    
     - 
      proc toJsKey[T: SomeFloat](text: cstring; t: type T): T {.
    importjs: "parseFloat(#)", ...raises: [], tags: [], forbids: [].}
 
- Source Edit
     
 
    
     - 
      proc toJsKey[T: SomeInteger](text: cstring; t: type T): T {.
    importjs: "parseInt(#)", ...raises: [], tags: [], forbids: [].}
 
- Source Edit
     
 
    
  
Iterators
  
   
    
     - 
      iterator items(obj: JsObject): JsObject {....raises: [], tags: [], forbids: [].}
 
- 
      Yields the valuesof each field in a JsObject, wrapped into a JsObject. Source Edit
 
    
     - 
      iterator items[K, V](assoc: JsAssoc[K, V]): V
 
- 
      Yields the valuesin a JsAssoc. Source Edit
 
    
   
    
     - 
      iterator keys(obj: JsObject): cstring {....raises: [], tags: [], forbids: [].}
 
- 
      Yields the namesof each field in a JsObject. Source Edit
 
    
     - 
      iterator keys[K: JsKey; V](assoc: JsAssoc[K, V]): K
 
- 
      Yields the keysin a JsAssoc. Source Edit
 
    
   
    
     - 
      iterator pairs(obj: JsObject): (cstring, JsObject) {....raises: [], tags: [],
    forbids: [].}
 
- 
      Yields tuples of type (cstring, JsObject), with the first entry being thenameof a fields in the JsObject and the second being its value wrapped into a JsObject. Source Edit
 
    
     - 
      iterator pairs[K: JsKey; V](assoc: JsAssoc[K, V]): (K, V)
 
- 
      Yields tuples of type (K, V), with the first entry being akeyin the JsAssoc and the second being its corresponding value. Source Edit
 
    
  
Macros
  
   
    
     - 
      macro `.`(obj: JsObject; field: untyped): JsObject
 
- 
      Experimental dot accessor (get) for type JsObject. Returns the value of a property of name fieldfrom a JsObjectx.Example: let obj = newJsObject()
obj.a = 20
assert obj.a.to(int) == 20
 Source Edit
 
    
     - 
      macro `.`[K: cstring; V](obj: JsAssoc[K, V]; field: untyped): V
 
- 
      Experimental dot accessor (get) for type JsAssoc. Returns the value of a property of name fieldfrom a JsObjectx. Source Edit
 
    
   
    
     - 
      macro `.()`(obj: JsObject; field: untyped; args: varargs[JsObject, jsFromAst]): JsObject
 
- 
      Experimental "method call" operator for type JsObject. Takes the name of a method of the JavaScript object (field) and calls it withargsas arguments, returning a JsObject (which may be discarded, and may beundefined, if the method does not return anything, so be careful when using this.)
 Example: # Let's get back to the console example:
var console {.importc, nodecl.}: JsObject
let res = console.log("I return undefined!")
console.log(res) # This prints undefined, as console.log always returns
                 # undefined. Thus one has to be careful, when using
                 # JsObject calls.
 Source Edit
 
    
     - 
      macro `.()`[K: cstring; V: proc](obj: JsAssoc[K, V]; field: untyped;
                                 args: varargs[untyped]): auto
 
- 
      Experimental "method call" operator for type JsAssoc. Takes the name of a method of the JavaScript object (field) and calls it withargsas arguments. Here, everything is typechecked, so you do not have to worry aboutundefinedreturn values. Source Edit
 
    
   
    
     - 
      macro `.=`(obj: JsObject; field, value: untyped): untyped
 
- 
      Experimental dot accessor (set) for type JsObject. Sets the value of a property of name fieldin a JsObjectxtovalue. Source Edit
 
    
     - 
      macro `.=`[K: cstring; V](obj: JsAssoc[K, V]; field: untyped; value: V): untyped
 
- 
      Experimental dot accessor (set) for type JsAssoc. Sets the value of a property of name fieldin a JsObjectxtovalue. Source Edit
 
    
   
    
     - 
      macro bindMethod(procedure: typed): auto
 
- 
      Takes the name of a procedure and wraps it into a lambda missing the first argument, which passes the JavaScript builtin thisas the first argument to the procedure. Returns the resulting lambda.
 Example: We want to generate roughly this JavaScript: var obj = {a: 10};
obj.someMethod = function() {
  return this.a + 42;
};
 We can achieve this using the bindMethodmacro:
 let obj = JsObject{ a: 10 }
proc someMethodImpl(that: JsObject): int =
  that.a.to(int) + 42
obj.someMethod = bindMethod someMethodImpl
# Alternatively:
obj.someMethod = bindMethod
  proc(that: JsObject): int = that.a.to(int) + 42
 Source Edit
 
    
   
   
    
     - 
      macro `{}`(typ: typedesc; xs: varargs[untyped]): auto
 
- 
      Takes a typedescas its first argument, and a series of expressions of typekey: value, and returns a value of the specified type with each fieldkeyset tovalue, as specified in the arguments of{}.
 Example: # Let's say we have a type with a ton of fields, where some fields do not
# need to be set, and we do not want those fields to be set to `nil`:
type
  ExtremelyHugeType = ref object
    a, b, c, d, e, f, g: int
    h, i, j, k, l: cstring
    # And even more fields ...
let obj = ExtremelyHugeType{ a: 1, k: "foo".cstring, d: 42 }
# This generates roughly the same JavaScript as:
{.emit: "var obj = {a: 1, k: "foo", d: 42};".}
 Source Edit
 
    
  
Templates