Git Product home page Git Product logo

jsbind's Introduction

jsbind

Create bindings to JavaScript that work when Nim is compiled to JavaScript as well as when compiled to Asm.js (through Emscripten).

Here's an example of how XMLHttpRequest can be defined:

import jsbind

type XMLHTTPRequest* = ref object of JSObj # Define the type. JSObj should be the root class for such types.

proc newXMLHTTPRequest*(): XMLHTTPRequest {.jsimportgWithName: "function(){return (window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP')}".}

proc open*(r: XMLHTTPRequest, httpMethod, url: cstring) {.jsimport.}
proc send*(r: XMLHTTPRequest) {.jsimport.}
proc send*(r: XMLHTTPRequest, body: cstring) {.jsimport.}

proc addEventListener*(r: XMLHTTPRequest, event: cstring, listener: proc()) {.jsimport.}
proc setRequestHeader*(r: XMLHTTPRequest, header, value: cstring) {.jsimport.}

proc responseText*(r: XMLHTTPRequest): jsstring {.jsimportProp.}
proc statusText*(r: XMLHTTPRequest): jsstring {.jsimportProp.}

proc `responseType=`*(r: XMLHTTPRequest, t: cstring) {.jsimportProp.}
proc response*(r: XMLHTTPRequest): JSObj {.jsimportProp.}

Use the bindings as normal Nim functions. They will work in both JS and Asm.js targets.

proc sendRequest*(meth, url, body: string, headers: openarray[(string, string)], handler: Handler) =
    let oReq = newXMLHTTPRequest()
    var reqListener: proc()
    reqListener = proc () =
        jsUnref(reqListener)
        handler(($oReq.statusText,  $oReq.responseText))
    jsRef(reqListener)
    oReq.responseType = "text"
    oReq.addEventListener("load", reqListener)
    oReq.open(meth, url)
    for h in headers:
        oReq.setRequestHeader(h[0], h[1])
    if body.isNil:
        oReq.send()
    else:
        oReq.send(body)

Low-level Emscripten bindings

jsbind.emscripten module defines the types and functions that emscripten defines along with some useful macros and pragmas such as EM_ASM_INT, EM_ASM_FLOAT, EMSCRIPTEN_KEEPALIVE, etc.

import jsbind.emscripten
proc foo() {.EMSCRIPTEN_KEEPALIVE.} = # now it's possible to call this function from JS
  discard EM_ASM_INT("""
  alert("hello, world!");
  """) # Use EM_ASM_* like you would do it in C

How jsbind works

When compiling to JavaScript, jsbind does almost nothing, translating its pragmas to corresponding importc, importcpp, etc. Basically there is no runtime cost for such bindings. The real magic happens when compiling to Emscripten. The imported functions are wrapped to EM_ASM_* calls, inside which the arguments are unpacked to JavaScript types as needed, and their return values are packed back to Asm.js.

Passing closures to imported functions

Closures are special because they have environment that can be garbage collected when no references to the closure left. Consider the example above with sendRequest. The reqListener is passed to Emscripten/JS function and no references are left after sendRequest returns. Here we need to explicitly protect it from collection with jsRef, and not forget to unprotect it when it is no longer needed with jsUnref, otherwise it will leak. jsRef and jsUnref do nothing when compiled to JavaScript, still its a good practice to place them where appropriate to make your bindings compatible with Asm.js.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.