mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-21 15:04:33 -05:00
Basic Local<String> support (#27)
This commit is contained in:
parent
cec2467245
commit
d91f0269fa
13 changed files with 209 additions and 6 deletions
3
BUILD.gn
3
BUILD.gn
|
@ -10,10 +10,11 @@ v8_static_library("rusty_v8") {
|
|||
"src/inspector/client.cc",
|
||||
"src/isolate.cc",
|
||||
"src/locker.cc",
|
||||
"src/number.cc",
|
||||
"src/platform/mod.cc",
|
||||
"src/platform/task.cc",
|
||||
"src/string.cc",
|
||||
"src/string_buffer.cc",
|
||||
"src/value.cc",
|
||||
]
|
||||
deps = [
|
||||
":v8",
|
||||
|
|
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -20,6 +20,11 @@ dependencies = [
|
|||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cargo_gn"
|
||||
version = "0.0.13"
|
||||
|
@ -62,6 +67,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "rusty_v8"
|
||||
version = "0.0.7"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cargo_gn 0.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -80,6 +86,7 @@ dependencies = [
|
|||
[metadata]
|
||||
"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
|
||||
"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum cargo_gn 0.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "0a679c108cad6ee19a25f4dbaf1b4e1fadf303e707fa1e2d060b4c169faeb836"
|
||||
"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
|
|
@ -50,6 +50,7 @@ exclude = [
|
|||
[dependencies]
|
||||
lazy_static = "1.4.0"
|
||||
libc = "0.2.65"
|
||||
bitflags = "1.2.1"
|
||||
|
||||
[build-dependencies]
|
||||
cargo_gn = "0.0.13"
|
||||
|
|
|
@ -55,4 +55,4 @@ void v8_inspector__V8Inspector__Channel__flushProtocolNotifications(
|
|||
V8Inspector::Channel& self) {
|
||||
self.flushProtocolNotifications();
|
||||
}
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
|
|
|
@ -51,4 +51,4 @@ void v8_inspector__V8InspectorClient__runIfWaitingForDebugger(
|
|||
int contextGroupId) {
|
||||
self.runIfWaitingForDebugger(contextGroupId);
|
||||
}
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#![allow(clippy::new_without_default)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate libc;
|
||||
|
@ -14,13 +16,14 @@ mod inspector;
|
|||
mod isolate;
|
||||
mod local;
|
||||
mod locker;
|
||||
mod number;
|
||||
mod string_buffer;
|
||||
mod string_view;
|
||||
mod support;
|
||||
mod value;
|
||||
|
||||
pub mod array_buffer;
|
||||
pub mod platform;
|
||||
pub mod string;
|
||||
// This module is intentionally named "V8" rather than "v8" to match the
|
||||
// C++ namespace "v8::V8".
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -30,6 +33,7 @@ pub use handle_scope::HandleScope;
|
|||
pub use isolate::Isolate;
|
||||
pub use local::Local;
|
||||
pub use locker::Locker;
|
||||
pub use number::{Integer, Number};
|
||||
pub use string::String;
|
||||
pub use string_buffer::StringBuffer;
|
||||
pub use string_view::StringView;
|
||||
pub use value::{Integer, Number};
|
||||
|
|
29
src/string.cc
Normal file
29
src/string.cc
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <cstdint>
|
||||
|
||||
#include "support.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
using namespace v8;
|
||||
using namespace support;
|
||||
|
||||
extern "C" {
|
||||
String* v8__String__NewFromUtf8(Isolate* isolate,
|
||||
const char* data,
|
||||
NewStringType type,
|
||||
int length) {
|
||||
return maybe_local_ptr(String::NewFromUtf8(isolate, data, type, length));
|
||||
}
|
||||
|
||||
int v8__String__Utf8Length(const String& self, Isolate* isolate) {
|
||||
return self.Utf8Length(isolate);
|
||||
}
|
||||
|
||||
int v8__String__WriteUtf8(const String& self,
|
||||
Isolate* isolate,
|
||||
char* buffer,
|
||||
int length,
|
||||
int* nchars_ref,
|
||||
int options) {
|
||||
return self.WriteUtf8(isolate, buffer, length, nchars_ref, options);
|
||||
}
|
||||
}
|
135
src/string.rs
Normal file
135
src/string.rs
Normal file
|
@ -0,0 +1,135 @@
|
|||
use std::convert::TryInto;
|
||||
use std::default::Default;
|
||||
use std::mem::forget;
|
||||
use std::slice;
|
||||
|
||||
use crate::isolate::CxxIsolate;
|
||||
use crate::isolate::LockedIsolate;
|
||||
use crate::support::char;
|
||||
use crate::support::int;
|
||||
use crate::support::Opaque;
|
||||
use crate::HandleScope;
|
||||
use crate::Local;
|
||||
|
||||
extern "C" {
|
||||
fn v8__String__NewFromUtf8(
|
||||
isolate: *mut CxxIsolate,
|
||||
data: *const char,
|
||||
new_type: NewStringType,
|
||||
length: int,
|
||||
) -> *const String;
|
||||
|
||||
fn v8__String__Utf8Length(this: &String, isolate: *mut CxxIsolate) -> int;
|
||||
|
||||
fn v8__String__WriteUtf8(
|
||||
this: &String,
|
||||
isolate: *mut CxxIsolate,
|
||||
buffer: *mut char,
|
||||
length: int,
|
||||
nchars_ref: *mut int,
|
||||
options: WriteOptions,
|
||||
) -> int;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub enum NewStringType {
|
||||
Normal,
|
||||
Internalized,
|
||||
}
|
||||
|
||||
impl Default for NewStringType {
|
||||
fn default() -> Self {
|
||||
NewStringType::Normal
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct WriteOptions: int {
|
||||
const NO_OPTIONS = 0;
|
||||
const HINT_MANY_WRITES_EXPECTED = 1;
|
||||
const NO_NULL_TERMINATION = 2;
|
||||
const PRESERVE_ONE_BYTE_NULL = 4;
|
||||
// Used by WriteUtf8 to replace orphan surrogate code units with the
|
||||
// unicode replacement character. Needs to be set to guarantee valid UTF-8
|
||||
// output.
|
||||
const REPLACE_INVALID_UTF8 = 8;
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct String(Opaque);
|
||||
|
||||
impl String {
|
||||
pub fn new_from_utf8<'sc>(
|
||||
scope: &mut HandleScope<'sc>,
|
||||
buffer: &[u8],
|
||||
new_type: NewStringType,
|
||||
) -> Option<Local<'sc, String>> {
|
||||
unsafe {
|
||||
let ptr = v8__String__NewFromUtf8(
|
||||
scope.cxx_isolate(),
|
||||
buffer.as_ptr() as *const char,
|
||||
new_type,
|
||||
buffer.len().try_into().ok()?,
|
||||
);
|
||||
Local::from_raw(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn utf8_length(&self, isolate: &mut impl LockedIsolate) -> usize {
|
||||
unsafe { v8__String__Utf8Length(self, isolate.cxx_isolate()) as usize }
|
||||
}
|
||||
|
||||
pub fn write_utf8(
|
||||
&self,
|
||||
isolate: &mut impl LockedIsolate,
|
||||
buffer: &mut [u8],
|
||||
nchars_ref: Option<&mut usize>,
|
||||
options: WriteOptions,
|
||||
) -> usize {
|
||||
let mut nchars_ref_int: int = 0;
|
||||
let bytes = unsafe {
|
||||
v8__String__WriteUtf8(
|
||||
self,
|
||||
isolate.cxx_isolate(),
|
||||
buffer.as_mut_ptr() as *mut char,
|
||||
buffer.len().try_into().unwrap_or(int::max_value()),
|
||||
&mut nchars_ref_int,
|
||||
options,
|
||||
)
|
||||
};
|
||||
if let Some(r) = nchars_ref {
|
||||
*r = nchars_ref_int as usize;
|
||||
}
|
||||
bytes as usize
|
||||
}
|
||||
|
||||
// Convenience function not present in the original V8 API.
|
||||
pub fn new<'sc>(
|
||||
scope: &mut HandleScope<'sc>,
|
||||
value: &str,
|
||||
new_type: NewStringType,
|
||||
) -> Option<Local<'sc, String>> {
|
||||
Self::new_from_utf8(scope, value.as_ref(), new_type)
|
||||
}
|
||||
|
||||
// Convenience function not present in the original V8 API.
|
||||
pub fn to_rust_string_lossy(
|
||||
&self,
|
||||
isolate: &mut impl LockedIsolate,
|
||||
) -> std::string::String {
|
||||
let capacity = self.utf8_length(isolate);
|
||||
let mut string = std::string::String::with_capacity(capacity);
|
||||
let data = string.as_mut_ptr();
|
||||
forget(string);
|
||||
let length = self.write_utf8(
|
||||
isolate,
|
||||
unsafe { slice::from_raw_parts_mut(data, capacity) },
|
||||
None,
|
||||
WriteOptions::NO_NULL_TERMINATION | WriteOptions::REPLACE_INVALID_UTF8,
|
||||
);
|
||||
unsafe { std::string::String::from_raw_parts(data, length, capacity) }
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
// Check assumptions made in binding code.
|
||||
// TODO(ry) re-enable the following
|
||||
// static_assert(sizeof(bool) == sizeof(uint8_t));
|
||||
|
@ -33,4 +35,9 @@ void construct_in_place(uninit_t<T>& buf, Args... args) {
|
|||
}
|
||||
} // namespace support
|
||||
|
||||
#endif // SUPPORT_H_
|
||||
template <class T>
|
||||
inline static T* maybe_local_ptr(v8::MaybeLocal<T> value) {
|
||||
return *value.FromMaybe(v8::Local<T>());
|
||||
}
|
||||
|
||||
#endif // SUPPORT_H_
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::ops::Deref;
|
|||
use std::ops::DerefMut;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
pub use std::os::raw::c_char as char;
|
||||
pub use std::os::raw::c_int as int;
|
||||
|
||||
pub type Opaque = [usize; 0];
|
||||
|
|
|
@ -76,6 +76,24 @@ fn handle_scope_numbers() {
|
|||
drop(g);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string() {
|
||||
setup();
|
||||
let mut params = v8::Isolate::create_params();
|
||||
params.set_array_buffer_allocator(
|
||||
v8::array_buffer::Allocator::new_default_allocator(),
|
||||
);
|
||||
let mut isolate = v8::Isolate::new(params);
|
||||
let mut locker = v8::Locker::new(&mut isolate);
|
||||
v8::HandleScope::enter(&mut locker, |scope| {
|
||||
let reference = "Hello 🦕 world!";
|
||||
let local =
|
||||
v8::String::new(scope, reference, v8::string::NewStringType::Normal)
|
||||
.unwrap();
|
||||
assert_eq!(reference, local.to_rust_string_lossy(scope));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn isolate_new() {
|
||||
let g = setup();
|
||||
|
|
Loading…
Reference in a new issue