v8eval 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1b41852421cf3a98adc4bb3085e0167502f3ac7d
4
+ data.tar.gz: 87cc44407a717ac6df88cee14a139d57e98fefe6
5
+ SHA512:
6
+ metadata.gz: 180f31e8c88ff8ef3368132c6a6fce6e1d732f46fc8d078d587d6b72c14b68e572914f13975a9e6ce94142eafdc750d5f39c46f72b6d4aca08b362aa50a83bad
7
+ data.tar.gz: 65a8814312d975007a0db7932d628622bcb946809324a8011c62b0cc0c930c0b4e4e2c34aca211da76fc094da8b4344f3f29db6b460d06eef5fb79922676a177
data/CMakeLists.txt ADDED
@@ -0,0 +1,64 @@
1
+ cmake_minimum_required(VERSION 2.8)
2
+
3
+ project(v8eval)
4
+
5
+ option(V8EVAL_TEST "Build tests" OFF)
6
+
7
+ if(COMMAND cmake_policy)
8
+ cmake_policy(SET CMP0015 NEW)
9
+ endif(COMMAND cmake_policy)
10
+
11
+ include_directories(
12
+ v8
13
+ v8/include
14
+ v8/third_party/icu/source/i18n
15
+ v8/third_party/icu/source/common
16
+ src
17
+ test/googletest/googletest/include
18
+ )
19
+
20
+ if(APPLE)
21
+ link_directories(
22
+ v8/out/x64.release
23
+ )
24
+ endif(APPLE)
25
+
26
+ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
27
+ link_directories(
28
+ v8/out/x64.release/obj.target/tools/gyp
29
+ v8/out/x64.release/obj.target/third_party/icu
30
+ )
31
+ endif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
32
+
33
+ add_library(v8eval STATIC
34
+ src/v8eval.cxx
35
+ )
36
+
37
+ set(v8eval-cflags
38
+ -Wall
39
+ -Wendif-labels
40
+ -Werror
41
+ -Wno-missing-field-initializers
42
+ -Wno-unused-parameter
43
+ -Wshorten-64-to-32
44
+ -fPIC
45
+ -fno-exceptions
46
+ -fno-rtti
47
+ -fno-strict-aliasing
48
+ -fno-threadsafe-statics
49
+ -fstrict-aliasing
50
+ -fvisibility=hidden
51
+ -fvisibility-inlines-hidden
52
+ -gdwarf-2
53
+ -std=c++11
54
+ )
55
+
56
+ string(REPLACE ";" " " v8eval-cflags "${v8eval-cflags}")
57
+
58
+ set_target_properties(v8eval PROPERTIES
59
+ COMPILE_FLAGS "${v8eval-cflags}"
60
+ )
61
+
62
+ if(V8EVAL_TEST)
63
+ add_subdirectory(test)
64
+ endif(V8EVAL_TEST)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright 2015 Sony Corporation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # v8eval
2
+
3
+ [![Build Status](https://travis-ci.org/sony/v8eval.svg)](https://travis-ci.org/sony/v8eval)
4
+ [![PyPI version](https://badge.fury.io/py/v8eval.svg)](http://badge.fury.io/py/v8eval)
5
+ [![GoDoc](https://godoc.org/github.com/sony/v8eval/go/v8eval?status.png)](http://godoc.org/github.com/sony/v8eval/go/v8eval)
6
+ [![Gem Version](https://badge.fury.io/rb/v8eval.svg)](https://badge.fury.io/rb/v8eval)
7
+
8
+ Multi-language bindings to JavaScript engine V8.
9
+
10
+ Currently v8eval provides Go, Python and Ruby bindings to the latest V8 4.7 and supports Linux and Mac OS X.
11
+ v8eval uses SWIG and can be extended easily for other languages.
12
+
13
+ ## Pre-installation
14
+
15
+ #### Linux
16
+
17
+ See [Dockerfile](https://github.com/sony/v8eval/blob/master/Dockerfile).
18
+
19
+ #### Mac
20
+
21
+ See [.travis.yml](https://github.com/sony/v8eval/blob/master/.travis.yml).
22
+
23
+ ## Installation
24
+
25
+ The installation takes several tens of minutes due to V8 build.
26
+
27
+ #### Go
28
+
29
+ ```
30
+ git clone https://github.com/sony/v8eval.git $GOPATH/src/github.com/sony/v8eval
31
+ $GOPATH/src/github.com/sony/v8eval/go/build.sh install
32
+ ```
33
+
34
+ #### Python
35
+
36
+ ```
37
+ pip install v8eval
38
+ ```
39
+
40
+ #### Ruby
41
+
42
+ ```
43
+ gem install v8eval
44
+ ```
45
+
46
+
47
+ ## Documentation
48
+
49
+ #### Go
50
+
51
+ See [godoc.org](http://godoc.org/github.com/sony/v8eval/go/v8eval).
52
+
53
+ #### Python
54
+
55
+ You can create the Sphinx documentation under python/docs.
56
+
57
+ ```
58
+ python/build.sh docs
59
+ ```
60
+ #### Ruby
61
+
62
+ You can create the YARD documentation under ruby/doc.
63
+
64
+ ```
65
+ ruby/build.sh docs
66
+ ```
67
+
68
+
69
+ ## Examples
70
+
71
+ #### Go
72
+
73
+ ```go
74
+ import "github.com/sony/v8eval/go/v8eval"
75
+
76
+ func Add(x, y int) int {
77
+ var v8 = v8eval.NewV8()
78
+ v8.Eval("var add = (x, y) => x + y;", nil)
79
+
80
+ var sum int;
81
+ v8.Call("add", []int{x, y}, &sum)
82
+ return sum
83
+ }
84
+ ```
85
+
86
+ #### Python
87
+
88
+ ```python
89
+ import v8eval
90
+
91
+ def add(x, y):
92
+ v8 = v8eval.V8()
93
+ v8.eval('var add = (x, y) => x + y;')
94
+ return v8.call('add', [x, y])
95
+ ```
96
+
97
+ #### Ruby
98
+
99
+ ```ruby
100
+ require 'v8eval'
101
+
102
+ def add(x, y)
103
+ v8 = V8Eval::V8.new
104
+ v8.eval('function add(x, y) { return x + y; }')
105
+ v8.call('add', [x, y])
106
+ end
107
+ ```
108
+
109
+
110
+
111
+ ## License
112
+
113
+ The MIT License (MIT)
114
+
115
+ See [LICENSE](https://github.com/sony/v8eval/blob/master/LICENSE) for details.
data/build.sh ADDED
@@ -0,0 +1,110 @@
1
+ #!/bin/sh
2
+
3
+ V8EVAL_ROOT=`cd $(dirname $0) && pwd`
4
+
5
+ if [ `uname` = "Linux" ] ; then
6
+ export CC=$V8EVAL_ROOT/v8/third_party/llvm-build/Release+Asserts/bin/clang
7
+ export CXX=$V8EVAL_ROOT/v8/third_party/llvm-build/Release+Asserts/bin/clang++
8
+ fi
9
+
10
+ if [ `uname` = "Darwin" ]; then
11
+ export CC=`which clang`
12
+ export CXX=`which clang++`
13
+ export CPP="`which clang` -E"
14
+ export LINK="`which clang++`"
15
+ export CC_host=`which clang`
16
+ export CXX_host=`which clang++`
17
+ export CPP_host="`which clang` -E"
18
+ export LINK_host=`which clang++`
19
+ export GYP_DEFINES="clang=1 mac_deployment_target=10.10"
20
+ fi
21
+
22
+ install_depot_tools() {
23
+ export PATH=$V8EVAL_ROOT/depot_tools:$PATH
24
+ if [ -d $V8EVAL_ROOT/depot_tools ]; then
25
+ return 0
26
+ fi
27
+
28
+ cd $V8EVAL_ROOT
29
+ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
30
+ }
31
+
32
+ install_googletest() {
33
+ if [ -d $V8EVAL_ROOT/test/googletest ]; then
34
+ return 0
35
+ fi
36
+
37
+ cd $V8EVAL_ROOT/test
38
+ git clone https://github.com/google/googletest.git
39
+ git checkout release-1.7.0
40
+ }
41
+
42
+ install_v8() {
43
+ if [ -d $V8EVAL_ROOT/v8 ]; then
44
+ return 0
45
+ fi
46
+
47
+ cd $V8EVAL_ROOT
48
+ fetch v8
49
+ cd v8
50
+ git checkout 4.7.68
51
+ CFLAGS="-fPIC" CXXFLAGS="-fPIC" make x64.release V=1
52
+ }
53
+
54
+ build() {
55
+ install_depot_tools
56
+ install_v8
57
+
58
+ cd $V8EVAL_ROOT
59
+ mkdir -p build
60
+ cd build
61
+ cmake -DCMAKE_BUILD_TYPE=Release -DV8EVAL_TEST=OFF ..
62
+ make VERBOSE=1
63
+ }
64
+
65
+ build_go() {
66
+ $V8EVAL_ROOT/go/build.sh
67
+ }
68
+
69
+ build_python() {
70
+ $V8EVAL_ROOT/python/build.sh
71
+ }
72
+
73
+ build_ruby() {
74
+ $V8EVAL_ROOT/ruby/build.sh
75
+ }
76
+
77
+ docs() {
78
+ cd $V8EVAL_ROOT/docs
79
+ rm -rf ./html
80
+ doxygen
81
+
82
+ $V8EVAL_ROOT/python/build.sh docs
83
+ }
84
+
85
+ test() {
86
+ build
87
+ install_googletest
88
+
89
+ cd $V8EVAL_ROOT/build
90
+ cmake -DCMAKE_BUILD_TYPE=Release -DV8EVAL_TEST=ON ..
91
+ make VERBOSE=1
92
+ ./test/v8eval-test || exit 1
93
+
94
+ cd ..
95
+ ./go/build.sh test || exit 1
96
+ ./python/build.sh test || exit 1
97
+ ./ruby/build.sh test || exit 1
98
+ }
99
+
100
+ # dispatch subcommand
101
+ SUBCOMMAND="$1";
102
+ case "${SUBCOMMAND}" in
103
+ "" ) build ;;
104
+ "go" ) build_go ;;
105
+ "python" ) build_python ;;
106
+ "ruby" ) build_ruby ;;
107
+ "docs" ) docs ;;
108
+ "test" ) test ;;
109
+ * ) echo "unknown subcommand: ${SUBCOMMAND}"; exit 1 ;;
110
+ esac
data/ruby/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # run `bundle install` on this file to install development dependencies.
2
+ source "https://rubygems.org"
3
+
4
+ gem 'rspec', '~> 3.0'
5
+ gem 'rake', '~> 10.4.2'
6
+ gem 'yard', '~> 0.8.7.6'
data/ruby/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ # Rakefile
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require_relative 'lib/setup/extension_builder'
5
+
6
+ CLEAN.include('ext/**/*{.o,.log,.so,.bundle}')
7
+ CLEAN.include('ext/**/Makefile')
8
+
9
+ # set path variable
10
+ v8eval_root = File.expand_path('..', Dir.pwd)
11
+
12
+ # make instance of BuildTool class
13
+ tool = BuildTool.new(v8eval_root)
14
+
15
+ desc 'task to prepare for the build'
16
+ task :prepare_build do
17
+ tool.run_swig
18
+ end
19
+
20
+ desc 'install v8 and build libv8eval.a'
21
+ task :install_v8 do
22
+ tool.install_v8
23
+ end
24
+
25
+ desc 'build v8eval{.so,.dll,.bundle}'
26
+ task :build_ext do
27
+ tool.build_ext
28
+ end
data/ruby/build.sh ADDED
@@ -0,0 +1,43 @@
1
+ #!/bin/sh
2
+
3
+ V8EVAL_ROOT=`cd $(dirname $0)/.. && pwd`
4
+
5
+ build() {
6
+ cd $V8EVAL_ROOT/ruby && rake prepare_build
7
+ cd $V8EVAL_ROOT && gem build v8eval.gemspec
8
+ }
9
+
10
+
11
+ install() {
12
+ cd $V8EVAL_ROOT
13
+ gem install v8eval-*.gem
14
+ }
15
+
16
+ docs() {
17
+ cd $V8EVAL_ROOT/ruby
18
+ rm -rf ./doc
19
+ mkdir ./doc
20
+ yardoc --main ../README.md lib/v8eval.rb
21
+ }
22
+
23
+ test() {
24
+ build
25
+
26
+ gem install bundle
27
+ cd $V8EVAL_ROOT/ruby
28
+ bundle install
29
+
30
+ rake install_v8 && rake build_ext
31
+ rspec
32
+ }
33
+
34
+
35
+ # dispatch subcommand
36
+ SUBCOMMAND="$1";
37
+ case "${SUBCOMMAND}" in
38
+ "" ) build ;;
39
+ "install" ) install ;;
40
+ "docs" ) docs ;;
41
+ "test" ) test ;;
42
+ * ) echo "unknown subcommand: ${SUBCOMMAND}"; exit 1 ;;
43
+ esac
@@ -0,0 +1,9 @@
1
+ require 'v8eval'
2
+
3
+ def add(x, y)
4
+ v8 = V8Eval::V8.new
5
+ v8.eval('function add(x, y) { return x + y; }')
6
+ v8.call('add', [x, y])
7
+ end
8
+
9
+ puts add(1, 2)
@@ -0,0 +1,53 @@
1
+ # extconf.rb
2
+ require 'rbconfig'
3
+ require 'mkmf'
4
+ require_relative '../../lib/setup/extension_builder'
5
+
6
+ # set path variables
7
+ v8eval_root = File.expand_path('../../..', Dir.pwd)
8
+ v8_dir = v8eval_root + '/v8'
9
+
10
+ # make instance of BuildTool class
11
+ tool = BuildTool.new(v8eval_root)
12
+
13
+ # install v8 and build libv8eval.a
14
+ tool.install_v8
15
+
16
+ # generate v8eval_wrap.cxx
17
+ tool.run_swig
18
+
19
+ LIBDIR = RbConfig::CONFIG['libdir']
20
+ INCLUDEDIR = RbConfig::CONFIG['includedir']
21
+
22
+ HEADER_DIRS = [
23
+ v8_dir,
24
+ v8_dir + '/include',
25
+ INCLUDEDIR
26
+ ]
27
+
28
+ LIB_DIRS = [
29
+ v8eval_root + '/build',
30
+ LIBDIR
31
+ ]
32
+ if RUBY_PLATFORM =~ /darwin/
33
+ LIB_DIRS += [
34
+ v8_dir + '/out/x64.release'
35
+ ]
36
+ elsif RUBY_PLATFORM =~ /linux/
37
+ LIB_DIRS += [
38
+ v8_dir + '/out/x64.release/obj.target/tools/gyp',
39
+ v8_dir + '/out/x64.release/obj.target/third_party/icu'
40
+ ]
41
+ end
42
+
43
+ dir_config('', HEADER_DIRS, LIB_DIRS)
44
+
45
+ $LDFLAGS << ' -lv8eval -lv8_libplatform -lv8_base -lv8_libbase -lv8_nosnapshot -licui18n -licuuc -licudata'
46
+ if RUBY_PLATFORM =~ /linux/
47
+ $LDFLAGS << ' -ldl -lpthread'
48
+ $CPPFLAGS << ' -g -O3 -std=c++11'
49
+ elsif RUBY_PLATFORM =~ /darwin/
50
+ $CXXFLAGS << ' -g -O3 -std=c++11'
51
+ end
52
+
53
+ create_makefile('v8eval/v8eval')
@@ -0,0 +1,30 @@
1
+ # BuildTool is a util class that is used to do some build tasks
2
+ class BuildTool
3
+ def initialize(path)
4
+ @v8eval_root = path
5
+ @rb_dir = @v8eval_root + '/ruby'
6
+ @rb_ext_dir = @rb_dir + '/ext'
7
+ @rb_ext_v8eval_dir = @rb_ext_dir + '/v8eval'
8
+ end
9
+
10
+ def install_v8
11
+ Dir.chdir @v8eval_root do
12
+ system('./build.sh')
13
+ end
14
+ end
15
+
16
+ def run_swig
17
+ system('cp ' + @v8eval_root + '/src/v8eval.h ' + @rb_ext_v8eval_dir)
18
+ system('swig -c++ -ruby -autorename -outdir ' + @rb_ext_v8eval_dir +
19
+ ' -o ' + @rb_ext_v8eval_dir + '/v8eval_wrap.cxx ' + @v8eval_root +
20
+ '/src/v8eval.i')
21
+ end
22
+
23
+ def build_ext
24
+ Dir.chdir @rb_ext_v8eval_dir do
25
+ system('ruby extconf.rb')
26
+ system('make')
27
+ system('make install')
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,60 @@
1
+ # require 'v8eval/v8eval' loads the V8eval module built by swig-generated extension
2
+ require 'v8eval/v8eval'
3
+
4
+ require 'json'
5
+
6
+ module V8Eval
7
+ # Represents a V8 instance.
8
+ class V8
9
+ def initialize
10
+ @v8 = V8eval::V8.new
11
+ end
12
+
13
+ # Evaluates JavaScript code.
14
+ # @param [String] src JavaScript code.
15
+ # @return
16
+ # The result of the JavaScript code. The result is marshalled/unmarshalled by using JSON.
17
+ # @raise [TypeError] If src is not a string.
18
+ # @raise [RuntimeError] If some JavaScript exception happens.
19
+ def eval(src)
20
+ fail TypeError unless src.is_a?(String)
21
+ res = @v8.eval(src)
22
+ if res == 'undefined'
23
+ return nil
24
+ else
25
+ begin
26
+ return JSON.load(res)
27
+ rescue StandardError => e
28
+ raise e.message
29
+ end
30
+ end
31
+ end
32
+
33
+ # Calls a JavaScript function.
34
+ # @param [String] func Name of a JavaScript function.
35
+ # @param [Array] args Argument list to pass.
36
+ # @return
37
+ # The result of the JavaScript code. The result is marshalled/unmarshalled by using JSON.
38
+ # @raise [TypeError] If either func is not a string or args is not a array.
39
+ # @raise [RuntimeError] If some JavaScript exception happens.
40
+ def call(func, args)
41
+ fail TypeError unless func.is_a?(String)
42
+ fail TypeError unless args.is_a?(Array)
43
+
44
+ args_str = JSON.dump(args)
45
+ res = @v8.call(func, args_str)
46
+ if res == 'undefined'
47
+ return nil
48
+ else
49
+ begin
50
+ return JSON.load(res)
51
+ rescue StandardError => e
52
+ raise e.message
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ # initialize the V8 runtime environment
60
+ V8eval.initialize
@@ -0,0 +1,96 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ RSpec.configure do |config|
20
+ # rspec-expectations config goes here. You can use an alternate
21
+ # assertion/expectation library such as wrong or the stdlib/minitest
22
+ # assertions if you prefer.
23
+ config.expect_with :rspec do |expectations|
24
+ # This option will default to `true` in RSpec 4. It makes the `description`
25
+ # and `failure_message` of custom matchers include text for helper methods
26
+ # defined using `chain`, e.g.:
27
+ # be_bigger_than(2).and_smaller_than(4).description
28
+ # # => "be bigger than 2 and smaller than 4"
29
+ # ...rather than:
30
+ # # => "be bigger than 2"
31
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
+ end
33
+
34
+ # rspec-mocks config goes here. You can use an alternate test double
35
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
36
+ config.mock_with :rspec do |mocks|
37
+ # Prevents you from mocking or stubbing a method that does not exist on
38
+ # a real object. This is generally recommended, and will default to
39
+ # `true` in RSpec 4.
40
+ mocks.verify_partial_doubles = true
41
+ end
42
+
43
+ # The settings below are suggested to provide a good initial experience
44
+ # with RSpec, but feel free to customize to your heart's content.
45
+ =begin
46
+ # These two settings work together to allow you to limit a spec run
47
+ # to individual examples or groups you care about by tagging them with
48
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
49
+ # get run.
50
+ config.filter_run :focus
51
+ config.run_all_when_everything_filtered = true
52
+
53
+ # Allows RSpec to persist some state between runs in order to support
54
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
55
+ # you configure your source control system to ignore this file.
56
+ config.example_status_persistence_file_path = "spec/examples.txt"
57
+
58
+ # Limits the available syntax to the non-monkey patched syntax that is
59
+ # recommended. For more details, see:
60
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
61
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
62
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
63
+ config.disable_monkey_patching!
64
+
65
+ # This setting enables warnings. It's recommended, but in some cases may
66
+ # be too noisy due to issues in dependencies.
67
+ config.warnings = true
68
+
69
+ # Many RSpec users commonly either run the entire suite or an individual
70
+ # file, and it's useful to allow more verbose output when running an
71
+ # individual spec file.
72
+ if config.files_to_run.one?
73
+ # Use the documentation formatter for detailed output,
74
+ # unless a formatter has already been configured
75
+ # (e.g. via a command-line flag).
76
+ config.default_formatter = 'doc'
77
+ end
78
+
79
+ # Print the 10 slowest examples and example groups at the
80
+ # end of the spec run, to help surface which specs are running
81
+ # particularly slow.
82
+ config.profile_examples = 10
83
+
84
+ # Run specs in random order to surface order dependencies. If you find an
85
+ # order dependency and want to debug it, you can fix the order by providing
86
+ # the seed, which is printed after each run.
87
+ # --seed 1234
88
+ config.order = :random
89
+
90
+ # Seed global randomization in this process using the `--seed` CLI option.
91
+ # Setting this allows you to use `--seed` to deterministically reproduce
92
+ # test failures related to randomization by passing the same `--seed` value
93
+ # as the one that triggered the failure.
94
+ Kernel.srand config.seed
95
+ =end
96
+ end
@@ -0,0 +1,58 @@
1
+ require 'v8eval'
2
+
3
+ RSpec.describe V8Eval, '#eval' do
4
+ context 'with vaild source code' do
5
+ it 'should evaluate the source code' do
6
+ v8 = V8Eval::V8.new
7
+ expect(v8.eval('1+2')).to eq 3
8
+ expect(v8.eval('var p = { x: 1.1, y: 2.2 }; p')).to eq('x' => 1.1,
9
+ 'y' => 2.2)
10
+ expect(v8.eval('')).to eq nil
11
+
12
+ expect { v8.eval(nil) }.to raise_exception(TypeError)
13
+ expect { v8.eval('foo') }.to raise_exception(RuntimeError)
14
+ end
15
+ end
16
+ end
17
+
18
+ RSpec.describe V8Eval, '#call' do
19
+ context 'with valid function and arguments' do
20
+ it 'should evaluate the given function' do
21
+ v8 = V8Eval::V8.new
22
+ v8.eval('function inc(x) { return x + 1; }')
23
+ expect(v8.call('inc', [7])).to eq 8
24
+
25
+ expect { v8.call(nil, [7]) }.to raise_exception(TypeError)
26
+ expect { v8.call('inc', nil) }.to raise_exception(TypeError)
27
+ expect { v8.call('i', [7]) }.to raise_exception(RuntimeError)
28
+ end
29
+ end
30
+ end
31
+
32
+ RSpec.describe V8Eval, '#multithreading' do
33
+ context 'with multithread execution' do
34
+ it 'should execute concurrently' do
35
+ def v8_thread(num)
36
+ num_repeat = num
37
+ v8 = V8Eval::V8.new
38
+ counter = 0
39
+ thread = Thread.new do
40
+ v8.eval('function inc(x) { return x + 1; }')
41
+ num_repeat.times do
42
+ counter = v8.call('inc', [counter])
43
+ end
44
+ expect(counter).to eq(num_repeat)
45
+ end
46
+ thread
47
+ end
48
+
49
+ num_repeat = 10_000
50
+
51
+ thread1 = v8_thread(num_repeat)
52
+ thread2 = v8_thread(num_repeat)
53
+
54
+ thread1.join
55
+ thread2.join
56
+ end
57
+ end
58
+ end
data/src/v8eval.cxx ADDED
@@ -0,0 +1,185 @@
1
+ #include "v8eval.h"
2
+
3
+ #include <stdlib.h>
4
+ #include <string.h>
5
+
6
+ #include "libplatform/libplatform.h"
7
+
8
+ namespace v8eval {
9
+
10
+ static v8::Platform* platform = nullptr;
11
+
12
+ bool initialize() {
13
+ if (platform) {
14
+ return false;
15
+ }
16
+
17
+ if (!v8::V8::InitializeICU()) {
18
+ return false;
19
+ }
20
+
21
+ platform = v8::platform::CreateDefaultPlatform();
22
+ v8::V8::InitializePlatform(platform);
23
+
24
+ return v8::V8::Initialize();
25
+ }
26
+
27
+ bool dispose() {
28
+ if (!platform) {
29
+ return false;
30
+ }
31
+
32
+ v8::V8::Dispose();
33
+
34
+ v8::V8::ShutdownPlatform();
35
+ delete platform;
36
+ platform = nullptr;
37
+
38
+ return true;
39
+ }
40
+
41
+ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
42
+ public:
43
+ virtual void* Allocate(size_t length) {
44
+ void* data = AllocateUninitialized(length);
45
+ return data == NULL ? data : memset(data, 0, length);
46
+ }
47
+
48
+ virtual void* AllocateUninitialized(size_t length) {
49
+ return malloc(length);
50
+ }
51
+
52
+ virtual void Free(void* data, size_t) {
53
+ free(data);
54
+ }
55
+ };
56
+
57
+ static ArrayBufferAllocator allocator;
58
+
59
+ _V8::_V8() {
60
+ v8::Isolate::CreateParams create_params;
61
+ create_params.array_buffer_allocator = &allocator;
62
+ isolate_ = v8::Isolate::New(create_params);
63
+
64
+ v8::Locker locker(isolate_);
65
+
66
+ v8::Isolate::Scope isolate_scope(isolate_);
67
+ v8::HandleScope handle_scope(isolate_);
68
+ context_.Reset(isolate_, new_context());
69
+ }
70
+
71
+ _V8::~_V8() {
72
+ context_.Reset();
73
+
74
+ isolate_->Dispose();
75
+ }
76
+
77
+ v8::Local<v8::Context> _V8::new_context() {
78
+ if (context_.IsEmpty()) {
79
+ v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_);
80
+ return v8::Context::New(isolate_, nullptr, global);
81
+ } else {
82
+ return v8::Local<v8::Context>::New(isolate_, context_);
83
+ }
84
+ }
85
+
86
+ v8::Local<v8::String> _V8::new_string(const char* str) {
87
+ return v8::String::NewFromUtf8(isolate_, str ? str : "", v8::NewStringType::kNormal).ToLocalChecked();
88
+ }
89
+
90
+ static std::string to_std_string(v8::Local<v8::Value> value) {
91
+ v8::String::Utf8Value str(value);
92
+ return *str ? *str : "Error: Cannot convert to string";
93
+ }
94
+
95
+ v8::Local<v8::Value> _V8::json_parse(v8::Local<v8::Context> context, v8::Local<v8::String> str) {
96
+ v8::Local<v8::Object> global = context->Global();
97
+ v8::Local<v8::Object> json = global->Get(context, new_string("JSON")).ToLocalChecked()->ToObject();
98
+ v8::Local<v8::Function> parse = v8::Local<v8::Function>::Cast(json->Get(context, new_string("parse")).ToLocalChecked());
99
+
100
+ v8::Local<v8::Value> result;
101
+ v8::Local<v8::Value> value = str;
102
+ if (!parse->Call(context, json, 1, &value).ToLocal(&result)) {
103
+ return v8::Local<v8::Value>(); // empty
104
+ } else {
105
+ return result;
106
+ }
107
+ }
108
+
109
+ v8::Local<v8::String> _V8::json_stringify(v8::Local<v8::Context> context, v8::Local<v8::Value> value) {
110
+ v8::Local<v8::Object> global = context->Global();
111
+ v8::Local<v8::Object> json = global->Get(context, new_string("JSON")).ToLocalChecked()->ToObject();
112
+ v8::Local<v8::Function> stringify = v8::Local<v8::Function>::Cast(json->Get(context, new_string("stringify")).ToLocalChecked());
113
+
114
+ v8::Local<v8::Value> result;
115
+ if (!stringify->Call(context, json, 1, &value).ToLocal(&result)) {
116
+ return new_string("");
117
+ } else {
118
+ return result->ToString();
119
+ }
120
+ }
121
+
122
+ std::string _V8::eval(const std::string& src) {
123
+ v8::Locker locker(isolate_);
124
+
125
+ v8::Isolate::Scope isolate_scope(isolate_);
126
+ v8::HandleScope handle_scope(isolate_);
127
+
128
+ v8::Local<v8::Context> context = new_context();
129
+ v8::Context::Scope context_scope(context);
130
+
131
+ v8::TryCatch try_catch(isolate_);
132
+
133
+ v8::Local<v8::String> source = new_string(src.c_str());
134
+
135
+ v8::Local<v8::String> name = new_string("v8eval");
136
+ v8::ScriptOrigin origin(name);
137
+
138
+ v8::Local<v8::Script> script;
139
+ if (!v8::Script::Compile(context, source, &origin).ToLocal(&script)) {
140
+ return to_std_string(try_catch.Exception());
141
+ } else {
142
+ v8::Local<v8::Value> result;
143
+ if (!script->Run(context).ToLocal(&result)) {
144
+ return to_std_string(try_catch.Exception());
145
+ } else {
146
+ return to_std_string(json_stringify(context, result));
147
+ }
148
+ }
149
+ }
150
+
151
+ std::string _V8::call(const std::string& func, const std::string& args) {
152
+ v8::Locker locker(isolate_);
153
+
154
+ v8::Isolate::Scope isolate_scope(isolate_);
155
+ v8::HandleScope handle_scope(isolate_);
156
+
157
+ v8::Local<v8::Context> context = new_context();
158
+ v8::Context::Scope context_scope(context);
159
+
160
+ v8::TryCatch try_catch(isolate_);
161
+
162
+ v8::Local<v8::Object> global = context->Global();
163
+ v8::Local<v8::Value> result;
164
+ if (!global->Get(context, new_string(func.c_str())).ToLocal(&result)) {
165
+ return to_std_string(try_catch.Exception());
166
+ } else if (!result->IsFunction()) {
167
+ return "TypeError: '" + func + "' is not a function";
168
+ }
169
+
170
+ v8::Local<v8::Function> function = v8::Handle<v8::Function>::Cast(result);
171
+ v8::Local<v8::Function> apply = v8::Handle<v8::Function>::Cast(function->Get(context, new_string("apply")).ToLocalChecked());
172
+ v8::Local<v8::Value> arguments = json_parse(context, new_string(args.c_str()));
173
+ if (arguments.IsEmpty() || !arguments->IsArray()) {
174
+ return "TypeError: '" + args + "' is not an array";
175
+ }
176
+
177
+ v8::Local<v8::Value> values[] = { function, arguments };
178
+ if (!apply->Call(context, function, 2, values).ToLocal(&result)) {
179
+ return to_std_string(try_catch.Exception());
180
+ } else {
181
+ return to_std_string(json_stringify(context, result));
182
+ }
183
+ }
184
+
185
+ } // namespace v8eval
data/src/v8eval.h ADDED
@@ -0,0 +1,64 @@
1
+ #ifndef V8EVAL_H_
2
+ #define V8EVAL_H_
3
+
4
+ #include <string>
5
+
6
+ #include "v8.h"
7
+
8
+ /// \file
9
+ namespace v8eval {
10
+
11
+ /// \brief Initialize the V8 runtime environment
12
+ /// \return success or not as boolean
13
+ ///
14
+ /// This method initializes the V8 runtime environment. It must be called before creating any V8 instance.
15
+ bool initialize();
16
+
17
+ /// \brief Dispose the V8 runtime environment
18
+ /// \return success or not as boolean
19
+ ///
20
+ /// This method disposes the V8 runtime environment.
21
+ bool dispose();
22
+
23
+ /// \class _V8
24
+ ///
25
+ /// _V8 instances can be used in multiple threads.
26
+ /// But each _V8 instance can be used in only one thread at a time.
27
+ class _V8 {
28
+ public:
29
+ _V8();
30
+ virtual ~_V8();
31
+
32
+ /// \brief Evaluate JavaScript code
33
+ /// \param src JavaScript code
34
+ /// \return JSON-encoded result or exception message
35
+ ///
36
+ /// This method evaluates the given JavaScript code 'src' and returns the result in JSON.
37
+ /// If some JavaScript exception happens in runtime, the exception message is returned.
38
+ std::string eval(const std::string& src);
39
+
40
+ /// \brief Call a JavaScript function
41
+ /// \param func Name of a JavaScript function
42
+ /// \param args JSON-encoded argument array
43
+ /// \return JSON-encoded result or exception message
44
+ ///
45
+ /// This method calls the JavaScript function specified by 'func'
46
+ /// with the JSON-encoded argument array 'args'
47
+ /// and returns the result in JSON.
48
+ /// If some JavaScript exception happens in runtime, the exception message is returned.
49
+ std::string call(const std::string& func, const std::string& args);
50
+
51
+ private:
52
+ v8::Local<v8::Context> new_context();
53
+ v8::Local<v8::String> new_string(const char* str);
54
+ v8::Local<v8::Value> json_parse(v8::Local<v8::Context> context, v8::Local<v8::String> str);
55
+ v8::Local<v8::String> json_stringify(v8::Local<v8::Context> context, v8::Local<v8::Value> value);
56
+
57
+ private:
58
+ v8::Isolate* isolate_;
59
+ v8::Persistent<v8::Context> context_;
60
+ };
61
+
62
+ } // namespace v8eval
63
+
64
+ #endif // V8EVAL_H_
data/src/v8eval.i ADDED
@@ -0,0 +1,9 @@
1
+ %module v8eval
2
+ %include "std_string.i"
3
+
4
+ %{
5
+ #define SWIG_FILE_WITH_INIT
6
+ #include "v8eval.h"
7
+ %}
8
+
9
+ %include "v8eval.h"
data/v8eval.gemspec ADDED
@@ -0,0 +1,26 @@
1
+
2
+
3
+ Gem::Specification.new 'v8eval', '1.0' do |s|
4
+ s.name = 'v8eval'
5
+ s.version = '0.1.3'
6
+ s.licenses = ['MIT']
7
+ s.description = 'Run JavaScript engine V8 in Ruby'
8
+ s.summary = 'v8eval gem is ruby binding to the latest V8 4.7 and
9
+ supports Linux and Mac OS X.'
10
+ s.authors = ['Prateek Papriwal']
11
+ s.email = 'papriwalprateek@gmail.com'
12
+ s.homepage = 'https://github.com/sony/v8eval'
13
+ s.extra_rdoc_files = ['README.md']
14
+
15
+ s.files = Dir['ruby/**/*'] + Dir['src/**/*'] + Dir['build.sh']
16
+ s.files += Dir['LICENSE'] + Dir['README.md'] + Dir['CMakeLists.txt'] + Dir['v8eval.gemspec']
17
+ s.platform = Gem::Platform::RUBY
18
+ s.require_paths = ['ruby/lib', 'ruby/ext']
19
+ s.extensions = Dir['ruby/ext/**/extconf.rb']
20
+
21
+ s.add_development_dependency 'rake', '~> 10.4', '>= 10.4.2'
22
+ s.add_development_dependency 'rspec', '~> 3.0'
23
+ s.add_development_dependency 'yard', '0.8.7.6'
24
+
25
+ s.required_ruby_version = '>= 2.0.0'
26
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: v8eval
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Prateek Papriwal
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '10.4'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 10.4.2
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '10.4'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 10.4.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: yard
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - '='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.8.7.6
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '='
59
+ - !ruby/object:Gem::Version
60
+ version: 0.8.7.6
61
+ description: Run JavaScript engine V8 in Ruby
62
+ email: papriwalprateek@gmail.com
63
+ executables: []
64
+ extensions:
65
+ - ruby/ext/v8eval/extconf.rb
66
+ extra_rdoc_files:
67
+ - README.md
68
+ files:
69
+ - CMakeLists.txt
70
+ - LICENSE
71
+ - README.md
72
+ - build.sh
73
+ - ruby/Gemfile
74
+ - ruby/Rakefile
75
+ - ruby/build.sh
76
+ - ruby/example/js_add.rb
77
+ - ruby/ext/v8eval/extconf.rb
78
+ - ruby/lib/setup/extension_builder.rb
79
+ - ruby/lib/v8eval.rb
80
+ - ruby/spec/spec_helper.rb
81
+ - ruby/spec/v8eval_spec.rb
82
+ - src/v8eval.cxx
83
+ - src/v8eval.h
84
+ - src/v8eval.i
85
+ - v8eval.gemspec
86
+ homepage: https://github.com/sony/v8eval
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - ruby/lib
94
+ - ruby/ext
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 2.0.0
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.4.6
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: v8eval gem is ruby binding to the latest V8 4.7 and supports Linux and Mac
111
+ OS X.
112
+ test_files: []
113
+ has_rdoc: