duktape

Bindings for the Duktape javascript engine javascript duktape hacktoberfest
0.5.1 released

Duktape.cr

Build Status

Duktape.cr provides Crystal bindings to the Duktape javascript engine.

Installation

Duktape.cr is best installed using either Shards or the Crystal Package Manager.

Via Crystal Package Manager

Add this to your Projectfile:

deps do
  github "jessedoyle/duktape.cr", name: "duktape"
end

then execute:

crystal deps

Finally build the native Duktape library:

make -C libs/duktape/ext libduktape

Via Shards

Add this to your shard.yml:

name: example  # your project's name
version: 1.0.0 # your project's version

dependencies:
  duktape:
    github: jessedoyle/duktape.cr
    branch: master

then execute:

shards install

Note that Shards v0.3.1 or greater will automatically make the native library. Otherwise you will have to make the library manually by calling make libduktape from libs/duktape/ext.

Usage

You must first create a Duktape context:

require "duktape"

sbx = Duktape::Sandbox.new

sbx.eval! <<-JS
  var birthYear = 1990;

  function calcAge(birthYear){
    var current = new Date();
    var year = current.getFullYear();
    return year - birthYear;
  }

  print("You are " + calcAge(birthYear) + " years old.");
JS

An overwhelming majority of the Duktape API has been implemented. You can call the API functions directly on a Duktape::Sandbox or Duktape::Context instance:

sbx = Duktape::Sandbox.new
sbx.push_global_object   # [ global ]
sbx.push_string "Math"   # [ global "Math" ]
sbx.get_prop -2          # [ global Math ]
sbx.push_string "PI"     # [ global Math "PI" ]
sbx.get_prop -2          # [ global Math PI ]
pi = sbx.get_number -1
puts "PI: #{pi}"         # => PI: 3.14159
sbx.pop_3

Eval vs Eval!

All of the evaluation API methods have a corresponding bang-method (!). The bang method calls will raise when a javascript error occurs, the non-bang methods will not raise on invalid javascript.

For example:

sbx = Duktape::Context.new
sbx.eval <<-JS
  var a =
JS

will not raise any errors, but will return a non-zero error code.

The following code:

sbx = Duktape::Context.new
sbx.eval! <<-JS
  __invalid();
JS

will raise Duktape::Error "SyntaxError".

Sandbox vs Context

You should only execute untrusted javascript code from within a Duktape::Sandbox instance. A sandbox isolates code from insecure operations such as Duktape's internal require mechanism and the Duktape global javascript object.

Note that a sandbox does not currently protect against infinite loops or excessive runtime. Ideally, a timeout mechanism will be available in future releases.

Creating a Duktape::Context gives code access to internal Duktape properties:

ctx = Duktape::Context.new
ctx.eval! <<-JS
  print(Duktape.version);
JS

Calling Crystal Code from Javascript

Note: This functionality is considered experimental and syntax/functionality may change dramatically between releases.

It is possible to call Crystal code from your javascript:

  sbx = Duktape::Sandbox.new

  sbx.push_proc(2) do |ptr| # 2 stack arguments
    env = Duktape::Sandbox.new ptr
    a = env.get_number 0
    b = env.get_number 1
    env.push_number a + b
    env.return 1 # return success
  end

  sbx.push_int 2
  sbx.push_int 3
  sbx.call 2 # 2 stack arguments
  val = sbx.get_int -1
  puts val #=> 5

Contributing

I'll accept any pull requests that are well tested for bugs/features with Duktape.cr.

You should fork the main repo, create a feature branch, write tests and submit a pull request.

License

Duktape.cr is licensed under the MIT License. Please see LICENSE for details.

duktape:
  github: jessedoyle/duktape.cr
  version: ~> 0.5.1
Crystal none

Authors

Dependencies 0

Development Dependencies 0

Last synced .
search fire star recently