v8eval 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: