Skip to content

Commit

Permalink
Run a simple script
Browse files Browse the repository at this point in the history
  • Loading branch information
sol committed Nov 10, 2012
1 parent 09e9c22 commit a850481
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 0 deletions.
26 changes: 26 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Haskell bindings to Google's V8 JavaScript Engine

This is still in a very early stage.

## Getting started with the code

Currently you have to build V8 yourself and copy the libraries and headers
manually.

#### Build V8

See [V8's download and build instructions](https://developers.google.com/v8/build).

After building V8, run the following commands from this repositories root
directory:

```console
$ cp -r <path-to-google-v8>/out/native/obj.target/tools/gyp/ lib
$ cp -r <path-to-google-v8>/include/ .
```

#### Build the bindings and run the test suite

```
$ cabal configure --enable-tests && cabal build && ./dist/build/spec/spec
```
39 changes: 39 additions & 0 deletions cbits/js.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <v8.h>

using namespace v8;

static_assert(sizeof(Handle<Value>) == 8,
"We treat Handle<Value> as a 64-bit value, but your compiler thinks it "
"has a different size. You can request support for your platform by "
"opening a ticket at https://github.com/sol/v8/issues."
);

extern "C" {

Handle<Value> mkUndefined() {
return Undefined();
}

void runScript(const InvocationCallback jsPrint, const char* input) {
// Create a stack-allocated handle scope.
HandleScope scope;

// Create a template for the global object and set the built-in global
// functions.
Local<ObjectTemplate> global = ObjectTemplate::New();
global->Set(String::New("print"), FunctionTemplate::New(jsPrint));

// Each processor gets its own context so different processors do not affect
// each other.
Persistent<Context> context = Context::New(NULL, global);

// Enter the created context for compiling and running the script.
Context::Scope context_scope(context);

// Compile the source code.
Script::Compile(String::New(input))->Run();

// Dispose the persistent context.
context.Dispose();
}
}
30 changes: 30 additions & 0 deletions src/Foreign/JavaScript/V8.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{-# LANGUAGE ForeignFunctionInterface #-}
module Foreign.JavaScript.V8 (runScript) where

import Foreign.C
import Foreign.Ptr
import Data.Int

runScript :: String -> IO ()
runScript input = do
ptr <- mkInvocationCallback jsPrint
withCString input (c_runScript ptr)
freeHaskellFunPtr ptr
where
jsPrint :: Arguments -> IO Value
jsPrint _ = do
putStrLn "foo"
mkUndefined

foreign import ccall "runScript" c_runScript :: InvocationCallback -> CString -> IO ()

type Value = Int64

foreign import ccall "mkUndefined" mkUndefined :: IO Value

data ArgumentsToken
type Arguments = Ptr ArgumentsToken

type InvocationCallback = FunPtr (Arguments -> IO Value)

foreign import ccall "wrapper" mkInvocationCallback :: (Arguments -> IO Value) -> IO InvocationCallback
16 changes: 16 additions & 0 deletions test/Foreign/JavaScript/V8Spec.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Foreign.JavaScript.V8Spec (main, spec) where

import Test.Hspec
import System.IO.Silently

import Foreign.JavaScript.V8

main :: IO ()
main = hspec spec

spec :: Spec
spec = do
describe "global built-ins" $ do
describe "print" $ do
it "can print a string" $ do
capture_ (runScript "print('foo')") `shouldReturn` "foo\n"
1 change: 1 addition & 0 deletions test/Spec.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
40 changes: 40 additions & 0 deletions v8.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: v8
version: 0.0.0
license: MIT
license-file: LICENSE
copyright: (c) 2012 Simon Hengel
author: Simon Hengel <sol@typeful.net>
maintainer: Simon Hengel <sol@typeful.net>
build-type: Simple
cabal-version: >= 1.10
stability: experimental
synopsis: Haskell bindings to Google's V8 JavaScript Engine

source-repository head
type: git
location: https://github.com/sol/v8

library
default-language: Haskell2010
ghc-options: -Wall

cc-options: -std=c++0x
ld-options: -Llib
extra-libraries: stdc++ v8_base v8_snapshot
include-dirs: include
c-sources: cbits/js.cpp

build-depends: base
hs-source-dirs: src
exposed-modules: Foreign.JavaScript.V8

test-suite spec
default-language: Haskell2010
type: exitcode-stdio-1.0
ghc-options: -Wall
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, v8
, hspec >= 1.3
, silently

0 comments on commit a850481

Please sign in to comment.