├── .gitignore ├── .dir-locals.el ├── v8-sys ├── src │ ├── v8-trampoline.h │ ├── lib.rs │ ├── v8-glue.h │ └── v8-glue.cc ├── Cargo.toml └── build.rs ├── .editorconfig ├── examples └── hello-world.rs ├── v8-api ├── src │ ├── bin │ │ └── v8-api-rs-parse.rs │ └── lib.rs └── Cargo.toml ├── Cargo.toml ├── src ├── allocator.rs ├── context.rs ├── script.rs ├── platform.rs ├── template.rs ├── util.rs ├── error.rs ├── isolate.rs └── lib.rs ├── .travis.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | *.bk 4 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((rust-mode . ((fill-column . 100)))) 2 | -------------------------------------------------------------------------------- /v8-sys/src/v8-trampoline.h: -------------------------------------------------------------------------------- 1 | // v8-trampoline.h: includes the files containing the V8 APIs we want 2 | // to wrap. 3 | #include 4 | #include 5 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | indent_style = space 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | 9 | [*.rs] 10 | indent_size = 4 11 | 12 | [*.js] 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /v8-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_camel_case_types)] 2 | #![allow(non_snake_case)] 3 | #![allow(non_upper_case_globals)] 4 | 5 | #[cfg(test)] 6 | #[macro_use] 7 | extern crate lazy_static; 8 | 9 | include!(concat!(env!("OUT_DIR"), "/ffi.rs")); 10 | 11 | pub use ffi::*; 12 | -------------------------------------------------------------------------------- /examples/hello-world.rs: -------------------------------------------------------------------------------- 1 | extern crate v8; 2 | 3 | use v8::value; 4 | 5 | fn main() { 6 | let isolate = v8::Isolate::new(); 7 | let context = v8::Context::new(&isolate); 8 | 9 | let source = value::String::from_str(&isolate, "'Hello, ' + 'World!'"); 10 | let script = v8::Script::compile(&isolate, &context, &source).unwrap(); 11 | 12 | let result = script.run(&context).unwrap(); 13 | let result_str = result.to_string(&context); 14 | 15 | println!("{}", result_str.value()); 16 | } 17 | -------------------------------------------------------------------------------- /v8-api/src/bin/v8-api-rs-parse.rs: -------------------------------------------------------------------------------- 1 | extern crate env_logger; 2 | extern crate v8_api; 3 | 4 | use std::env; 5 | use std::path; 6 | 7 | fn main() { 8 | env_logger::init().unwrap(); 9 | 10 | let header_file_path = if let Some(path) = env::args_os().nth(1) { 11 | path::PathBuf::from(path) 12 | } else if let Some(path) = env::var_os("V8_SOURCE") { 13 | path::PathBuf::from(path).join("include").join("v8.h") 14 | } else { 15 | path::Path::new("/usr/include/v8.h").to_path_buf() 16 | }; 17 | 18 | print!("{}", v8_api::read(&header_file_path, &[] as &[&path::Path])); 19 | } 20 | -------------------------------------------------------------------------------- /v8-api/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["David Flemström "] 3 | description = "A parser for v8.h files to extract a description of the V8 API heuristically. Used in build scripts, for example in v8-sys." 4 | homepage = "https://dflemstr.github.io/v8-rs" 5 | keywords = ["v8", "javascript", "api"] 6 | license = "Apache-2.0" 7 | name = "v8-api" 8 | repository = "https://github.com/dflemstr/v8-rs/tree/master/v8-api" 9 | version = "0.7.3" 10 | 11 | [dependencies] 12 | env_logger = "0.4.0" 13 | log = "0.3.6" 14 | 15 | [dependencies.clang] 16 | features = ["clang_3_5", "runtime"] 17 | version = "0.15.0" 18 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["David Flemström "] 3 | description = "High-level bindings to V8, the Javascript engine" 4 | documentation = "https://dflemstr.github.io/v8-rs/v8/index.html" 5 | homepage = "https://dflemstr.github.io/v8-rs" 6 | keywords = ["v8", "javascript", "js", "ecmascript", "google"] 7 | license = "Apache-2.0" 8 | name = "v8" 9 | repository = "https://github.com/dflemstr/v8-rs" 10 | version = "0.9.6" 11 | 12 | [dependencies] 13 | error-chain = "0.9.0" 14 | lazy_static = "0.2.1" 15 | num_cpus = "1.1.0" 16 | 17 | [dependencies.v8-sys] 18 | path = "v8-sys" 19 | version = "0.14.0" 20 | 21 | [features] 22 | shared = ["v8-sys/shared"] 23 | unstable = [] 24 | -------------------------------------------------------------------------------- /v8-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["David Flemström "] 3 | build = "build.rs" 4 | description = "Low-level bindings to V8, the Javascript engine" 5 | documentation = "https://dflemstr.github.io/v8-rs/v8_sys/index.html" 6 | homepage = "https://dflemstr.github.io/v8-rs" 7 | include = ["build.rs", "src/**/*", "Cargo.toml"] 8 | keywords = ["v8", "javascript", "js", "ecmascript", "google"] 9 | license = "Apache-2.0" 10 | name = "v8-sys" 11 | repository = "https://github.com/dflemstr/v8-rs/tree/master/v8-sys" 12 | version = "0.14.7" 13 | 14 | [build-dependencies] 15 | bindgen = "0.22.0" 16 | gcc = "0.3.38" 17 | pkg-config = "0.3.8" 18 | 19 | [build-dependencies.clang] 20 | features = ["runtime"] 21 | version = "0.15.0" 22 | 23 | [build-dependencies.clang-sys] 24 | features = ["runtime"] 25 | version = "0.14.0" 26 | 27 | [build-dependencies.v8-api] 28 | path = "../v8-api" 29 | version = "0.7.0" 30 | 31 | [dev-dependencies] 32 | lazy_static = "0.2.1" 33 | 34 | [features] 35 | shared = [] 36 | -------------------------------------------------------------------------------- /src/allocator.rs: -------------------------------------------------------------------------------- 1 | //! Allocators for array buffers. 2 | use v8_sys as v8; 3 | 4 | use std::os; 5 | use std::mem; 6 | 7 | /// A simple array buffer allocator that guarantees that all allocated 8 | /// blocks are coercible to `Vec`s. 9 | #[derive(Debug)] 10 | pub struct Allocator(v8::ArrayBuffer_AllocatorPtr); 11 | 12 | impl Allocator { 13 | /// Creates a new allocator. 14 | pub fn new() -> Allocator { 15 | let raw = unsafe { v8::v8_ArrayBuffer_Allocator_Create(ALLOCATOR_FUNCTIONS) }; 16 | if raw.is_null() { 17 | panic!("Could not create ArrayBuffer::Allocator"); 18 | } 19 | 20 | Allocator(raw) 21 | } 22 | 23 | /// Returns the underlying raw pointer behind this allocator. 24 | pub fn as_raw(&self) -> v8::ArrayBuffer_AllocatorPtr { 25 | self.0 26 | } 27 | } 28 | 29 | impl Drop for Allocator { 30 | fn drop(&mut self) { 31 | unsafe { 32 | v8::v8_ArrayBuffer_Allocator_Destroy(self.0); 33 | } 34 | } 35 | } 36 | 37 | const ALLOCATOR_FUNCTIONS: v8::v8_AllocatorFunctions = v8::v8_AllocatorFunctions { 38 | Allocate: Some(allocate), 39 | AllocateUninitialized: Some(allocate_uninitialized), 40 | Free: Some(free), 41 | }; 42 | 43 | extern "C" fn allocate(length: usize) -> *mut os::raw::c_void { 44 | let mut data = Vec::with_capacity(length); 45 | data.resize(length, 0u8); 46 | let ptr = data.as_mut_ptr(); 47 | mem::forget(data); 48 | 49 | ptr as *mut os::raw::c_void 50 | } 51 | 52 | extern "C" fn allocate_uninitialized(length: usize) -> *mut os::raw::c_void { 53 | let mut data = Vec::with_capacity(length); 54 | 55 | unsafe { 56 | data.set_len(length); 57 | } 58 | 59 | let ptr = data.as_mut_ptr(); 60 | mem::forget(data); 61 | 62 | ptr as *mut os::raw::c_void 63 | } 64 | 65 | unsafe extern "C" fn free(data: *mut os::raw::c_void, length: usize) { 66 | // TODO: restore `cap` here? Can this possibly leak memory? 67 | drop(Vec::from_raw_parts(data, length, length)); 68 | } 69 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: true 2 | dist: trusty 3 | language: rust 4 | 5 | addons: 6 | apt: 7 | sources: 8 | - sourceline: 'ppa:pinepain/libv8-5.4' 9 | - ubuntu-toolchain-r-test 10 | packages: 11 | # Modern compilers 12 | - gcc-6 13 | - g++-6 14 | # The V8 version that we want to bind 15 | - libv8-5.4-dev 16 | - libicu-dev 17 | # Dependencies for travis-cargo and for coverage 18 | - libcurl4-openssl-dev 19 | - libelf-dev 20 | - libdw-dev 21 | - binutils-dev 22 | 23 | matrix: 24 | include: 25 | - env: FEATURES="" CC=gcc-6 CXX=g++-6 26 | rust: stable 27 | os: linux 28 | - env: FEATURES="--features=shared" CC=gcc-6 CXX=g++-6 29 | rust: stable 30 | os: linux 31 | - env: FEATURES="--features=shared" 32 | rust: stable 33 | os: osx 34 | osx_image: xcode8 35 | - env: FEATURES="" CC=gcc-6 CXX=g++-6 36 | rust: nightly 37 | os: linux 38 | - env: FEATURES="--features=shared" CC=gcc-6 CXX=g++-6 39 | rust: nightly 40 | os: linux 41 | allow_failures: 42 | - rust: nightly 43 | 44 | before_install: 45 | - | 46 | if [ "$TRAVIS_OS_NAME" = osx ] 47 | then 48 | brew tap dflemstr/tools 49 | brew update 50 | brew install -v dflemstr/tools/v8 51 | fi 52 | 53 | before_script: 54 | - | 55 | pip install 'travis-cargo<0.2' --user && 56 | export PATH=$HOME/.local/bin:$HOME/Library/Python/2.7/bin:$PATH 57 | 58 | script: 59 | - | 60 | travis-cargo build -- $FEATURES && 61 | travis-cargo test -- $FEATURES && 62 | travis-cargo bench -- $FEATURES 63 | 64 | after_success: 65 | - | 66 | if [ -z "$FEATURES" ]; then travis-cargo --only stable doc; travis-cargo --only stable doc-upload; fi 67 | wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && 68 | tar xzf master.tar.gz && 69 | cd kcov-master && 70 | mkdir build && 71 | cd build && 72 | cmake .. && 73 | make && 74 | sudo make install && 75 | cd ../.. && 76 | rm -rf kcov-master && 77 | RUSTFLAGS='-C link-dead-code' cargo test $FEATURES --no-run && 78 | for file in target/debug/v8-* 79 | do 80 | kcov --exclude-pattern=/.cargo,/usr/lib --verify "target/cov" "$file" 81 | done && 82 | bash <(curl -s https://codecov.io/bash) && 83 | echo "Uploaded code coverage" 84 | -------------------------------------------------------------------------------- /src/context.rs: -------------------------------------------------------------------------------- 1 | //! Execution contexts and sandboxing. 2 | use v8_sys as v8; 3 | use isolate; 4 | use util; 5 | use value; 6 | 7 | /// A sandboxed execution context with its own set of built-in objects and functions. 8 | #[derive(Debug)] 9 | pub struct Context(isolate::Isolate, v8::ContextRef); 10 | 11 | /// A guard that keeps a context bound while it is in scope. 12 | #[must_use] 13 | pub struct ContextGuard<'a>(&'a Context); 14 | 15 | impl Context { 16 | /// Creates a new context and returns a handle to the newly allocated context. 17 | pub fn new(isolate: &isolate::Isolate) -> Context { 18 | unsafe { 19 | Context(isolate.clone(), 20 | util::invoke(isolate, |c| v8::v8_Context_New(c)).unwrap()) 21 | } 22 | } 23 | 24 | /// Binds the context to the current scope. 25 | /// 26 | /// Within this scope, functionality that relies on implicit contexts will work. 27 | pub fn make_current(&self) -> ContextGuard { 28 | self.enter(); 29 | ContextGuard(self) 30 | } 31 | 32 | fn enter(&self) { 33 | unsafe { util::invoke(&self.0, |c| v8::v8_Context_Enter(c, self.1)).unwrap() } 34 | } 35 | 36 | fn exit(&self) { 37 | unsafe { util::invoke(&self.0, |c| v8::v8_Context_Exit(c, self.1)).unwrap() } 38 | } 39 | 40 | /// Returns the global proxy object. 41 | /// 42 | /// Global proxy object is a thin wrapper whose prototype points to actual context's global 43 | /// object with the properties like Object, etc. This is done that way for security reasons (for 44 | /// more details see https://wiki.mozilla.org/Gecko:SplitWindow). 45 | /// 46 | /// Please note that changes to global proxy object prototype most probably would break VM---v8 47 | /// expects only global object as a prototype of global proxy object. 48 | /// 49 | pub fn global(&self) -> value::Object { 50 | unsafe { 51 | value::Object::from_raw(&self.0, 52 | util::invoke(&self.0, |c| v8::v8_Context_Global(c, self.1)) 53 | .unwrap()) 54 | } 55 | } 56 | 57 | /// Creates a context from a set of raw pointers. 58 | pub unsafe fn from_raw(isolate: &isolate::Isolate, raw: v8::ContextRef) -> Context { 59 | Context(isolate.clone(), raw) 60 | } 61 | 62 | /// Returns the underlying raw pointer behind this context. 63 | pub fn as_raw(&self) -> v8::ContextRef { 64 | self.1 65 | } 66 | } 67 | 68 | reference!(Context, v8::v8_Context_CloneRef, v8::v8_Context_DestroyRef); 69 | 70 | impl<'a> Drop for ContextGuard<'a> { 71 | fn drop(&mut self) { 72 | self.0.exit() 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/script.rs: -------------------------------------------------------------------------------- 1 | //! Script and source code compilation, execution, origins and management. 2 | use v8_sys as v8; 3 | 4 | use context; 5 | use error; 6 | use isolate; 7 | use value; 8 | use util; 9 | 10 | /// A compiled JavaScript script, tied to a Context which was active when the script was compiled. 11 | #[derive(Debug)] 12 | pub struct Script(isolate::Isolate, v8::ScriptRef); 13 | 14 | impl Script { 15 | /// Compiles the specified source code into a compiled script. 16 | pub fn compile(isolate: &isolate::Isolate, 17 | context: &context::Context, 18 | source: &value::String) 19 | -> error::Result